18b3be6f68b2ae9b7f2b25893aad30c67f79663e
[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 #if defined(_MSC_VER)
38         #include "pstdint.h"
39 #else
40         #include <stdint.h>
41 #endif
42 #include "SDCCglobl.h"
43 #include "newalloc.h" 
44
45 #include "common.h"
46 #include "SDCCpeeph.h"
47 #include "ralloc.h"
48 #include "pcode.h"
49 #include "gen.h"
50
51 /* When changing these, you must also update the assembler template
52  * in device/lib/libsdcc/macros.inc */
53 #define GPTRTAG_DATA    0x00
54 #define GPTRTAG_CODE    0x80
55
56 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
57 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
58 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
59
60 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
61 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
62 void genMult8X8_8 (operand *, operand *,operand *);
63 extern void printpBlock(FILE *of, pBlock *pb);
64
65 static int labelOffset=0;
66 extern int debug_verbose;
67 extern int pic14_hasInterrupt;
68 //static int optimized_for_speed = 0;
69
70 /* max_key keeps track of the largest label number used in 
71 a function. This is then used to adjust the label offset
72 for the next function.
73 */
74 static int max_key=0;
75 static int GpsuedoStkPtr=0;
76
77 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
78 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
79 unsigned int pic14aopLiteral (value *val, int offset);
80 const char *AopType(short type);
81
82 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
83
84 /* this is the down and dirty file with all kinds of 
85 kludgy & hacky stuff. This is what it is all about
86 CODE GENERATION for a specific MCU . some of the
87 routines may be reusable, will have to see */
88
89 static char *zero = "#0x00";
90 static char *one  = "#0x01";
91 static char *spname = "sp";
92
93 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
94 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
95 static char **fReturn = fReturnpic14;
96
97 //static char *accUse[] = {"a","b"};
98
99 //static short rbank = -1;
100
101 static struct {
102         short r0Pushed;
103         short r1Pushed;
104         short accInUse;
105         short inLine;
106         short debugLine;
107         short nRegsSaved;
108         set *sendSet;
109 } _G;
110
111 /* Resolved ifx structure. This structure stores information
112 about an iCode ifx that makes it easier to generate code.
113 */
114 typedef struct resolvedIfx {
115         symbol *lbl;     /* pointer to a label */
116         int condition;   /* true or false ifx */
117         int generated;   /* set true when the code associated with the ifx
118                           * is generated */
119 } resolvedIfx;
120
121 extern int pic14_ptrRegReq ;
122 extern int pic14_nRegs;
123 extern FILE *codeOutFile;
124 static void saverbank (int, iCode *,bool);
125
126 static lineNode *lineHead = NULL;
127 static lineNode *lineCurr = NULL;
128
129 #if 0
130 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
131 0xE0, 0xC0, 0x80, 0x00};
132 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
133 0x07, 0x03, 0x01, 0x00};
134 #endif
135
136 static  pBlock *pb;
137
138 /*-----------------------------------------------------------------*/
139 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
140 /*                                 exponent of 2 is returned, otherwise -1 is      */
141 /*                                 returned.                                                                       */
142 /* note that this is similar to the function `powof2' in SDCCsymt  */
143 /* if(n == 2^y)                                                                                                    */
144 /*       return y;                                                                                                         */
145 /* return -1;                                                                                                      */
146 /*-----------------------------------------------------------------*/
147 static int my_powof2 (unsigned long num)
148 {
149         if(num) {
150                 if( (num & (num-1)) == 0) {
151                         int nshifts = -1;
152                         while(num) {
153                                 num>>=1;
154                                 nshifts++;
155                         }
156                         return nshifts;
157                 }
158         }
159         
160         return -1;
161 }
162
163 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
164 {
165         
166         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
167                 line_no,
168                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
169                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
170                 ((result) ? AOP_SIZE(result) : 0),
171                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
172                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
173                 ((left)   ? AOP_SIZE(left) : 0),
174                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
175                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
176                 ((right)  ? AOP_SIZE(right) : 0));
177         
178 }
179
180 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
181 {
182         
183         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
184                 line_no,
185                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
186                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
187                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
188                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
189                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
190                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
191         
192 }
193
194 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
195 {
196         va_list ap;
197         char lb[INITIAL_INLINEASM];  
198         unsigned char *lbp = (unsigned char *)lb;
199         
200         if(!debug_verbose && !options.debug)
201                 return;
202         
203         va_start(ap,fmt);   
204         
205         if (inst && *inst) {
206                 if (fmt && *fmt)
207                         sprintf(lb,"%s\t",inst);
208                 else
209                         sprintf(lb,"%s",inst);
210                 vsprintf(lb+(strlen(lb)),fmt,ap);
211         }  else
212                 vsprintf(lb,fmt,ap);
213         
214         while (isspace(*lbp)) lbp++;
215         
216         if (lbp && *lbp) 
217                 lineCurr = (lineCurr ?
218                 connectLine(lineCurr,newLineNode(lb)) :
219         (lineHead = newLineNode(lb)));
220         lineCurr->isInline = _G.inLine;
221         lineCurr->isDebug  = _G.debugLine;
222         
223         addpCode2pBlock(pb,newpCodeCharP(lb));
224         
225         va_end(ap);
226 }
227
228 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
229 {
230 #if defined (HAVE_VSNPRINTF)
231   vsnprintf (buf, size, fmt, ap);
232 #elif defined (HAVE_VSPRINTF)
233   vsprintf (buf, size, fmt, ap);
234   if (strlen (buf) >= size)
235   {
236     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
237   }
238 #elif defined (HAVE_SNPRINTF)
239   snprintf (buf, size, "vs(n)printf required");
240 #elif defined (HAVE_SRINTF)
241   sprintf (buf, "vs(n)printf required");
242   if (strlen (buf) >= size)
243   {
244     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
245   }
246 #else
247   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
248 #endif
249 }
250
251 void emitpComment (const char *fmt, ...)
252 {
253   va_list va;
254   char buffer[4096];
255   
256   va_start (va, fmt);
257   if (pb) {
258     Safe_vsnprintf (buffer, 4096, fmt, va);
259     //fprintf (stderr, "%s\n" ,buffer);
260     addpCode2pBlock (pb, newpCodeCharP (buffer));
261 #if 0
262   } else {
263     Safe_vsnprintf (buffer, 4096, fmt, va);
264     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
265 #endif
266   }
267   va_end (va);
268 }
269
270 void emitpLabel(int key)
271 {
272         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
273 }
274
275 /* gen.h defines a macro emitpcode that should be used to call emitpcode
276  * as this allows for easy debugging (ever asked the question: where was
277  * this instruction geenrated? Here is the answer... */
278 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
279 {
280         if(pcop)
281                 addpCode2pBlock(pb,newpCode(poc,pcop));
282         else
283                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
284 }
285
286 void emitpcodeNULLop(PIC_OPCODE poc)
287 {
288         
289         addpCode2pBlock(pb,newpCode(poc,NULL));
290         
291 }
292
293
294 /*-----------------------------------------------------------------*/
295 /* pic14_emitcode - writes the code into a file : for now it is simple    */
296 /*-----------------------------------------------------------------*/
297 void pic14_emitcode (char *inst,char *fmt, ...)
298 {
299         va_list ap;
300         char lb[INITIAL_INLINEASM];  
301         unsigned char *lbp = (unsigned char *)lb;
302         
303         va_start(ap,fmt);   
304         
305         if (inst && *inst) {
306                 if (fmt && *fmt)
307                         sprintf(lb,"%s\t",inst);
308                 else
309                         sprintf(lb,"%s",inst);
310                 vsprintf(lb+(strlen(lb)),fmt,ap);
311         }  else
312                 vsprintf(lb,fmt,ap);
313         
314         while (isspace(*lbp)) lbp++;
315         
316         if (lbp && *lbp) 
317                 lineCurr = (lineCurr ?
318                 connectLine(lineCurr,newLineNode(lb)) :
319         (lineHead = newLineNode(lb)));
320         lineCurr->isInline = _G.inLine;
321         lineCurr->isDebug  = _G.debugLine;
322         
323         if(debug_verbose)
324                 addpCode2pBlock(pb,newpCodeCharP(lb));
325         
326         va_end(ap);
327 }
328
329 /*-----------------------------------------------------------------*/
330 /* pic14_emitDebuggerSymbol - associate the current code location  */
331 /*       with a debugger symbol                                                                            */
332 /*-----------------------------------------------------------------*/
333 void
334 pic14_emitDebuggerSymbol (char * debugSym)
335 {
336         _G.debugLine = 1;
337         pic14_emitcode ("", ";%s ==.", debugSym);
338         _G.debugLine = 0;
339 }
340
341 #if 0
342 /*-----------------------------------------------------------------*/
343 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
344 /*-----------------------------------------------------------------*/
345 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
346 {
347         bool r0iu = FALSE , r1iu = FALSE;
348         bool r0ou = FALSE , r1ou = FALSE;
349         
350         /* the logic: if r0 & r1 used in the instruction
351         then we are in trouble otherwise */
352         
353         /* first check if r0 & r1 are used by this
354         instruction, in which case we are in trouble */
355         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
356                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
357         {
358                 goto endOfWorld;          
359         }
360         
361         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
362         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
363         
364         /* if no usage of r0 then return it */
365         if (!r0iu && !r0ou) {
366                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
367                 (*aopp)->type = AOP_R0;
368                 
369                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
370         }
371         
372         /* if no usage of r1 then return it */
373         if (!r1iu && !r1ou) {
374                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
375                 (*aopp)->type = AOP_R1;
376                 
377                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
378         }    
379         
380         /* now we know they both have usage */
381         /* if r0 not used in this instruction */
382         if (!r0iu) {
383                 /* push it if not already pushed */
384                 if (!_G.r0Pushed) {
385                         //pic14_emitcode ("push","%s",
386                         //                pic14_regWithIdx(R0_IDX)->dname);
387                         _G.r0Pushed++ ;
388                 }
389                 
390                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
391                 (*aopp)->type = AOP_R0;
392                 
393                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
394         }
395         
396         /* if r1 not used then */
397         
398         if (!r1iu) {
399                 /* push it if not already pushed */
400                 if (!_G.r1Pushed) {
401                         //pic14_emitcode ("push","%s",
402                         //                pic14_regWithIdx(R1_IDX)->dname);
403                         _G.r1Pushed++ ;
404                 }
405                 
406                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
407                 (*aopp)->type = AOP_R1;
408                 return pic14_regWithIdx(R1_IDX);
409         }
410         
411 endOfWorld :
412         /* I said end of world but not quite end of world yet */
413         /* if this is a result then we can push it on the stack*/
414         if (result) {
415                 (*aopp)->type = AOP_STK;        
416                 return NULL;
417         }
418         
419         /* other wise this is true end of the world */
420         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
421                 "getFreePtr should never reach here");
422         exit(0);
423 }
424 #endif
425
426 /*-----------------------------------------------------------------*/
427 /* newAsmop - creates a new asmOp                                                                  */
428 /*-----------------------------------------------------------------*/
429 asmop *newAsmop (short type)
430 {
431         asmop *aop;
432         
433         aop = Safe_calloc(1,sizeof(asmop));
434         aop->type = type;
435         return aop;
436 }
437
438 static void genSetDPTR(int n)
439 {
440         if (!n)
441         {
442                 pic14_emitcode(";", "Select standard DPTR");
443                 pic14_emitcode("mov", "dps, #0x00");
444         }
445         else
446         {
447                 pic14_emitcode(";", "Select alternate DPTR");
448                 pic14_emitcode("mov", "dps, #0x01");
449         }
450 }
451
452 /*-----------------------------------------------------------------*/
453 /* resolveIfx - converts an iCode ifx into a form more useful for  */
454 /*                              generating code                                                                    */
455 /*-----------------------------------------------------------------*/
456 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
457 {
458         if(!resIfx) 
459                 return;
460         
461         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
462         
463         resIfx->condition = 1;  /* assume that the ifx is true */
464         resIfx->generated = 0;  /* indicate that the ifx has not been used */
465         
466         if(!ifx) {
467                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
468                                                                                         /*
469                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
470                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
471                 */
472         } else {
473                 if(IC_TRUE(ifx)) {
474                         resIfx->lbl = IC_TRUE(ifx);
475                 } else {
476                         resIfx->lbl = IC_FALSE(ifx);
477                         resIfx->condition = 0;
478                 }
479                 /*
480                 if(IC_TRUE(ifx)) 
481                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
482                 if(IC_FALSE(ifx)) 
483                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
484                 */
485         }
486         
487         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
488         
489 }
490 /*-----------------------------------------------------------------*/
491 /* pointerCode - returns the code for a pointer type                       */
492 /*-----------------------------------------------------------------*/
493 #if 0
494 static int pointerCode (sym_link *etype)
495 {
496         
497         return PTR_TYPE(SPEC_OCLS(etype));
498         
499 }
500 #endif
501
502 /*-----------------------------------------------------------------*/
503 /* aopForSym - for a true symbol                                                                   */
504 /*-----------------------------------------------------------------*/
505 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
506 {
507         asmop *aop;
508         memmap *space= SPEC_OCLS(sym->etype);
509         
510         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
511         /* if already has one */
512         if (sym->aop)
513                 return sym->aop;
514         
515 #if 0
516         /* assign depending on the storage class */
517         /* if it is on the stack or indirectly addressable */
518         /* space we need to assign either r0 or r1 to it         */    
519         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
520                 sym->aop = aop = newAsmop(0);
521                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
522                 aop->size = getSize(sym->type);
523                 
524                 /* now assign the address of the variable to 
525                 the pointer register */
526                 if (aop->type != AOP_STK) {
527                         
528                         if (sym->onStack) {
529                                 if ( _G.accInUse )
530                                         pic14_emitcode("push","acc");
531                                 
532                                 pic14_emitcode("mov","a,_bp");
533                                 pic14_emitcode("add","a,#0x%02x",
534                                         ((sym->stack < 0) ?
535                                         ((char)(sym->stack - _G.nRegsSaved )) :
536                                 ((char)sym->stack)) & 0xff);
537                                 pic14_emitcode("mov","%s,a",
538                                         aop->aopu.aop_ptr->name);
539                                 
540                                 if ( _G.accInUse )
541                                         pic14_emitcode("pop","acc");
542                         } else
543                                 pic14_emitcode("mov","%s,#%s",
544                                 aop->aopu.aop_ptr->name,
545                                 sym->rname);
546                         aop->paged = space->paged;
547                 } else
548                         aop->aopu.aop_stk = sym->stack;
549                 return aop;
550         }
551         
552         if (sym->onStack && options.stack10bit)
553         {
554                 /* It's on the 10 bit stack, which is located in
555                 * far data space.
556                 */
557                 
558                 //DEBUGpic14_emitcode(";","%d",__LINE__);
559                 
560                 if ( _G.accInUse )
561                         pic14_emitcode("push","acc");
562                 
563                 pic14_emitcode("mov","a,_bp");
564                 pic14_emitcode("add","a,#0x%02x",
565                         ((sym->stack < 0) ?
566                         ((char)(sym->stack - _G.nRegsSaved )) :
567                 ((char)sym->stack)) & 0xff);
568                 
569                 genSetDPTR(1);
570                 pic14_emitcode ("mov","dpx1,#0x40");
571                 pic14_emitcode ("mov","dph1,#0x00");
572                 pic14_emitcode ("mov","dpl1, a");
573                 genSetDPTR(0);
574                 
575                 if ( _G.accInUse )
576                         pic14_emitcode("pop","acc");
577                 
578                 sym->aop = aop = newAsmop(AOP_DPTR2);
579                 aop->size = getSize(sym->type); 
580                 return aop;
581         }
582 #endif
583
584         //DEBUGpic14_emitcode(";","%d",__LINE__);
585         /* if in bit space */
586         if (IN_BITSPACE(space)) {
587                 sym->aop = aop = newAsmop (AOP_CRY);
588                 aop->aopu.aop_dir = sym->rname ;
589                 aop->size = getSize(sym->type);
590                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
591                 return aop;
592         }
593         /* if it is in direct space */
594         if (IN_DIRSPACE(space)) {
595                 sym->aop = aop = newAsmop (AOP_DIR);
596                 aop->aopu.aop_dir = sym->rname ;
597                 aop->size = getSize(sym->type);
598                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
599                 return aop;
600         }
601         
602         /* special case for a function */
603         if (IS_FUNC(sym->type)) {   
604                 
605                 sym->aop = aop = newAsmop(AOP_PCODE);
606                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
607                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
608                 PCOI(aop->aopu.pcop)->_function = 1;
609                 PCOI(aop->aopu.pcop)->index = 0;
610                 aop->size = FPTRSIZE; 
611                 /*
612                 sym->aop = aop = newAsmop(AOP_IMMD);    
613                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
614                 strcpy(aop->aopu.aop_immd,sym->rname);
615                 aop->size = FPTRSIZE; 
616                 */
617                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
618                 return aop;
619         }
620         
621         if (IS_ARRAY(sym->type)) {
622                 sym->aop = aop = newAsmop(AOP_PCODE);
623                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
624                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
625                 PCOI(aop->aopu.pcop)->_function = 0;
626                 PCOI(aop->aopu.pcop)->index = 0;
627                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
628                 
629                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
630                 return aop;
631         }
632         
633         /* only remaining is far space */
634         /* in which case DPTR gets the address */
635         sym->aop = aop = newAsmop(AOP_PCODE);
636         
637         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
638         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
639         PCOI(aop->aopu.pcop)->index = 0;
640         
641         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
642                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
643         
644         allocDirReg (IC_LEFT(ic));
645         
646         aop->size = FPTRSIZE;
647         /*
648         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
649         sym->aop = aop = newAsmop(AOP_DPTR);
650         pic14_emitcode ("mov","dptr,#%s", sym->rname);
651         aop->size = getSize(sym->type);
652         
653           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
654         */
655         
656         /* if it is in code space */
657         if (IN_CODESPACE(space))
658                 aop->code = 1;
659         
660         return aop;       
661 }
662
663 /*-----------------------------------------------------------------*/
664 /* aopForRemat - rematerialzes an object                                                   */
665 /*-----------------------------------------------------------------*/
666 static asmop *aopForRemat (operand *op) // x symbol *sym)
667 {
668         symbol *sym = OP_SYMBOL(op);
669         iCode *ic = NULL;
670         asmop *aop = newAsmop(AOP_PCODE);
671         int val = 0;
672         int offset = 0;
673         
674         ic = sym->rematiCode;
675
676         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
677         if(IS_OP_POINTER(op)) {
678                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
679         }
680         for (;;) {
681                 if (ic->op == '+') {
682                         val += (int) operandLitValue(IC_RIGHT(ic));
683                 } else if (ic->op == '-') {
684                         val -= (int) operandLitValue(IC_RIGHT(ic));
685                 } else
686                         break;
687                 
688                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
689         }
690         
691         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
692         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
693         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
694         PCOI(aop->aopu.pcop)->index = val;
695         
696         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
697                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
698                 val, IS_PTR_CONST(operandType(op)));
699         
700         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
701         
702         allocDirReg (IC_LEFT(ic));
703         
704         return aop;              
705 }
706
707 int aopIdx (asmop *aop, int offset)
708 {
709         if(!aop)
710                 return -1;
711         
712         if(aop->type !=  AOP_REG)
713                 return -2;
714         
715         return aop->aopu.aop_reg[offset]->rIdx;
716         
717 }
718 /*-----------------------------------------------------------------*/
719 /* regsInCommon - two operands have some registers in common       */
720 /*-----------------------------------------------------------------*/
721 static bool regsInCommon (operand *op1, operand *op2)
722 {
723         symbol *sym1, *sym2;
724         int i;
725         
726         /* if they have registers in common */
727         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
728                 return FALSE ;
729         
730         sym1 = OP_SYMBOL(op1);
731         sym2 = OP_SYMBOL(op2);
732         
733         if (sym1->nRegs == 0 || sym2->nRegs == 0)
734                 return FALSE ;
735         
736         for (i = 0 ; i < sym1->nRegs ; i++) {
737                 int j;
738                 if (!sym1->regs[i])
739                         continue ;
740                 
741                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
742                         if (!sym2->regs[j])
743                                 continue ;
744                         
745                         if (sym2->regs[j] == sym1->regs[i])
746                                 return TRUE ;
747                 }
748         }
749         
750         return FALSE ;
751 }
752
753 /*-----------------------------------------------------------------*/
754 /* operandsEqu - equivalent                                                                        */
755 /*-----------------------------------------------------------------*/
756 static bool operandsEqu ( operand *op1, operand *op2)
757 {
758         symbol *sym1, *sym2;
759         
760         /* if they not symbols */
761         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
762                 return FALSE;
763         
764         sym1 = OP_SYMBOL(op1);
765         sym2 = OP_SYMBOL(op2);
766         
767         /* if both are itemps & one is spilt
768         and the other is not then false */
769         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
770                 sym1->isspilt != sym2->isspilt )
771                 return FALSE ;
772         
773         /* if they are the same */
774         if (sym1 == sym2)
775                 return TRUE ;
776         
777         if (sym1->rname[0] && sym2->rname[0]
778                 && strcmp (sym1->rname, sym2->rname) == 0)
779                 return TRUE;
780         
781         
782         /* if left is a tmp & right is not */
783         if (IS_ITEMP(op1)  && 
784                 !IS_ITEMP(op2) &&
785                 sym1->isspilt  &&
786                 (sym1->usl.spillLoc == sym2))
787                 return TRUE;
788         
789         if (IS_ITEMP(op2)  && 
790                 !IS_ITEMP(op1) &&
791                 sym2->isspilt  &&
792                 sym1->level > 0 &&
793                 (sym2->usl.spillLoc == sym1))
794                 return TRUE ;
795         
796         return FALSE ;
797 }
798
799 /*-----------------------------------------------------------------*/
800 /* pic14_sameRegs - two asmops have the same registers             */
801 /*-----------------------------------------------------------------*/
802 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
803 {
804         int i;
805         
806         if (aop1 == aop2)
807                 return TRUE ;
808         
809         if (aop1->type != AOP_REG ||
810                 aop2->type != AOP_REG )
811                 return FALSE ;
812         
813         if (aop1->size != aop2->size )
814                 return FALSE ;
815         
816         for (i = 0 ; i < aop1->size ; i++ )
817                 if (aop1->aopu.aop_reg[i] !=
818                         aop2->aopu.aop_reg[i] )
819                         return FALSE ;
820                 
821                 return TRUE ;
822 }
823
824 /*-----------------------------------------------------------------*/
825 /* aopOp - allocates an asmop for an operand  :                    */
826 /*-----------------------------------------------------------------*/
827 void aopOp (operand *op, iCode *ic, bool result)
828 {
829         asmop *aop;
830         symbol *sym;
831         int i;
832         
833         if (!op)
834                 return ;
835         
836         /* if this a literal */
837         if (IS_OP_LITERAL(op)) {
838                 op->aop = aop = newAsmop(AOP_LIT);
839                 aop->aopu.aop_lit = op->operand.valOperand;
840                 aop->size = getSize(operandType(op));
841                 return;
842         }
843         
844         {
845                 sym_link *type = operandType(op);
846                 if(IS_PTR_CONST(type))
847                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
848         }
849         
850         /* if already has a asmop then continue */
851         if (op->aop)
852                 return ;
853         
854         /* if the underlying symbol has a aop */
855         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
856                 DEBUGpic14_emitcode(";","%d",__LINE__);
857                 op->aop = OP_SYMBOL(op)->aop;
858                 return;
859         }
860         
861         /* if this is a true symbol */
862         if (IS_TRUE_SYMOP(op)) {          
863                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
864                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
865                 return ;
866         }
867         
868         /* this is a temporary : this has
869         only four choices :
870         a) register
871         b) spillocation
872         c) rematerialize 
873         d) conditional   
874         e) can be a return use only */
875         
876         sym = OP_SYMBOL(op);
877         
878         
879         /* if the type is a conditional */
880         if (sym->regType == REG_CND) {
881                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
882                 aop->size = 0;
883                 return;
884         }
885         
886         /* if it is spilt then two situations
887         a) is rematerialize 
888         b) has a spill location */
889         if (sym->isspilt || sym->nRegs == 0) {
890                 
891                 DEBUGpic14_emitcode(";","%d",__LINE__);
892                 /* rematerialize it NOW */
893                 if (sym->remat) {
894                         
895                         sym->aop = op->aop = aop = aopForRemat (op);
896                         aop->size = getSize(sym->type);
897                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
898                         return;
899                 }
900                 
901 #if 0
902                 /* WREG is not usable as an ordinary operand with PIC architecture,
903                  * one might introduce a scratch register that can be used to make
904                  * WREG accesible as an operand... disable WREG for now */
905                 if (sym->accuse) {
906                         int i;
907                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
908                         aop->size = getSize(sym->type);
909                         for ( i = 0 ; i < 2 ; i++ )
910                                 aop->aopu.aop_str[i] = accUse[i];
911                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
912                         return;  
913                 }
914 #endif
915                 
916                 if (sym->ruonly ) {
917                         if(sym->isptr) {        // && sym->uptr 
918                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
919                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
920                                 
921                                 //PCOI(aop->aopu.pcop)->_const = 0;
922                                 //PCOI(aop->aopu.pcop)->index = 0;
923                                 /*
924                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
925                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
926                                 */
927                                 //allocDirReg (IC_LEFT(ic));
928                                 
929                                 aop->size = getSize(sym->type);
930                                 DEBUGpic14_emitcode(";","%d",__LINE__);
931                                 return;
932                                 
933                         } else {
934                                 
935                                 unsigned i;
936                                 
937                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
938                                 aop->size = getSize(sym->type);
939                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
940                                         aop->aopu.aop_str[i] = fReturn[i];
941                                 
942                                 DEBUGpic14_emitcode(";","%d",__LINE__);
943                                 return;
944                         }
945                 }
946                 
947                 /* else spill location  */
948                 if (sym->usl.spillLoc)
949                 {
950                         asmop *oldAsmOp = NULL;
951
952                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
953                         {
954                                 /* force a new aop if sizes differ */
955                                 oldAsmOp = sym->usl.spillLoc->aop;
956                                 sym->usl.spillLoc->aop = NULL;
957                         }
958                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
959                                 __FUNCTION__,__LINE__,
960                                 sym->usl.spillLoc->rname,
961                                 sym->rname, sym->usl.spillLoc->offset);
962                 
963                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
964                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
965                         {
966                                 /* Don't reuse the new aop, go with the last one */
967                                 sym->usl.spillLoc->aop = oldAsmOp;
968                         }
969                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
970                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
971                                 getSize(sym->type), 
972                                 sym->usl.spillLoc->offset);
973                         aop->size = getSize(sym->type);
974                 
975                         return;
976                 }
977         }
978         
979         {
980                 sym_link *type = operandType(op);
981                 if(IS_PTR_CONST(type)) 
982                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
983         }
984         
985         /* must be in a register */
986         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
987         sym->aop = op->aop = aop = newAsmop(AOP_REG);
988         aop->size = sym->nRegs;
989         for ( i = 0 ; i < sym->nRegs ;i++)
990                 aop->aopu.aop_reg[i] = sym->regs[i];
991 }
992
993 /*-----------------------------------------------------------------*/
994 /* freeAsmop - free up the asmop given to an operand                       */
995 /*----------------------------------------------------------------*/
996 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
997 {       
998         asmop *aop ;
999         
1000         if (!op)
1001                 aop = aaop;
1002         else 
1003                 aop = op->aop;
1004         
1005         if (!aop)
1006                 return ;
1007         
1008         if (aop->freed)
1009                 goto dealloc; 
1010         
1011         aop->freed = 1;
1012         
1013         /* depending on the asmop type only three cases need work AOP_RO
1014         , AOP_R1 && AOP_STK */
1015 #if 0
1016         switch (aop->type) {
1017         case AOP_R0 :
1018                 if (_G.r0Pushed ) {
1019                         if (pop) {
1020                                 pic14_emitcode ("pop","ar0");     
1021                                 _G.r0Pushed--;
1022                         }
1023                 }
1024                 bitVectUnSetBit(ic->rUsed,R0_IDX);
1025                 break;
1026                 
1027         case AOP_R1 :
1028                 if (_G.r1Pushed ) {
1029                         if (pop) {
1030                                 pic14_emitcode ("pop","ar1");
1031                                 _G.r1Pushed--;
1032                         }
1033                 }
1034                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
1035                 break;
1036                 
1037         case AOP_STK :
1038                 {
1039                         int sz = aop->size;      
1040                         int stk = aop->aopu.aop_stk + aop->size;
1041                         bitVectUnSetBit(ic->rUsed,R0_IDX);
1042                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
1043                         
1044                         getFreePtr(ic,&aop,FALSE);
1045                         
1046                         if (options.stack10bit)
1047                         {
1048                                 /* I'm not sure what to do here yet... */
1049                                 /* #STUB */
1050                                 fprintf(stderr, 
1051                                         "*** Warning: probably generating bad code for "
1052                                         "10 bit stack mode.\n");
1053                         }
1054                         
1055                         if (stk) {
1056                                 pic14_emitcode ("mov","a,_bp");
1057                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1058                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1059                         } else {
1060                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1061                         }
1062                         
1063                         while (sz--) {
1064                                 pic14_emitcode("pop","acc");
1065                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1066                                 if (!sz) break;
1067                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1068                         }
1069                         op->aop = aop;
1070                         freeAsmop(op,NULL,ic,TRUE);
1071                         if (_G.r0Pushed) {
1072                                 pic14_emitcode("pop","ar0");
1073                                 _G.r0Pushed--;
1074                         }
1075                         
1076                         if (_G.r1Pushed) {
1077                                 pic14_emitcode("pop","ar1");
1078                                 _G.r1Pushed--;
1079                         }         
1080                 }
1081         }
1082 #endif
1083         
1084 dealloc:
1085         /* all other cases just dealloc */
1086         if (op ) {
1087                 op->aop = NULL;
1088                 if (IS_SYMOP(op)) {
1089                         OP_SYMBOL(op)->aop = NULL;      
1090                         /* if the symbol has a spill */
1091                         if (SPIL_LOC(op))
1092                                 SPIL_LOC(op)->aop = NULL;
1093                 }
1094         }
1095 }
1096
1097 /*-----------------------------------------------------------------*/
1098 /* aopGet - for fetching value of the aop                                                  */
1099 /*-----------------------------------------------------------------*/
1100 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1101 {
1102         char *s = buffer ;
1103         char *rs;
1104         
1105         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1106         /* offset is greater than
1107         size then zero */
1108         if (offset > (aop->size - 1) &&
1109                 aop->type != AOP_LIT)
1110                 return zero;
1111         
1112         /* depending on type */
1113         switch (aop->type) {
1114                 
1115         case AOP_R0:
1116         case AOP_R1:
1117                 DEBUGpic14_emitcode(";","%d",__LINE__);
1118                 /* if we need to increment it */           
1119                 while (offset > aop->coff) {            
1120                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1121                         aop->coff++;
1122                 }
1123                 
1124                 while (offset < aop->coff) {
1125                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1126                         aop->coff--;
1127                 }
1128                 
1129                 aop->coff = offset ;
1130                 if (aop->paged) {
1131                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1132                         return (dname ? "acc" : "a");
1133                 }               
1134                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1135                 rs = Safe_calloc(1,strlen(s)+1);
1136                 strcpy(rs,s);   
1137                 return rs;
1138                 
1139         case AOP_DPTR:
1140         case AOP_DPTR2:
1141                 DEBUGpic14_emitcode(";","%d",__LINE__);
1142                 if (aop->type == AOP_DPTR2)
1143                 {
1144                         genSetDPTR(1);
1145                 }
1146                 
1147                 while (offset > aop->coff) {
1148                         pic14_emitcode ("inc","dptr");
1149                         aop->coff++;
1150                 }
1151                 
1152                 while (offset < aop->coff) {            
1153                         pic14_emitcode("lcall","__decdptr");
1154                         aop->coff--;
1155                 }
1156                 
1157                 aop->coff = offset;
1158                 if (aop->code) {
1159                         pic14_emitcode("clr","a");
1160                         pic14_emitcode("movc","a,@a+dptr");
1161                 }
1162                 else {
1163                         pic14_emitcode("movx","a,@dptr");
1164                 }
1165                 
1166                 if (aop->type == AOP_DPTR2)
1167                 {
1168                         genSetDPTR(0);
1169                 }
1170                 
1171                 return (dname ? "acc" : "a");
1172                 
1173                 
1174         case AOP_IMMD:
1175                 if (bit16) 
1176                         sprintf (s,"%s",aop->aopu.aop_immd);
1177                 else
1178                         if (offset) 
1179                                 sprintf(s,"(%s >> %d)",
1180                                 aop->aopu.aop_immd,
1181                                 offset*8);
1182                         else
1183                                 sprintf(s,"%s",
1184                                 aop->aopu.aop_immd);
1185                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1186                         rs = Safe_calloc(1,strlen(s)+1);
1187                         strcpy(rs,s);   
1188                         return rs;
1189                         
1190         case AOP_DIR:
1191                 if (offset) {
1192                         sprintf(s,"(%s + %d)",
1193                                 aop->aopu.aop_dir,
1194                                 offset);
1195                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1196                 } else
1197                         sprintf(s,"%s",aop->aopu.aop_dir);
1198                 rs = Safe_calloc(1,strlen(s)+1);
1199                 strcpy(rs,s);   
1200                 return rs;
1201                 
1202         case AOP_REG:
1203                 //if (dname) 
1204                 //        return aop->aopu.aop_reg[offset]->dname;
1205                 //else
1206                 return aop->aopu.aop_reg[offset]->name;
1207                 
1208         case AOP_CRY:
1209                 //pic14_emitcode(";","%d",__LINE__);
1210                 return aop->aopu.aop_dir;
1211                 
1212         case AOP_ACC:
1213                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1214                 return "AOP_accumulator_bug";
1215                 
1216         case AOP_LIT:
1217                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1218                 rs = Safe_calloc(1,strlen(s)+1);
1219                 strcpy(rs,s);   
1220                 return rs;
1221                 
1222         case AOP_STR:
1223                 aop->coff = offset ;
1224                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1225                         dname)
1226                         return "acc";
1227                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1228                 
1229                 return aop->aopu.aop_str[offset];
1230                 
1231         case AOP_PCODE:
1232                 {
1233                         pCodeOp *pcop = aop->aopu.pcop;
1234                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1235                         if(pcop->name) {
1236                                 if (offset) {
1237                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1238                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1239                                 } else {
1240                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1241                                         sprintf(s,"%s", pcop->name);
1242                                 }
1243                         } else
1244                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1245                         
1246                 }
1247                 rs = Safe_calloc(1,strlen(s)+1);
1248                 strcpy(rs,s);   
1249                 return rs;
1250                 
1251   }
1252   
1253   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1254           "aopget got unsupported aop->type");
1255   exit(0);
1256 }
1257
1258
1259 /*-----------------------------------------------------------------*/
1260 /* popGetTempReg - create a new temporary pCodeOp                                  */
1261 /*-----------------------------------------------------------------*/
1262 pCodeOp *popGetTempReg(void)
1263 {
1264         
1265         pCodeOp *pcop;
1266         
1267         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1268         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1269                 PCOR(pcop)->r->wasUsed=1;
1270                 PCOR(pcop)->r->isFree=0;
1271         }
1272         
1273         return pcop;
1274 }
1275
1276 /*-----------------------------------------------------------------*/
1277 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1278 /*-----------------------------------------------------------------*/
1279 void popReleaseTempReg(pCodeOp *pcop)
1280 {
1281         
1282         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1283                 PCOR(pcop)->r->isFree = 1;
1284         
1285 }
1286 /*-----------------------------------------------------------------*/
1287 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1288 /*-----------------------------------------------------------------*/
1289 pCodeOp *popGetLabel(unsigned int key)
1290 {
1291         
1292         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1293         
1294         if(key>(unsigned int)max_key)
1295                 max_key = key;
1296         
1297         return newpCodeOpLabel(NULL,key+100+labelOffset);
1298 }
1299
1300 /*-------------------------------------------------------------------*/
1301 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1302 /*-------------------------------------------------------------------*/
1303 pCodeOp *popGetHighLabel(unsigned int key)
1304 {
1305         pCodeOp *pcop;
1306         pcop = popGetLabel(key);
1307         PCOLAB(pcop)->offset = 1;
1308         return pcop;
1309 }
1310
1311 /*-----------------------------------------------------------------*/
1312 /* popGetLit - asm operator to pcode operator conversion                           */
1313 /*-----------------------------------------------------------------*/
1314 pCodeOp *popGetLit(unsigned int lit)
1315 {
1316         
1317         return newpCodeOpLit((unsigned char)lit);
1318 }
1319
1320 /*-----------------------------------------------------------------*/
1321 /* popGetImmd - asm operator to pcode immediate conversion                 */
1322 /*-----------------------------------------------------------------*/
1323 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1324 {
1325         
1326         return newpCodeOpImmd(name, offset,index, 0, is_func);
1327 }
1328
1329 extern set *externs;
1330
1331 /*-----------------------------------------------------------------*/
1332 /* popGetWithString - asm operator to pcode operator conversion                    */
1333 /*-----------------------------------------------------------------*/
1334 pCodeOp *popGetWithString(char *str, int isExtern)
1335 {
1336         pCodeOp *pcop;
1337         
1338         
1339         if(!str) {
1340                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1341                 exit (1);
1342         }
1343         
1344         pcop = newpCodeOp(str,PO_STR);
1345         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1346
1347         return pcop;
1348 }
1349
1350 pCodeOp *popGetExternal (char *str)
1351 {
1352         pCodeOp *pcop = popGetWithString (str, 1);
1353         
1354         if (str) {
1355           symbol *sym;
1356           bool found = 0;
1357
1358           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1359           {
1360             if (!strcmp (str, sym->rname))
1361               found = 1;
1362           }
1363           
1364           if (!found)
1365           {
1366             sym = newSymbol(str, 0);
1367             strncpy(sym->rname, str, SDCC_NAME_MAX);
1368             addSet (&externs, sym);
1369           } // if
1370         }
1371         return pcop;
1372 }
1373
1374 /*-----------------------------------------------------------------*/
1375 /* popRegFromString -                                                                                      */
1376 /*-----------------------------------------------------------------*/
1377 pCodeOp *popRegFromString(char *str, int size, int offset)
1378 {
1379         
1380         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1381         pcop->type = PO_DIR;
1382         
1383         DEBUGpic14_emitcode(";","%d",__LINE__);
1384         
1385         if(!str)
1386                 str = "BAD_STRING";
1387         
1388         pcop->name = Safe_calloc(1,strlen(str)+1);
1389         strcpy(pcop->name,str);
1390         
1391         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1392         
1393         PCOR(pcop)->r = dirregWithName(pcop->name);
1394         if(PCOR(pcop)->r == NULL) {
1395                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1396                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1397                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1398         } else {
1399                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1400         }
1401         PCOR(pcop)->instance = offset;
1402         
1403         return pcop;
1404 }
1405
1406 /*-----------------------------------------------------------------*/
1407 /*-----------------------------------------------------------------*/
1408 pCodeOp *popRegFromIdx(int rIdx)
1409 {
1410         pCodeOp *pcop;
1411         
1412         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1413                 __FUNCTION__,__LINE__,rIdx);
1414         
1415         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1416         
1417         PCOR(pcop)->rIdx = rIdx;
1418         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1419         PCOR(pcop)->r->isFree = 0;
1420         PCOR(pcop)->r->wasUsed = 1;
1421         
1422         pcop->type = PCOR(pcop)->r->pc_type;
1423         
1424         
1425         return pcop;
1426 }
1427
1428 /*-----------------------------------------------------------------*/
1429 /* popGet - asm operator to pcode operator conversion                      */
1430 /*-----------------------------------------------------------------*/
1431 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1432 {
1433         //char *s = buffer ;
1434         //char *rs;
1435         
1436         pCodeOp *pcop;
1437         
1438         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1439         /* offset is greater than
1440         size then zero */
1441
1442         assert (aop);
1443
1444         /* XXX: still needed for BIT operands (AOP_CRY) */
1445         if (offset > (aop->size - 1) &&
1446                 aop->type != AOP_LIT)
1447                 return NULL;  //zero;
1448         
1449         /* depending on type */
1450         switch (aop->type) {
1451                 
1452         case AOP_R0:
1453         case AOP_R1:
1454         case AOP_DPTR:
1455         case AOP_DPTR2:
1456         case AOP_ACC:
1457                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1458                 return NULL;
1459                 
1460         case AOP_IMMD:
1461                 DEBUGpic14_emitcode(";","%d",__LINE__);
1462                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1463                 
1464         case AOP_DIR:
1465                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1466 #if 0
1467                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1468                 pcop->type = PO_DIR;
1469                 
1470                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1471                 strcpy(pcop->name,aop->aopu.aop_dir);   
1472                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1473                 if(PCOR(pcop)->r == NULL) {
1474                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1475                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1476                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1477                 } else {
1478                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1479                 }
1480                 PCOR(pcop)->instance = offset;
1481                 
1482                 return pcop;
1483 #endif
1484                 
1485         case AOP_REG:
1486                 {
1487                         int rIdx;
1488                         assert (offset < aop->size);
1489                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1490                         
1491                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1492                         PCOR(pcop)->rIdx = rIdx;
1493                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1494                         PCOR(pcop)->r->wasUsed=1;
1495                         PCOR(pcop)->r->isFree=0;
1496                         
1497                         PCOR(pcop)->instance = offset;
1498                         pcop->type = PCOR(pcop)->r->pc_type;
1499                         //rs = aop->aopu.aop_reg[offset]->name;
1500                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1501                         return pcop;
1502                 }
1503                 
1504         case AOP_CRY:
1505                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1506                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1507                 //if(PCOR(pcop)->r == NULL)
1508                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1509                 return pcop;
1510                 
1511         case AOP_LIT:
1512                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1513                 
1514         case AOP_STR:
1515                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1516                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1517                 /*
1518                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1519                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1520                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1521                 pcop->type = PCOR(pcop)->r->pc_type;
1522                 pcop->name = PCOR(pcop)->r->name;
1523                 
1524                   return pcop;
1525                 */
1526                 
1527         case AOP_PCODE:
1528                 pcop = NULL;
1529                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1530                         __LINE__, 
1531                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1532                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1533                 switch (aop->aopu.pcop->type)
1534                 {
1535                 case PO_IMMEDIATE:
1536                   pcop = pCodeOpCopy (aop->aopu.pcop);
1537                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1538                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1539                   PCOI(pcop)->index += offset;
1540                   //PCOI(pcop)->offset = 0;
1541                   break;
1542                 case PO_DIR:
1543                   pcop = pCodeOpCopy (aop->aopu.pcop);
1544                   PCOR(pcop)->instance = offset;
1545                   break;
1546                 default:
1547                   assert ( !"unhandled pCode type" );
1548                   break;
1549                 } // switch
1550                 return pcop;
1551         }
1552         
1553         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1554                 "popGet got unsupported aop->type");
1555         exit(0);
1556 }
1557
1558 /*-----------------------------------------------------------------*/
1559 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1560 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1561 /*-----------------------------------------------------------------*/
1562 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1563 {
1564   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1565   {
1566     pCodeOp *pcop = aop->aopu.pcop;
1567     assert (offset <= GPTRSIZE);
1568
1569     /* special case: index >= 2 should return GPOINTER-style values */
1570     if (offset == 2)
1571     {
1572       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1573       return pcop;
1574     }
1575     
1576     pcop = pCodeOpCopy (pcop);
1577     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1578      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1579     PCOI(pcop)->offset += offset;
1580     PCOI(pcop)->index += index;
1581     //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);
1582     return pcop;
1583   } else {
1584     return popGet (aop, offset + index);
1585   }
1586 }
1587
1588 /*-----------------------------------------------------------------*/
1589 /* aopPut - puts a string for a aop                                                        */
1590 /*-----------------------------------------------------------------*/
1591 void aopPut (asmop *aop, char *s, int offset)
1592 {
1593         char *d = buffer ;
1594         symbol *lbl ;
1595         
1596         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1597         
1598         if (aop->size && offset > ( aop->size - 1)) {
1599                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1600                         "aopPut got offset > aop->size");
1601                 exit(0);
1602         }
1603         
1604         /* will assign value to value */
1605         /* depending on where it is ofcourse */
1606         switch (aop->type) {
1607         case AOP_DIR:
1608                 if (offset) {
1609                         sprintf(d,"(%s + %d)",
1610                                 aop->aopu.aop_dir,offset);
1611                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1612                         
1613                 } else
1614                         sprintf(d,"%s",aop->aopu.aop_dir);
1615                 
1616                 if (strcmp(d,s)) {
1617                         DEBUGpic14_emitcode(";","%d",__LINE__);
1618                         if(strcmp(s,"W"))
1619                                 pic14_emitcode("movf","%s,w",s);
1620                         pic14_emitcode("movwf","%s",d);
1621                         
1622                         if(strcmp(s,"W")) {
1623                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1624                                 if(offset >= aop->size) {
1625                                         emitpcode(POC_CLRF,popGet(aop,offset));
1626                                         break;
1627                                 } else {
1628                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1629                                 }
1630                         }
1631                         emitpcode(POC_MOVWF,popGet(aop,offset));
1632                 
1633                 }
1634                 break;
1635                 
1636         case AOP_REG:
1637                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1638                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1639                         /*
1640                         if (*s == '@'             ||
1641                         strcmp(s,"r0") == 0 ||
1642                         strcmp(s,"r1") == 0 ||
1643                         strcmp(s,"r2") == 0 ||
1644                         strcmp(s,"r3") == 0 ||
1645                         strcmp(s,"r4") == 0 ||
1646                         strcmp(s,"r5") == 0 ||
1647                         strcmp(s,"r6") == 0 || 
1648                         strcmp(s,"r7") == 0 )
1649                         pic14_emitcode("mov","%s,%s  ; %d",
1650                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1651                         else
1652                         */
1653                         
1654                         if(strcmp(s,"W")==0 )
1655                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1656                         
1657                         pic14_emitcode("movwf","%s",
1658                                 aop->aopu.aop_reg[offset]->name);
1659                         
1660                         if(strcmp(s,zero)==0) {
1661                                 emitpcode(POC_CLRF,popGet(aop,offset));
1662                                 
1663                         } else if(strcmp(s,"W")==0) {
1664                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1665                                 pcop->type = PO_GPR_REGISTER;
1666                                 
1667                                 PCOR(pcop)->rIdx = -1;
1668                                 PCOR(pcop)->r = NULL;
1669                                 
1670                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1671                                 pcop->name = Safe_strdup(s);
1672                                 emitpcode(POC_MOVFW,pcop);
1673                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1674                         } else if(strcmp(s,one)==0) {
1675                                 emitpcode(POC_CLRF,popGet(aop,offset));
1676                                 emitpcode(POC_INCF,popGet(aop,offset));
1677                         } else {
1678                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1679                         }
1680                 }
1681                 break;
1682                 
1683         case AOP_DPTR:
1684         case AOP_DPTR2:
1685                 
1686                 if (aop->type == AOP_DPTR2)
1687                 {
1688                         genSetDPTR(1);
1689                 }
1690                 
1691                 if (aop->code) {
1692                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1693                                 "aopPut writting to code space");
1694                         exit(0);
1695                 }
1696                 
1697                 while (offset > aop->coff) {
1698                         aop->coff++;
1699                         pic14_emitcode ("inc","dptr");
1700                 }
1701                 
1702                 while (offset < aop->coff) {
1703                         aop->coff-- ;
1704                         pic14_emitcode("lcall","__decdptr");
1705                 }
1706                 
1707                 aop->coff = offset;
1708                 
1709                 /* if not in accumulater */
1710                 MOVA(s);
1711                 
1712                 pic14_emitcode ("movx","@dptr,a");
1713                 
1714                 if (aop->type == AOP_DPTR2)
1715                 {
1716                         genSetDPTR(0);
1717                 }
1718                 break;
1719                 
1720         case AOP_R0:
1721         case AOP_R1:
1722                 while (offset > aop->coff) {
1723                         aop->coff++;
1724                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1725                 }
1726                 while (offset < aop->coff) {
1727                         aop->coff-- ;
1728                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1729                 }
1730                 aop->coff = offset;
1731                 
1732                 if (aop->paged) {
1733                         MOVA(s);                         
1734                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1735                         
1736                 } else
1737                         if (*s == '@') {
1738                                 MOVA(s);
1739                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1740                         } else
1741                                 if (strcmp(s,"r0") == 0 ||
1742                                         strcmp(s,"r1") == 0 ||
1743                                         strcmp(s,"r2") == 0 ||
1744                                         strcmp(s,"r3") == 0 ||
1745                                         strcmp(s,"r4") == 0 ||
1746                                         strcmp(s,"r5") == 0 ||
1747                                         strcmp(s,"r6") == 0 || 
1748                                         strcmp(s,"r7") == 0 ) {
1749                                         char buffer[10];
1750                                         sprintf(buffer,"a%s",s);
1751                                         pic14_emitcode("mov","@%s,%s",
1752                                                 aop->aopu.aop_ptr->name,buffer);
1753                                 } else
1754                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1755                                 
1756                                 break;
1757                                 
1758         case AOP_STK:
1759                 if (strcmp(s,"a") == 0)
1760                         pic14_emitcode("push","acc");
1761                 else
1762                         pic14_emitcode("push","%s",s);
1763                 
1764                 break;
1765                 
1766         case AOP_CRY:
1767                 /* if bit variable */
1768                 if (!aop->aopu.aop_dir) {
1769                         pic14_emitcode("clr","a");
1770                         pic14_emitcode("rlc","a");
1771                 } else {
1772                         if (s == zero) 
1773                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1774                         else
1775                                 if (s == one)
1776                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1777                                 else
1778                                         if (!strcmp(s,"c"))
1779                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1780                                         else {
1781                                                 lbl = newiTempLabel(NULL);
1782                                                 
1783                                                 if (strcmp(s,"a")) {
1784                                                         MOVA(s);
1785                                                 }
1786                                                 pic14_emitcode("clr","c");
1787                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1788                                                 pic14_emitcode("cpl","c");
1789                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1790                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1791                                         }
1792                 }
1793                 break;
1794                 
1795         case AOP_STR:
1796                 aop->coff = offset;
1797                 if (strcmp(aop->aopu.aop_str[offset],s))
1798                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1799                 break;
1800                 
1801         case AOP_ACC:
1802                 aop->coff = offset;
1803                 if (!offset && (strcmp(s,"acc") == 0))
1804                         break;
1805                 
1806                 if (strcmp(aop->aopu.aop_str[offset],s))
1807                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1808                 break;
1809                 
1810         default :
1811                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1812                         "aopPut got unsupported aop->type");
1813                 exit(0);
1814         }
1815         
1816 }
1817
1818 /*-----------------------------------------------------------------*/
1819 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1820 /*-----------------------------------------------------------------*/
1821 static void mov2w_op (operand *op, int offset)
1822 {
1823         assert (op);
1824         FENTRY;
1825
1826         /* for PO_IMMEDIATEs: use address or value? */
1827         if (op_isLitLike (op))
1828         {
1829                 /* access address of op */
1830                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1831                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1832                 {
1833                         if (offset == GPTRSIZE-1)
1834                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1835                         else
1836                                 emitpcode (POC_MOVLW, popGetLit (0));
1837                 }
1838                 else
1839                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1840         } else {
1841                 /* access value stored in op */
1842                 mov2w (AOP(op), offset);
1843         }
1844 }
1845
1846
1847 /*-----------------------------------------------------------------*/
1848 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1849 /*-----------------------------------------------------------------*/
1850 void mov2w (asmop *aop, int offset)
1851 {
1852         
1853         if(!aop)
1854                 return;
1855         
1856         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1857         
1858         if ( aop_isLitLike (aop) )
1859                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1860         else
1861                 emitpcode(POC_MOVFW,popGet(aop,offset));
1862         
1863 }
1864
1865 static void movwf (asmop *op, int offset)
1866 {
1867         emitpcode (POC_MOVWF, popGet(op, offset));
1868 }
1869
1870 static pCodeOp *get_argument_pcop (int idx)
1871 {
1872         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1873         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1874 }
1875
1876 static pCodeOp *get_return_val_pcop (int offset)
1877 {
1878         assert (offset > 0 && "the most significant byte is returned via WREG");
1879         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1880 }
1881
1882 static void pass_argument (operand *op, int offset, int idx)
1883 {
1884         if (op)
1885                 mov2w_op (op, offset);
1886         if (idx != 0)
1887                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1888 }
1889
1890 static void get_returnvalue (operand *op, int offset, int idx)
1891 {
1892         if (idx != 0)
1893                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1894         movwf(AOP(op), offset);
1895 }
1896
1897 static void call_libraryfunc (char *name)
1898 {
1899   /* library code might reside in different page... */
1900   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1901   /* call the library function */
1902   emitpcode (POC_CALL, popGetExternal (name));
1903   /* might return from different page... */
1904   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1905 }
1906 #if 0
1907 /*-----------------------------------------------------------------*/
1908 /* reAdjustPreg - points a register back to where it should        */
1909 /*-----------------------------------------------------------------*/
1910 static void reAdjustPreg (asmop *aop)
1911 {
1912         int size ;
1913         
1914         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1915         aop->coff = 0;
1916         if ((size = aop->size) <= 1)
1917                 return ;
1918         size-- ;
1919         switch (aop->type) {
1920         case AOP_R0 :
1921         case AOP_R1 :
1922                 while (size--)
1923                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1924                 break;                  
1925         case AOP_DPTR :
1926         case AOP_DPTR2:
1927                 if (aop->type == AOP_DPTR2)
1928                 {
1929                         genSetDPTR(1);
1930                 } 
1931                 while (size--)
1932                 {
1933                         pic14_emitcode("lcall","__decdptr");
1934                 }
1935                 
1936                 if (aop->type == AOP_DPTR2)
1937                 {
1938                         genSetDPTR(0);
1939                 }
1940                 break;
1941                 
1942         }
1943         
1944 }
1945 #endif
1946
1947
1948 #if 0
1949 /*-----------------------------------------------------------------*/
1950 /* opIsGptr: returns non-zero if the passed operand is             */
1951 /* a generic pointer type.                                         */
1952 /*-----------------------------------------------------------------*/ 
1953 static int opIsGptr(operand *op)
1954 {
1955         sym_link *type = operandType(op);
1956         
1957         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1958         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1959         {
1960                 return 1;
1961         }
1962         return 0;          
1963 }
1964 #endif
1965
1966 /*-----------------------------------------------------------------*/
1967 /* pic14_getDataSize - get the operand data size                   */
1968 /*-----------------------------------------------------------------*/
1969 int pic14_getDataSize(operand *op)
1970 {
1971         int size;
1972         
1973         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1974         
1975 #if 0
1976         size = getSize(OP_SYM_ETYPE(op));
1977         return size;
1978         //return AOP_SIZE(op);
1979         
1980         // tsd- in the pic port, the genptr size is 1, so this code here
1981         // fails. ( in the 8051 port, the size was 4).
1982 #else
1983         size = AOP_SIZE(op);
1984         if (IS_GENPTR(OP_SYM_TYPE(op)))
1985         {
1986                 sym_link *type = operandType(op);
1987                 if (IS_GENPTR(type))
1988                 {
1989                         /* generic pointer; arithmetic operations
1990                         * should ignore the high byte (pointer type).
1991                         */
1992                         size--;
1993                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1994                 }
1995         }
1996         return size;
1997 #endif
1998 }
1999
2000 /*-----------------------------------------------------------------*/
2001 /* pic14_outAcc - output Acc                                       */
2002 /*-----------------------------------------------------------------*/
2003 void pic14_outAcc(operand *result)
2004 {
2005         int size,offset;
2006         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2007         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2008         
2009         
2010         size = pic14_getDataSize(result);
2011         if(size){
2012                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2013                 size--;
2014                 offset = 1;
2015                 /* unsigned or positive */
2016                 while(size--)
2017                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2018         }
2019         
2020 }
2021
2022 /*-----------------------------------------------------------------*/
2023 /* pic14_outBitC - output a bit C                                  */
2024 /*-----------------------------------------------------------------*/
2025 void pic14_outBitC(operand *result)
2026 {
2027         
2028         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2029         /* if the result is bit */
2030         if (AOP_TYPE(result) == AOP_CRY) 
2031                 aopPut(AOP(result),"c",0);
2032         else {
2033                 pic14_emitcode("clr","a  ; %d", __LINE__);
2034                 pic14_emitcode("rlc","a");
2035                 pic14_outAcc(result);
2036         }
2037 }
2038
2039 /*-----------------------------------------------------------------*/
2040 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2041 /*-----------------------------------------------------------------*/
2042 void pic14_toBoolean(operand *oper)
2043 {
2044         int size = AOP_SIZE(oper);
2045         int offset = 0;
2046         
2047         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2048
2049         assert (size > 0);
2050
2051         if (size == 1) {
2052                 /* MOVFW does not load the flags... */
2053                 if (AOP_TYPE(oper) == AOP_ACC) {
2054                         emitpcode(POC_IORLW, popGetLit(0));
2055                         offset = 1;
2056                 } else {
2057                         emitpcode(POC_MOVLW, popGetLit(0));
2058                         offset = 0;
2059                 }
2060         } else {
2061                 if ( AOP_TYPE(oper) != AOP_ACC) {
2062                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2063                         offset = 1;
2064                 }
2065         }
2066         
2067         while (offset < size) {
2068                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2069         }
2070         /* Z is set iff (oper == 0) */
2071 }
2072
2073
2074 /*-----------------------------------------------------------------*/
2075 /* genNot - generate code for ! operation                          */
2076 /*-----------------------------------------------------------------*/
2077 static void genNot (iCode *ic)
2078 {
2079         //symbol *tlbl;
2080         int size;
2081
2082         FENTRY;
2083         
2084         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2085         /* assign asmOps to operand & result */
2086         aopOp (IC_LEFT(ic),ic,FALSE);
2087         aopOp (IC_RESULT(ic),ic,TRUE);
2088         
2089         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2090         /* if in bit space then a special case */
2091         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2092                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2093                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2094                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2095                 } else {
2096                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2097                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2098                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2099                 }
2100                 goto release;
2101         }
2102         
2103         size = AOP_SIZE(IC_LEFT(ic));
2104         mov2w (AOP(IC_LEFT(ic)),0);
2105         while (--size > 0)
2106         {
2107           if (op_isLitLike (IC_LEFT(ic)))
2108             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2109           else
2110             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2111         }
2112         emitpcode(POC_MOVLW, popGetLit (0));
2113         emitSKPNZ;
2114         emitpcode(POC_MOVLW, popGetLit (1));
2115         movwf(AOP(IC_RESULT(ic)), 0);
2116
2117         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2118         {
2119           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2120         }
2121         goto release;
2122         
2123 release:        
2124         /* release the aops */
2125         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2126         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2127 }
2128
2129
2130 /*-----------------------------------------------------------------*/
2131 /* genCpl - generate code for complement                                                   */
2132 /*-----------------------------------------------------------------*/
2133 static void genCpl (iCode *ic)
2134 {
2135         operand *left, *result;
2136         int size, offset=0;  
2137         
2138         FENTRY;
2139         
2140         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2141         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2142         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2143         
2144         /* if both are in bit space then 
2145         a special case */
2146         if (AOP_TYPE(result) == AOP_CRY &&
2147                 AOP_TYPE(left) == AOP_CRY ) { 
2148                 
2149                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2150                 pic14_emitcode("cpl","c"); 
2151                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2152                 goto release; 
2153         } 
2154         
2155         size = AOP_SIZE(result);
2156         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2157         while (size--) {
2158                 
2159                 if(AOP_TYPE(left) == AOP_ACC) 
2160                         emitpcode(POC_XORLW, popGetLit(0xff));
2161                 else
2162                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2163                 
2164                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2165                 offset++;
2166         }
2167         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2168         
2169         
2170 release:
2171         /* release the aops */
2172         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2173         freeAsmop(result,NULL,ic,TRUE);
2174 }
2175
2176 /*-----------------------------------------------------------------*/
2177 /* genUminusFloat - unary minus for floating points                        */
2178 /*-----------------------------------------------------------------*/
2179 static void genUminusFloat(operand *op,operand *result)
2180 {
2181         int size ,offset =0 ;
2182         char *l;
2183         
2184         FENTRY;
2185
2186         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2187         /* for this we just need to flip the 
2188         first it then copy the rest in place */
2189         size = AOP_SIZE(op) - 1;
2190         l = aopGet(AOP(op),3,FALSE,FALSE);
2191         
2192         MOVA(l);          
2193         
2194         pic14_emitcode("cpl","acc.7");
2195         aopPut(AOP(result),"a",3);      
2196         
2197         while(size--) {
2198                 aopPut(AOP(result),
2199                         aopGet(AOP(op),offset,FALSE,FALSE),
2200                         offset);
2201                 offset++;
2202         }                
2203 }
2204
2205 /*-----------------------------------------------------------------*/
2206 /* genUminus - unary minus code generation                                                 */
2207 /*-----------------------------------------------------------------*/
2208 static void genUminus (iCode *ic)
2209 {
2210         int size, i;
2211         sym_link *optype, *rtype;
2212         
2213         FENTRY;
2214         
2215         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2216         /* assign asmops */
2217         aopOp(IC_LEFT(ic),ic,FALSE);
2218         aopOp(IC_RESULT(ic),ic,TRUE);
2219         
2220         /* if both in bit space then special
2221         case */
2222         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2223                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2224                 
2225                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2226                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2227                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2228                 
2229                 goto release; 
2230         } 
2231         
2232         optype = operandType(IC_LEFT(ic));
2233         rtype = operandType(IC_RESULT(ic));
2234         
2235         /* if float then do float stuff */
2236         if (IS_FLOAT(optype)) {
2237                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2238                 goto release;
2239         }
2240         
2241         /* otherwise subtract from zero by taking the 2's complement */
2242         size = AOP_SIZE(IC_LEFT(ic));
2243         
2244         for(i=0; i<size; i++) {
2245                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2246                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2247                 else {
2248                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2249                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2250                 }
2251         }
2252         
2253         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2254         for(i=1; i<size; i++) {
2255                 emitSKPNZ;
2256                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2257         }
2258         
2259 release:
2260         /* release the aops */
2261         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2262         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2263 }
2264
2265 /*-----------------------------------------------------------------*/
2266 /* saveRegisters - will look for a call and save the registers     */
2267 /*-----------------------------------------------------------------*/
2268 static void saveRegisters(iCode *lic) 
2269 {
2270         int i;
2271         iCode *ic;
2272         bitVect *rsave;
2273         sym_link *dtype;
2274         
2275         FENTRY;
2276
2277         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2278         /* look for call */
2279         for (ic = lic ; ic ; ic = ic->next) 
2280                 if (ic->op == CALL || ic->op == PCALL)
2281                         break;
2282                 
2283                 if (!ic) {
2284                         fprintf(stderr,"found parameter push with no function call\n");
2285                         return ;
2286                 }
2287                 
2288                 /* if the registers have been saved already then
2289                 do nothing */
2290                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2291                         return ;
2292                 
2293                         /* find the registers in use at this time 
2294                 and push them away to safety */
2295                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2296                         ic->rUsed);
2297                 
2298                 ic->regsSaved = 1;
2299                 if (options.useXstack) {
2300                         if (bitVectBitValue(rsave,R0_IDX))
2301                                 pic14_emitcode("mov","b,r0");
2302                         pic14_emitcode("mov","r0,%s",spname);
2303                         for (i = 0 ; i < pic14_nRegs ; i++) {
2304                                 if (bitVectBitValue(rsave,i)) {
2305                                         if (i == R0_IDX)
2306                                                 pic14_emitcode("mov","a,b");
2307                                         else
2308                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2309                                         pic14_emitcode("movx","@r0,a");
2310                                         pic14_emitcode("inc","r0");
2311                                 }
2312                         }
2313                         pic14_emitcode("mov","%s,r0",spname);
2314                         if (bitVectBitValue(rsave,R0_IDX))
2315                                 pic14_emitcode("mov","r0,b");     
2316                 }// else
2317                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2318                 //        if (bitVectBitValue(rsave,i))
2319                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2320                 //}
2321                 
2322                 dtype = operandType(IC_LEFT(ic));
2323                 if (currFunc && dtype && 
2324                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2325                         IFFUNC_ISISR(currFunc->type) &&
2326                         !ic->bankSaved) 
2327                         
2328                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2329                 
2330 }
2331 /*-----------------------------------------------------------------*/
2332 /* unsaveRegisters - pop the pushed registers                                      */
2333 /*-----------------------------------------------------------------*/
2334 static void unsaveRegisters (iCode *ic)
2335 {
2336         int i;
2337         bitVect *rsave;
2338         
2339         FENTRY;
2340
2341         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2342         /* find the registers in use at this time 
2343         and push them away to safety */
2344         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2345                 ic->rUsed);
2346         
2347         if (options.useXstack) {
2348                 pic14_emitcode("mov","r0,%s",spname); 
2349                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2350                         if (bitVectBitValue(rsave,i)) {
2351                                 pic14_emitcode("dec","r0");
2352                                 pic14_emitcode("movx","a,@r0");
2353                                 if (i == R0_IDX)
2354                                         pic14_emitcode("mov","b,a");
2355                                 else
2356                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2357                         }       
2358                         
2359                 }
2360                 pic14_emitcode("mov","%s,r0",spname);
2361                 if (bitVectBitValue(rsave,R0_IDX))
2362                         pic14_emitcode("mov","r0,b");
2363         } //else
2364         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2365         //      if (bitVectBitValue(rsave,i))
2366         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2367         //}
2368         
2369 }  
2370
2371
2372 /*-----------------------------------------------------------------*/
2373 /* pushSide -                            */
2374 /*-----------------------------------------------------------------*/
2375 static void pushSide(operand * oper, int size)
2376 {
2377 #if 0
2378         int offset = 0;
2379         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2380         while (size--) {
2381                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2382                 if (AOP_TYPE(oper) != AOP_REG &&
2383                         AOP_TYPE(oper) != AOP_DIR &&
2384                         strcmp(l,"a") ) {
2385                         pic14_emitcode("mov","a,%s",l);
2386                         pic14_emitcode("push","acc");
2387                 } else
2388                         pic14_emitcode("push","%s",l);
2389         }
2390 #endif
2391 }
2392
2393 /*-----------------------------------------------------------------*/
2394 /* assignResultValue -                           */
2395 /*-----------------------------------------------------------------*/
2396 static void assignResultValue(operand * oper)
2397 {
2398         int size = AOP_SIZE(oper);
2399         int offset = 0;
2400         
2401         FENTRY;
2402
2403         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2404         
2405         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2406         
2407         /* assign MSB first (passed via WREG) */
2408         while (size--) {
2409                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2410                 GpsuedoStkPtr++;
2411         }
2412 }
2413
2414
2415 /*-----------------------------------------------------------------*/
2416 /* genIpush - genrate code for pushing this gets a little complex  */
2417 /*-----------------------------------------------------------------*/
2418 static void genIpush (iCode *ic)
2419 {
2420         FENTRY;
2421         
2422         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2423 #if 0
2424         int size, offset = 0 ;
2425         char *l;
2426         
2427         
2428         /* if this is not a parm push : ie. it is spill push 
2429         and spill push is always done on the local stack */
2430         if (!ic->parmPush) {
2431                 
2432                 /* and the item is spilt then do nothing */
2433                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2434                         return ;
2435                 
2436                 aopOp(IC_LEFT(ic),ic,FALSE);
2437                 size = AOP_SIZE(IC_LEFT(ic));
2438                 /* push it on the stack */
2439                 while(size--) {
2440                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2441                         if (*l == '#') {
2442                                 MOVA(l);
2443                                 l = "acc";
2444                         }
2445                         pic14_emitcode("push","%s",l);
2446                 }
2447                 return ;                
2448         }
2449         
2450         /* this is a paramter push: in this case we call
2451         the routine to find the call and save those
2452         registers that need to be saved */   
2453         saveRegisters(ic);
2454         
2455         /* then do the push */
2456         aopOp(IC_LEFT(ic),ic,FALSE);
2457         
2458         
2459         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2460         size = AOP_SIZE(IC_LEFT(ic));
2461         
2462         while (size--) {
2463                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2464                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2465                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2466                         strcmp(l,"a") ) {
2467                         pic14_emitcode("mov","a,%s",l);
2468                         pic14_emitcode("push","acc");
2469                 } else
2470                         pic14_emitcode("push","%s",l);
2471         }         
2472         
2473         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2474 #endif
2475 }
2476
2477 /*-----------------------------------------------------------------*/
2478 /* genIpop - recover the registers: can happen only for spilling   */
2479 /*-----------------------------------------------------------------*/
2480 static void genIpop (iCode *ic)
2481 {
2482         FENTRY;
2483
2484         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2485         assert (!"genIpop -- unimplemented");
2486 #if 0
2487         int size,offset ;
2488         
2489         
2490         /* if the temp was not pushed then */
2491         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2492                 return ;
2493         
2494         aopOp(IC_LEFT(ic),ic,FALSE);
2495         size = AOP_SIZE(IC_LEFT(ic));
2496         offset = (size-1);
2497         while (size--) 
2498                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2499                 FALSE,TRUE));
2500         
2501         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2502 #endif
2503 }
2504
2505 /*-----------------------------------------------------------------*/
2506 /* unsaverbank - restores the resgister bank from stack                    */
2507 /*-----------------------------------------------------------------*/
2508 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2509 {
2510         FENTRY;
2511
2512         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2513 #if 0
2514         int i;
2515         asmop *aop ;
2516         regs *r = NULL;
2517         
2518         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2519         if (popPsw) {
2520                 if (options.useXstack) {
2521                         aop = newAsmop(0);
2522                         r = getFreePtr(ic,&aop,FALSE);
2523                         
2524                         
2525                         pic14_emitcode("mov","%s,_spx",r->name);
2526                         pic14_emitcode("movx","a,@%s",r->name);
2527                         pic14_emitcode("mov","psw,a");
2528                         pic14_emitcode("dec","%s",r->name);
2529                         
2530                 }else
2531                         pic14_emitcode ("pop","psw");
2532         }
2533         
2534         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2535                 if (options.useXstack) {           
2536                         pic14_emitcode("movx","a,@%s",r->name);
2537                         //pic14_emitcode("mov","(%s+%d),a",
2538                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2539                         pic14_emitcode("dec","%s",r->name);
2540                         
2541                 } else 
2542                         pic14_emitcode("pop",""); //"(%s+%d)",
2543                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2544         }
2545         
2546         if (options.useXstack) {
2547                 
2548                 pic14_emitcode("mov","_spx,%s",r->name);
2549                 freeAsmop(NULL,aop,ic,TRUE);
2550                 
2551         }
2552 #endif 
2553 }
2554
2555 /*-----------------------------------------------------------------*/
2556 /* saverbank - saves an entire register bank on the stack                  */
2557 /*-----------------------------------------------------------------*/
2558 static void saverbank (int bank, iCode *ic, bool pushPsw)
2559 {
2560         FENTRY;
2561
2562         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2563 #if 0
2564         int i;
2565         asmop *aop ;
2566         regs *r = NULL;
2567         
2568         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2569         if (options.useXstack) {
2570                 
2571                 aop = newAsmop(0);
2572                 r = getFreePtr(ic,&aop,FALSE);  
2573                 pic14_emitcode("mov","%s,_spx",r->name);
2574                 
2575         }
2576         
2577         for (i = 0 ; i < pic14_nRegs ;i++) {
2578                 if (options.useXstack) {
2579                         pic14_emitcode("inc","%s",r->name);
2580                         //pic14_emitcode("mov","a,(%s+%d)",
2581                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2582                         pic14_emitcode("movx","@%s,a",r->name);                 
2583                 } else 
2584                         pic14_emitcode("push","");// "(%s+%d)",
2585                 //regspic14[i].base,8*bank+regspic14[i].offset);
2586         }
2587         
2588         if (pushPsw) {
2589                 if (options.useXstack) {
2590                         pic14_emitcode("mov","a,psw");
2591                         pic14_emitcode("movx","@%s,a",r->name); 
2592                         pic14_emitcode("inc","%s",r->name);
2593                         pic14_emitcode("mov","_spx,%s",r->name);                 
2594                         freeAsmop (NULL,aop,ic,TRUE);
2595                         
2596                 } else
2597                         pic14_emitcode("push","psw");
2598                 
2599                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2600         }
2601         ic->bankSaved = 1;
2602 #endif
2603 }
2604
2605 /*-----------------------------------------------------------------*/
2606 /* genCall - generates a call statement                                                    */
2607 /*-----------------------------------------------------------------*/
2608 static void genCall (iCode *ic)
2609 {
2610         sym_link *dtype;         
2611         symbol *sym;
2612         char *name;
2613         int isExtern;
2614         
2615         FENTRY;
2616
2617         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2618         
2619         /* if caller saves & we have not saved then */
2620         if (!ic->regsSaved)
2621                 saveRegisters(ic);
2622         
2623                 /* if we are calling a function that is not using
2624                 the same register bank then we need to save the
2625         destination registers on the stack */
2626         dtype = operandType(IC_LEFT(ic));
2627         if (currFunc && dtype && 
2628                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2629                 IFFUNC_ISISR(currFunc->type) &&
2630                 !ic->bankSaved) 
2631                 
2632                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2633         
2634         /* if send set is not empty the assign */
2635         if (_G.sendSet) {
2636                 iCode *sic;
2637                 /* For the Pic port, there is no data stack.
2638                 * So parameters passed to functions are stored
2639                 * in registers. (The pCode optimizer will get
2640                 * rid of most of these :).
2641                 */
2642                 int psuedoStkPtr=-1;
2643                 int firstTimeThruLoop = 1;
2644                 
2645                 _G.sendSet = reverseSet(_G.sendSet);
2646                 
2647                 /* First figure how many parameters are getting passed */
2648                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2649                 sic = setNextItem(_G.sendSet)) {
2650                         
2651                         aopOp(IC_LEFT(sic),sic,FALSE);
2652                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2653                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2654                 }
2655                 
2656                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2657                 sic = setNextItem(_G.sendSet)) {
2658                         int size, offset = 0;
2659                         
2660                         aopOp(IC_LEFT(sic),sic,FALSE);
2661                         size = AOP_SIZE(IC_LEFT(sic));
2662                         
2663                         while (size--) {
2664                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2665                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2666                                 
2667                                 if(!firstTimeThruLoop) {
2668                                         /* If this is not the first time we've been through the loop
2669                                         * then we need to save the parameter in a temporary
2670                                         * register. The last byte of the last parameter is
2671                                         * passed in W. */
2672                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2673                                         
2674                                 }
2675                                 firstTimeThruLoop=0;
2676                                 
2677                                 mov2w_op (IC_LEFT(sic),  offset);
2678                                 offset++;
2679                         }
2680                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2681                 }
2682                 _G.sendSet = NULL;
2683         }
2684         /* make the call */
2685         sym = OP_SYMBOL(IC_LEFT(ic));
2686         name = sym->rname[0] ? sym->rname : sym->name;
2687         isExtern = IS_EXTERN(sym->etype);
2688         if (isExtern) {
2689                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2690         }
2691         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2692         if (isExtern) {
2693                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2694         }
2695         GpsuedoStkPtr=0;
2696         /* if we need assign a result value */
2697         if ((IS_ITEMP(IC_RESULT(ic)) && 
2698                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2699                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2700                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2701                 
2702                 _G.accInUse++;
2703                 aopOp(IC_RESULT(ic),ic,FALSE);
2704                 _G.accInUse--;
2705                 
2706                 assignResultValue(IC_RESULT(ic));
2707                 
2708                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2709                         AopType(AOP_TYPE(IC_RESULT(ic))));
2710                 
2711                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2712         }
2713         
2714         /* if register bank was saved then pop them */
2715         if (ic->bankSaved)
2716                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2717         
2718         /* if we hade saved some registers then unsave them */
2719         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2720                 unsaveRegisters (ic);
2721         
2722         
2723 }
2724
2725 /*-----------------------------------------------------------------*/
2726 /* genPcall - generates a call by pointer statement                        */
2727 /*-----------------------------------------------------------------*/
2728 static void genPcall (iCode *ic)
2729 {
2730         sym_link *dtype;
2731         symbol *albl = newiTempLabel(NULL);
2732         symbol *blbl = newiTempLabel(NULL);
2733         PIC_OPCODE poc;
2734         pCodeOp *pcop;
2735         operand *left;
2736         
2737         FENTRY;
2738
2739         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2740         /* if caller saves & we have not saved then */
2741         if (!ic->regsSaved)
2742                 saveRegisters(ic);
2743         
2744                 /* if we are calling a function that is not using
2745                 the same register bank then we need to save the
2746         destination registers on the stack */
2747         dtype = operandType(IC_LEFT(ic));
2748         if (currFunc && dtype && 
2749                 IFFUNC_ISISR(currFunc->type) &&
2750                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2751                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2752         
2753         left = IC_LEFT(ic);
2754         aopOp(left,ic,FALSE);
2755         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2756         
2757         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2758         
2759         pushSide(IC_LEFT(ic), FPTRSIZE);
2760         
2761         /* if send set is not empty, assign parameters */
2762         if (_G.sendSet) {
2763                 
2764                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2765                 /* no way to pass args - W always gets used to make the call */
2766         }
2767         /* first idea - factor out a common helper function and call it.
2768         But don't know how to get it generated only once in its own block
2769         
2770         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2771                 char *rname;
2772                 char *buffer;
2773                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2774                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2775                 buffer = Safe_calloc(1,strlen(rname)+16);
2776                 sprintf(buffer, "%s_goto_helper", rname);
2777                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2778                 free(buffer);
2779         }
2780         */
2781         emitpcode(POC_CALL,popGetLabel(albl->key));
2782         pcop = popGetLabel(blbl->key);
2783         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2784         emitpcode(POC_GOTO,pcop);
2785         emitpLabel(albl->key);
2786         
2787         emitpcode(poc,popGetAddr(AOP(left),1,0));
2788         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2789         emitpcode(poc,popGetAddr(AOP(left),0,0));
2790         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2791         
2792         emitpLabel(blbl->key);
2793         
2794         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2795         
2796         /* if we need to assign a result value */
2797         if ((IS_ITEMP(IC_RESULT(ic)) &&
2798                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2799                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2800                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2801                 
2802                 _G.accInUse++;
2803                 aopOp(IC_RESULT(ic),ic,FALSE);
2804                 _G.accInUse--;
2805
2806                 GpsuedoStkPtr = 0;
2807                 
2808                 assignResultValue(IC_RESULT(ic));
2809                 
2810                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2811         }
2812         
2813         /* if register bank was saved then unsave them */
2814         if (currFunc && dtype && 
2815                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2816                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2817         
2818                 /* if we hade saved some registers then
2819         unsave them */
2820         if (ic->regsSaved)
2821                 unsaveRegisters (ic);
2822         
2823 }
2824
2825 /*-----------------------------------------------------------------*/
2826 /* resultRemat - result  is rematerializable                                       */
2827 /*-----------------------------------------------------------------*/
2828 static int resultRemat (iCode *ic)
2829 {
2830         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2831         FENTRY;
2832
2833         if (SKIP_IC(ic) || ic->op == IFX)
2834                 return 0;
2835         
2836         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2837                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2838                 if (sym->remat && !POINTER_SET(ic)) 
2839                         return 1;
2840         }
2841         
2842         return 0;
2843 }
2844
2845 #if defined(__BORLANDC__) || defined(_MSC_VER)
2846 #define STRCASECMP stricmp
2847 #else
2848 #define STRCASECMP strcasecmp
2849 #endif
2850
2851 #if 0
2852 /*-----------------------------------------------------------------*/
2853 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2854 /*-----------------------------------------------------------------*/
2855 static bool inExcludeList(char *s)
2856 {
2857         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2858         int i =0;
2859         
2860         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2861         if (options.excludeRegs[i] &&
2862                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2863                 return FALSE ;
2864         
2865         for ( i = 0 ; options.excludeRegs[i]; i++) {
2866                 if (options.excludeRegs[i] &&
2867                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2868                         return TRUE;
2869         }
2870         return FALSE ;
2871 }
2872 #endif
2873
2874 /*-----------------------------------------------------------------*/
2875 /* genFunction - generated code for function entry                                 */
2876 /*-----------------------------------------------------------------*/
2877 static void genFunction (iCode *ic)
2878 {
2879         symbol *sym;
2880         sym_link *ftype;
2881         
2882         FENTRY;
2883
2884         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2885         
2886         labelOffset += (max_key+4);
2887         max_key=0;
2888         GpsuedoStkPtr=0;
2889         _G.nRegsSaved = 0;
2890         /* create the function header */
2891         pic14_emitcode(";","-----------------------------------------");
2892         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2893         pic14_emitcode(";","-----------------------------------------");
2894         
2895         pic14_emitcode("","%s:",sym->rname);
2896         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2897         
2898         ftype = operandType(IC_LEFT(ic));
2899         
2900         /* if critical function then turn interrupts off */
2901         if (IFFUNC_ISCRITICAL(ftype))
2902                 pic14_emitcode("clr","ea");
2903         
2904                 /* here we need to generate the equates for the
2905         register bank if required */
2906 #if 0
2907         if (FUNC_REGBANK(ftype) != rbank) {
2908                 int i ;
2909                 
2910                 rbank = FUNC_REGBANK(ftype);
2911                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2912                         if (strcmp(regspic14[i].base,"0") == 0)
2913                                 pic14_emitcode("","%s = 0x%02x",
2914                                 regspic14[i].dname,
2915                                 8*rbank+regspic14[i].offset);
2916                         else
2917                                 pic14_emitcode ("","%s = %s + 0x%02x",
2918                                 regspic14[i].dname,
2919                                 regspic14[i].base,
2920                                 8*rbank+regspic14[i].offset);
2921                 }
2922         }
2923 #endif
2924         
2925         /* if this is an interrupt service routine */
2926         if (IFFUNC_ISISR(sym->type)) {
2927         /*  already done in pic14createInterruptVect() - delete me
2928         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2929         emitpcodeNULLop(POC_NOP);
2930         emitpcodeNULLop(POC_NOP);
2931         emitpcodeNULLop(POC_NOP);
2932                 */
2933                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2934                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2935                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2936                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2937                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2938                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2939                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2940                 
2941                 pBlockConvert2ISR(pb);
2942                 pic14_hasInterrupt = 1;
2943 #if 0  
2944                 if (!inExcludeList("acc"))              
2945                         pic14_emitcode ("push","acc");  
2946                 if (!inExcludeList("b"))
2947                         pic14_emitcode ("push","b");
2948                 if (!inExcludeList("dpl"))
2949                         pic14_emitcode ("push","dpl");
2950                 if (!inExcludeList("dph"))
2951                         pic14_emitcode ("push","dph");
2952                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2953                 {
2954                         pic14_emitcode ("push", "dpx");
2955                         /* Make sure we're using standard DPTR */
2956                         pic14_emitcode ("push", "dps");
2957                         pic14_emitcode ("mov", "dps, #0x00");
2958                         if (options.stack10bit)
2959                         { 
2960                                 /* This ISR could conceivably use DPTR2. Better save it. */
2961                                 pic14_emitcode ("push", "dpl1");
2962                                 pic14_emitcode ("push", "dph1");
2963                                 pic14_emitcode ("push", "dpx1");
2964                         }
2965                 }
2966                 /* if this isr has no bank i.e. is going to
2967                 run with bank 0 , then we need to save more
2968                 registers :-) */
2969                 if (!FUNC_REGBANK(sym->type)) {
2970                         
2971                 /* if this function does not call any other
2972                 function then we can be economical and
2973                         save only those registers that are used */
2974                         if (! IFFUNC_HASFCALL(sym->type)) {
2975                                 int i;
2976                                 
2977                                 /* if any registers used */
2978                                 if (sym->regsUsed) {
2979                                         /* save the registers used */
2980                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2981                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2982                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2983                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2984                                         }
2985                                 }
2986                                 
2987                         } else {
2988                         /* this function has    a function call cannot
2989                         determines register usage so we will have the
2990                                 entire bank */
2991                                 saverbank(0,ic,FALSE);
2992                         }       
2993                 }
2994 #endif
2995         } else {
2996         /* if callee-save to be used for this function
2997                 then save the registers being used in this function */
2998                 if (IFFUNC_CALLEESAVES(sym->type)) {
2999                         int i;
3000                         
3001                         /* if any registers used */
3002                         if (sym->regsUsed) {
3003                                 /* save the registers used */
3004                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3005                                         if (bitVectBitValue(sym->regsUsed,i) ||
3006                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3007                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3008                                                 _G.nRegsSaved++;
3009                                         }
3010                                 }
3011                         }
3012                 }
3013         }
3014         
3015         /* set the register bank to the desired value */
3016         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3017                 pic14_emitcode("push","psw");
3018                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3019         }
3020         
3021         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3022                 
3023                 if (options.useXstack) {
3024                         pic14_emitcode("mov","r0,%s",spname);
3025                         pic14_emitcode("mov","a,_bp");
3026                         pic14_emitcode("movx","@r0,a");
3027                         pic14_emitcode("inc","%s",spname);
3028                 }
3029                 else
3030                 {
3031                         /* set up the stack */
3032                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3033                 }
3034                 pic14_emitcode ("mov","_bp,%s",spname);
3035         }
3036         
3037         /* adjust the stack for the function */
3038         if (sym->stack) {
3039                 
3040                 int i = sym->stack;
3041                 if (i > 256 ) 
3042                         werror(W_STACK_OVERFLOW,sym->name);
3043                 
3044                 if (i > 3 && sym->recvSize < 4) {                
3045                         
3046                         pic14_emitcode ("mov","a,sp");
3047                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3048                         pic14_emitcode ("mov","sp,a");
3049                         
3050                 }
3051                 else
3052                         while(i--)
3053                                 pic14_emitcode("inc","sp");
3054         }
3055         
3056         if (sym->xstack) {
3057                 
3058                 pic14_emitcode ("mov","a,_spx");
3059                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3060                 pic14_emitcode ("mov","_spx,a");
3061         }
3062         
3063 }
3064
3065 /*-----------------------------------------------------------------*/
3066 /* genEndFunction - generates epilogue for functions                       */
3067 /*-----------------------------------------------------------------*/
3068 static void genEndFunction (iCode *ic)
3069 {
3070         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3071         
3072         FENTRY;
3073
3074         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3075         
3076         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3077         {
3078                 pic14_emitcode ("mov","%s,_bp",spname);
3079         }
3080         
3081         /* if use external stack but some variables were
3082         added to the local stack then decrement the
3083         local stack */
3084         if (options.useXstack && sym->stack) {    
3085                 pic14_emitcode("mov","a,sp");
3086                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3087                 pic14_emitcode("mov","sp,a");
3088         }
3089         
3090         
3091         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3092                 if (options.useXstack) {
3093                         pic14_emitcode("mov","r0,%s",spname);
3094                         pic14_emitcode("movx","a,@r0");
3095                         pic14_emitcode("mov","_bp,a");
3096                         pic14_emitcode("dec","%s",spname);
3097                 }
3098                 else
3099                 {
3100                         pic14_emitcode ("pop","_bp");
3101                 }
3102         }
3103         
3104         /* restore the register bank    */        
3105         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3106                 pic14_emitcode ("pop","psw");
3107         
3108         if (IFFUNC_ISISR(sym->type)) {
3109                 
3110                 /* now we need to restore the registers */
3111                 /* if this isr has no bank i.e. is going to
3112                 run with bank 0 , then we need to save more
3113 registers :-) */
3114                 if (!FUNC_REGBANK(sym->type)) {
3115                         
3116                 /* if this function does not call any other
3117                 function then we can be economical and
3118                         save only those registers that are used */
3119                         if (! IFFUNC_HASFCALL(sym->type)) {
3120                                 int i;
3121                                 
3122                                 /* if any registers used */
3123                                 if (sym->regsUsed) {
3124                                         /* save the registers used */
3125                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3126                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3127                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3128                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3129                                         }
3130                                 }
3131                                 
3132                         } else {
3133                         /* this function has    a function call cannot
3134                         determines register usage so we will have the
3135                                 entire bank */
3136                                 unsaverbank(0,ic,FALSE);
3137                         }       
3138                 }
3139 #if 0
3140                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3141                 {
3142                         if (options.stack10bit)
3143                         {
3144                                 pic14_emitcode ("pop", "dpx1");
3145                                 pic14_emitcode ("pop", "dph1");
3146                                 pic14_emitcode ("pop", "dpl1");
3147                         } 
3148                         pic14_emitcode ("pop", "dps");
3149                         pic14_emitcode ("pop", "dpx");
3150                 }
3151                 if (!inExcludeList("dph"))
3152                         pic14_emitcode ("pop","dph");
3153                 if (!inExcludeList("dpl"))
3154                         pic14_emitcode ("pop","dpl");
3155                 if (!inExcludeList("b"))
3156                         pic14_emitcode ("pop","b");
3157                 if (!inExcludeList("acc"))
3158                         pic14_emitcode ("pop","acc");
3159                 
3160                 if (IFFUNC_ISCRITICAL(sym->type))
3161                         pic14_emitcode("setb","ea");
3162 #endif
3163                 
3164                 /* if debug then send end of function */
3165                 /*      if (options.debug && currFunc) { */
3166                 if (currFunc) {
3167                         debugFile->writeEndFunction (currFunc, ic, 1);
3168                 }
3169                 
3170                 pic14_emitcode ("reti","");
3171                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3172                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3173                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3174                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3175                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3176                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3177                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3178                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3179                 emitpcodeNULLop(POC_RETFIE);
3180         }
3181         else {
3182                 if (IFFUNC_ISCRITICAL(sym->type))
3183                         pic14_emitcode("setb","ea");
3184                 
3185                 if (IFFUNC_CALLEESAVES(sym->type)) {
3186                         int i;
3187                         
3188                         /* if any registers used */
3189                         if (sym->regsUsed) {
3190                                 /* save the registers used */
3191                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3192                                         if (bitVectBitValue(sym->regsUsed,i) ||
3193                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3194                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3195                                 }
3196                         }
3197                         
3198                 }
3199                 
3200                 /* if debug then send end of function */
3201                 if (currFunc) {
3202                         debugFile->writeEndFunction (currFunc, ic, 1);
3203                 }
3204                 
3205                 pic14_emitcode ("return","");
3206                 emitpcodeNULLop(POC_RETURN);
3207                 
3208                 /* Mark the end of a function */
3209                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3210         }
3211         
3212 }
3213
3214 /*-----------------------------------------------------------------*/
3215 /* genRet - generate code for return statement                                     */
3216 /*-----------------------------------------------------------------*/
3217 static void genRet (iCode *ic)
3218 {
3219         int size,offset = 0;
3220         
3221         FENTRY;
3222
3223         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3224         /* if we have no return value then
3225         just generate the "ret" */
3226         if (!IC_LEFT(ic)) 
3227                 goto jumpret;           
3228         
3229                 /* we have something to return then
3230         move the return value into place */
3231         aopOp(IC_LEFT(ic),ic,FALSE);
3232         size = AOP_SIZE(IC_LEFT(ic));
3233
3234         for (offset = 0; offset < size; offset++)
3235         {
3236                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3237         }
3238         
3239         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3240         
3241 jumpret:
3242         /* generate a jump to the return label
3243         if the next is not the return statement */
3244         if (!(ic->next && ic->next->op == LABEL &&
3245                 IC_LABEL(ic->next) == returnLabel)) {
3246                 
3247                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3248         }
3249         
3250 }
3251
3252 /*-----------------------------------------------------------------*/
3253 /* genLabel - generates a label                                                                    */
3254 /*-----------------------------------------------------------------*/
3255 static void genLabel (iCode *ic)
3256 {
3257         FENTRY;
3258
3259         /* special case never generate */
3260         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3261         if (IC_LABEL(ic) == entryLabel)
3262                 return ;
3263         
3264         emitpLabel(IC_LABEL(ic)->key);
3265         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3266 }
3267
3268 /*-----------------------------------------------------------------*/
3269 /* genGoto - generates a goto                                                                      */
3270 /*-----------------------------------------------------------------*/
3271 //tsd
3272 static void genGoto (iCode *ic)
3273 {
3274         FENTRY;
3275
3276         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3277         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3278 }
3279
3280
3281 /*-----------------------------------------------------------------*/
3282 /* genMultbits :- multiplication of bits                                                   */
3283 /*-----------------------------------------------------------------*/
3284 static void genMultbits (operand *left, 
3285                                                  operand *right, 
3286                                                  operand *result)
3287 {
3288         FENTRY;
3289         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3290         
3291         if(!pic14_sameRegs(AOP(result),AOP(right)))
3292                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3293         
3294         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3295         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3296         emitpcode(POC_BCF,  popGet(AOP(result),0));
3297         
3298 }
3299
3300
3301 /*-----------------------------------------------------------------*/
3302 /* genMultOneByte : 8 bit multiplication & division                        */
3303 /*-----------------------------------------------------------------*/
3304 static void genMultOneByte (operand *left,
3305                                                         operand *right,
3306                                                         operand *result)
3307 {
3308         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3309         
3310         // symbol *lbl ;
3311         int size,offset,i;
3312         
3313         
3314         FENTRY;
3315         
3316         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3317         DEBUGpic14_AopType(__LINE__,left,right,result);
3318         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3319         
3320         /* (if two literals, the value is computed before) */
3321         /* if one literal, literal on the right */
3322         if (AOP_TYPE(left) == AOP_LIT){
3323                 operand *t = right;
3324                 right = left;
3325                 left = t;
3326         }
3327
3328         assert (AOP_SIZE(left) == AOP_SIZE(right));
3329         
3330         size = min(AOP_SIZE(result),AOP_SIZE(left));
3331         offset = Gstack_base_addr - (2*size - 1);
3332
3333         /* pass right operand as argument */
3334         for (i=0; i < size; i++)
3335         {
3336                 mov2w (AOP(right), i);
3337                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3338         } // for
3339         
3340         /* pass left operand as argument */
3341         for (i=0; i < size; i++)
3342         {
3343                 mov2w (AOP(left), i);
3344                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3345         } // for
3346         assert (offset == Gstack_base_addr);
3347         
3348         /* call library routine */
3349         assert (size > 0 && size <= 4);
3350         call_libraryfunc (func[size]);
3351         
3352         /* assign result */
3353         movwf (AOP(result), size-1);
3354         for (i=0; i < size - 1; i++)
3355         {
3356                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3357                 movwf (AOP(result), size - 2 - i);
3358         } // for
3359
3360         /* now (zero-/sign) extend the result to its size */
3361         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3362 }
3363
3364 /*-----------------------------------------------------------------*/
3365 /* genMult - generates code for multiplication                                     */
3366 /*-----------------------------------------------------------------*/
3367 static void genMult (iCode *ic)
3368 {
3369         operand *left = IC_LEFT(ic);
3370         operand *right = IC_RIGHT(ic);
3371         operand *result= IC_RESULT(ic); 
3372         
3373         FENTRY;
3374
3375         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3376         /* assign the amsops */
3377         aopOp (left,ic,FALSE);
3378         aopOp (right,ic,FALSE);
3379         aopOp (result,ic,TRUE);
3380         
3381         DEBUGpic14_AopType(__LINE__,left,right,result);
3382         
3383         /* special cases first */
3384         /* both are bits */
3385         if (AOP_TYPE(left) == AOP_CRY &&
3386                 AOP_TYPE(right)== AOP_CRY) {
3387                 genMultbits(left,right,result);
3388                 goto release ;
3389         }
3390         
3391         /* if both are of size == 1 */
3392         if (AOP_SIZE(left) == 1 &&
3393                 AOP_SIZE(right) == 1 ) {
3394                 genMultOneByte(left,right,result);
3395                 goto release ;
3396         }
3397         
3398         /* should have been converted to function call */
3399         assert(0) ;
3400         
3401 release :
3402         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3403         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3404         freeAsmop(result,NULL,ic,TRUE); 
3405 }
3406
3407 /*-----------------------------------------------------------------*/
3408 /* genDivbits :- division of bits                                                                  */
3409 /*-----------------------------------------------------------------*/
3410 static void genDivbits (operand *left, 
3411                                                 operand *right, 
3412                                                 operand *result)
3413 {
3414         
3415         char *l;
3416         
3417         FENTRY;
3418
3419         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3420         /* the result must be bit */      
3421         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3422         l = aopGet(AOP(left),0,FALSE,FALSE);
3423         
3424         MOVA(l);          
3425         
3426         pic14_emitcode("div","ab");
3427         pic14_emitcode("rrc","a");
3428         aopPut(AOP(result),"c",0);
3429 }
3430
3431 /*-----------------------------------------------------------------*/
3432 /* genDivOneByte : 8 bit division                                                                  */
3433 /*-----------------------------------------------------------------*/
3434 static void genDivOneByte (operand *left,
3435                                                    operand *right,
3436                                                    operand *result)
3437 {
3438         int size;
3439         
3440         FENTRY;
3441         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3442         
3443         assert (AOP_SIZE(result) == 1);
3444         assert (AOP_SIZE(right) == 1);
3445         assert (AOP_SIZE(left) == 1);
3446
3447         size = min(AOP_SIZE(result),AOP_SIZE(left));
3448
3449         if (AOP_TYPE(right) == AOP_LIT)
3450         {
3451                 /* XXX: might add specialized code */
3452         }
3453
3454         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3455         {
3456                 /* unsigned division */
3457         #if 1
3458                 mov2w(AOP(right),0);
3459                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3460                 mov2w(AOP(left),0);
3461                 call_libraryfunc("__divuchar");
3462                 movwf(AOP(result),0);
3463         #else
3464                 pCodeOp *temp;
3465                 symbol *lbl;
3466
3467                 temp = popGetTempReg();
3468                 lbl = newiTempLabel(NULL);
3469                 
3470                 /* XXX: improve this naive approach:
3471                    [result] = [a] / [b]
3472                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3473
3474                    In PIC assembler:
3475                    movf  left,W
3476                    movwf temp           // temp <-- left
3477                    movf  right,W        // W <-- right
3478                    clrf  result
3479                    label1:
3480                    incf  result
3481                    subwf temp,F         // temp <-- temp - W
3482                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3483                    goto  label1
3484                    decf result          // we just subtract once too often
3485                  */
3486
3487                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3488                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3489                 
3490                 mov2w(AOP(left),0);
3491                 emitpcode(POC_MOVWF, temp);
3492                 mov2w(AOP(right),0);
3493                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3494
3495                 emitpLabel(lbl->key);
3496                 emitpcode(POC_INCF, popGet(AOP(result),0));
3497                 emitpcode(POC_SUBWF, temp);
3498                 emitSKPNC;
3499                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3500                 emitpcode(POC_DECF, popGet(AOP(result),0));
3501         #endif
3502         }
3503         else
3504         {
3505                 /* signed division */
3506                 mov2w(AOP(right),0);
3507                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3508                 mov2w(AOP(left),0);
3509                 call_libraryfunc("__divschar");
3510                 movwf(AOP(result),0);
3511         }
3512
3513         /* now performed the signed/unsigned division -- extend result */
3514         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3515 }
3516
3517 /*-----------------------------------------------------------------*/
3518 /* genDiv - generates code for division                            */
3519 /*-----------------------------------------------------------------*/
3520 static void genDiv (iCode *ic)
3521 {
3522         operand *left = IC_LEFT(ic);
3523         operand *right = IC_RIGHT(ic);
3524         operand *result= IC_RESULT(ic); 
3525         
3526         FENTRY;
3527         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3528         /* assign the amsops */
3529         aopOp (left,ic,FALSE);
3530         aopOp (right,ic,FALSE);
3531         aopOp (result,ic,TRUE);
3532         
3533         /* special cases first */
3534         /* both are bits */
3535         if (AOP_TYPE(left) == AOP_CRY &&
3536                 AOP_TYPE(right)== AOP_CRY) {
3537                 genDivbits(left,right,result);
3538                 goto release ;
3539         }
3540         
3541         /* if both are of size == 1 */
3542         if (AOP_SIZE(left) == 1 &&
3543                 AOP_SIZE(right) == 1 ) {
3544                 genDivOneByte(left,right,result);
3545                 goto release ;
3546         }
3547         
3548         /* should have been converted to function call */
3549         assert(0);
3550 release :
3551         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3552         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3553         freeAsmop(result,NULL,ic,TRUE); 
3554 }
3555
3556 /*-----------------------------------------------------------------*/
3557 /* genModbits :- modulus of bits                                                                   */
3558 /*-----------------------------------------------------------------*/
3559 static void genModbits (operand *left, 
3560                                                 operand *right, 
3561                                                 operand *result)
3562 {
3563         
3564         char *l;
3565         
3566         FENTRY;
3567         /* the result must be bit */      
3568         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3569         l = aopGet(AOP(left),0,FALSE,FALSE);
3570         
3571         MOVA(l);
3572         
3573         pic14_emitcode("div","ab");
3574         pic14_emitcode("mov","a,b");
3575         pic14_emitcode("rrc","a");
3576         aopPut(AOP(result),"c",0);
3577 }
3578
3579 /*-----------------------------------------------------------------*/
3580 /* genModOneByte : 8 bit modulus                                                                   */
3581 /*-----------------------------------------------------------------*/
3582 static void genModOneByte (operand *left,
3583                                                    operand *right,
3584                                                    operand *result)
3585 {
3586         int size;
3587         
3588         FENTRY;
3589         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3590         
3591         assert (AOP_SIZE(result) == 1);
3592         assert (AOP_SIZE(right) == 1);
3593         assert (AOP_SIZE(left) == 1);
3594
3595         size = min(AOP_SIZE(result),AOP_SIZE(left));
3596
3597         if (AOP_TYPE(right) == AOP_LIT)
3598         {
3599                 /* XXX: might add specialized code */
3600         }
3601
3602         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3603         {
3604                 /* unsigned division */
3605         #if 1
3606                 mov2w(AOP(right),0);
3607                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3608                 mov2w(AOP(left),0);
3609                 call_libraryfunc("__moduchar");
3610                 movwf(AOP(result),0);
3611         #else
3612                 pCodeOp *temp;
3613                 symbol *lbl;
3614
3615                 lbl = newiTempLabel(NULL);
3616                 
3617                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3618
3619                 /* XXX: improve this naive approach:
3620                    [result] = [a] % [b]
3621                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3622
3623                    In PIC assembler:
3624                    movf  left,W
3625                    movwf result         // result <-- left
3626                    movf  right,W        // W <-- right
3627                    label1:
3628                    subwf result,F       // result <-- result - W
3629                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3630                    goto  label1
3631                    addwf result, F      // we just subtract once too often
3632                  */
3633
3634                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3635                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3636                 
3637                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3638                 {
3639                         mov2w(AOP(left),0);
3640                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3641                 }
3642                 mov2w(AOP(right),0);
3643
3644                 emitpLabel(lbl->key);
3645                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3646                 emitSKPNC;
3647                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3648                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3649         #endif
3650         }
3651         else
3652         {
3653                 /* signed division */
3654                 mov2w(AOP(right),0);
3655                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3656                 mov2w(AOP(left),0);
3657                 call_libraryfunc("__modschar");
3658                 movwf(AOP(result),0);
3659         }
3660
3661         /* now we performed the signed/unsigned modulus -- extend result */
3662         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3663 }
3664
3665 /*-----------------------------------------------------------------*/
3666 /* genMod - generates code for division                                                    */
3667 /*-----------------------------------------------------------------*/
3668 static void genMod (iCode *ic)
3669 {
3670         operand *left = IC_LEFT(ic);
3671         operand *right = IC_RIGHT(ic);
3672         operand *result= IC_RESULT(ic);  
3673         
3674         FENTRY;
3675         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3676         /* assign the amsops */
3677         aopOp (left,ic,FALSE);
3678         aopOp (right,ic,FALSE);
3679         aopOp (result,ic,TRUE);
3680         
3681         /* special cases first */
3682         /* both are bits */
3683         if (AOP_TYPE(left) == AOP_CRY &&
3684                 AOP_TYPE(right)== AOP_CRY) {
3685                 genModbits(left,right,result);
3686                 goto release ;
3687         }
3688         
3689         /* if both are of size == 1 */
3690         if (AOP_SIZE(left) == 1 &&
3691                 AOP_SIZE(right) == 1 ) {
3692                 genModOneByte(left,right,result);
3693                 goto release ;
3694         }
3695         
3696         /* should have been converted to function call */
3697         assert(0);
3698         
3699 release :
3700         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3701         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3702         freeAsmop(result,NULL,ic,TRUE); 
3703 }
3704
3705 /*-----------------------------------------------------------------*/
3706 /* genIfxJump :- will create a jump depending on the ifx                   */
3707 /*-----------------------------------------------------------------*/
3708 /*
3709 note: May need to add parameter to indicate when a variable is in bit space.
3710 */
3711 static void genIfxJump (iCode *ic, char *jval)
3712 {
3713         
3714         FENTRY;
3715         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3716         /* if true label then we jump if condition
3717         supplied is true */
3718         if ( IC_TRUE(ic) ) {
3719                 
3720                 if(strcmp(jval,"a") == 0)
3721                         emitSKPZ;
3722                 else if (strcmp(jval,"c") == 0)
3723                         emitSKPC;
3724                 else {
3725                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3726                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3727                 }
3728                 
3729                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3730                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3731                 
3732         }
3733         else {
3734                 /* false label is present */
3735                 if(strcmp(jval,"a") == 0)
3736                         emitSKPNZ;
3737                 else if (strcmp(jval,"c") == 0)
3738                         emitSKPNC;
3739                 else {
3740                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3741                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3742                 }
3743                 
3744                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3745                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3746                 
3747         }
3748         
3749         
3750         /* mark the icode as generated */
3751         ic->generated = 1;
3752 }
3753
3754 #if 0
3755 /*-----------------------------------------------------------------*/
3756 /* genSkip                                                                                                                 */
3757 /*-----------------------------------------------------------------*/
3758 static void genSkip(iCode *ifx,int status_bit)
3759 {
3760         FENTRY;
3761         if(!ifx)
3762                 return;
3763         
3764         if ( IC_TRUE(ifx) ) {
3765                 switch(status_bit) {
3766                 case 'z':
3767                         emitSKPNZ;
3768                         break;
3769                         
3770                 case 'c':
3771                         emitSKPNC;
3772                         break;
3773                         
3774                 case 'd':
3775                         emitSKPDC;
3776                         break;
3777                         
3778                 }
3779                 
3780                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3781                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3782                 
3783         } else {
3784                 
3785                 switch(status_bit) {
3786                         
3787                 case 'z':
3788                         emitSKPZ;
3789                         break;
3790                         
3791                 case 'c':
3792                         emitSKPC;
3793                         break;
3794                         
3795                 case 'd':
3796                         emitSKPDC;
3797                         break;
3798                 }
3799                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3800                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3801                 
3802         }
3803         
3804 }
3805 #endif
3806
3807 /*-----------------------------------------------------------------*/
3808 /* genSkipc                                                                                                        */
3809 /*-----------------------------------------------------------------*/
3810 static void genSkipc(resolvedIfx *rifx)
3811 {
3812         FENTRY;
3813         if(!rifx)
3814                 return;
3815         
3816         if(rifx->condition)
3817                 emitSKPNC;
3818         else
3819                 emitSKPC;
3820         
3821         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3822         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3823         rifx->generated = 1;
3824 }
3825
3826 #if 0
3827 /*-----------------------------------------------------------------*/
3828 /* genSkipz2                                                                                                       */
3829 /*-----------------------------------------------------------------*/
3830 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3831 {
3832         FENTRY;
3833         if(!rifx)
3834                 return;
3835         
3836         if( (rifx->condition ^ invert_condition) & 1)
3837                 emitSKPZ;
3838         else
3839                 emitSKPNZ;
3840         
3841         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3842         rifx->generated = 1;
3843 }
3844 #endif
3845
3846 #if 0
3847 /*-----------------------------------------------------------------*/
3848 /* genSkipz                                                        */
3849 /*-----------------------------------------------------------------*/
3850 static void genSkipz(iCode *ifx, int condition)
3851 {
3852         FENTRY;
3853         assert (ifx != NULL);
3854         
3855         if(condition)
3856                 emitSKPNZ;
3857         else
3858                 emitSKPZ;
3859         
3860         if ( IC_TRUE(ifx) )
3861                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3862         else
3863                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3864         
3865         if ( IC_TRUE(ifx) )
3866                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3867         else
3868                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3869         
3870 }
3871 #endif
3872
3873 #if 0
3874 /*-----------------------------------------------------------------*/
3875 /* genSkipCond                                                     */
3876 /*-----------------------------------------------------------------*/
3877 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3878 {
3879         FENTRY;
3880         if(!rifx)
3881                 return;
3882         
3883         if(rifx->condition)
3884                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3885         else
3886                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3887         
3888         
3889         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3890         rifx->generated = 1;
3891 }
3892 #endif
3893
3894 #if 0
3895 /*-----------------------------------------------------------------*/
3896 /* genChkZeroes :- greater or less than comparison                 */
3897 /*     For each byte in a literal that is zero, inclusive or the   */
3898 /*     the corresponding byte in the operand with W                */
3899 /*     returns true if any of the bytes are zero                   */
3900 /*-----------------------------------------------------------------*/
3901 static int genChkZeroes(operand *op, int lit,  int size)
3902 {
3903         
3904         int i;
3905         int flag =1;
3906         
3907         while(size--) {
3908                 i = (lit >> (size*8)) & 0xff;
3909                 
3910                 if(i==0) {
3911                         if(flag) 
3912                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3913                         else
3914                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3915                         flag = 0;
3916                 }
3917         }
3918         
3919         return (flag==0);
3920 }
3921 #endif
3922
3923
3924 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3925 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3926 #define DEBUGpc           emitpComment
3927
3928 /*-----------------------------------------------------------------*/
3929 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3930 /*                  aop (if it's NOT a literal) or from lit (if    */
3931 /*                  aop is a literal)                              */
3932 /*-----------------------------------------------------------------*/
3933 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3934   if (aop->type == AOP_LIT) {
3935     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3936   } else {
3937     emitpcode (POC_MOVFW, popGet (aop, offset));
3938   }
3939 }
3940
3941 /* genCmp performs a left < right comparison, stores
3942  * the outcome in result (if != NULL) and generates
3943  * control flow code for the ifx (if != NULL).
3944  *
3945  * This version leaves in sequences like
3946  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3947  * which should be optmized by the peephole
3948  * optimizer - RN 2005-01-01 */
3949 static void genCmp (operand *left,operand *right,
3950                     operand *result, iCode *ifx, int sign)
3951 {
3952   resolvedIfx rIfx;
3953   int size;
3954   int offs;
3955   symbol *templbl;
3956   operand *dummy;
3957   unsigned long lit;
3958   unsigned long mask;
3959   int performedLt;
3960   int invert_result = 0;
3961
3962   FENTRY;
3963   
3964   assert (AOP_SIZE(left) == AOP_SIZE(right));
3965   assert (left && right);
3966
3967   size = AOP_SIZE(right) - 1;
3968   mask = (0x100UL << (size*8)) - 1;
3969   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3970   performedLt = 1;
3971   templbl = NULL;
3972   lit = 0;
3973   
3974   resolveIfx (&rIfx, ifx);
3975
3976   /**********************************************************************
3977    * handle bits - bit compares are promoted to int compares seemingly! *
3978    **********************************************************************/
3979 #if 0
3980   // THIS IS COMPLETELY UNTESTED!
3981   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3982     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3983     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3984     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3985
3986     emitSETC;
3987     // 1 < {0,1} is false --> clear C by skipping the next instruction
3988     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3989     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3990     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3991     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3992     emitCLRC; // only skipped for left=0 && right=1
3993
3994     goto correct_result_in_carry;
3995   } // if
3996 #endif
3997
3998   /*************************************************
3999    * make sure that left is register (or the like) *
4000    *************************************************/
4001   if (!isAOP_REGlike(left)) {
4002     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4003     assert (isAOP_LIT(left));
4004     assert (isAOP_REGlike(right));
4005     // swap left and right
4006     // left < right <==> right > left <==> (right >= left + 1)
4007     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4008
4009     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4010       // MAXVALUE < right? always false
4011       if (performedLt) emitCLRC; else emitSETC;
4012       goto correct_result_in_carry;
4013     } // if
4014
4015     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4016     // that's why we handled it above.
4017     lit++;
4018
4019     dummy = left;
4020     left = right;
4021     right = dummy;
4022
4023     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4024   } else if (isAOP_LIT(right)) {
4025     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4026   } // if
4027
4028   assert (isAOP_REGlike(left)); // left must be register or the like
4029   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4030
4031   /*************************************************
4032    * special cases go here                         *
4033    *************************************************/
4034
4035   if (isAOP_LIT(right)) {
4036     if (!sign) {
4037       // unsigned comparison to a literal
4038       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4039       if (lit == 0) {
4040         // unsigned left < 0? always false
4041         if (performedLt) emitCLRC; else emitSETC;
4042         goto correct_result_in_carry;
4043       }
4044     } else {
4045       // signed comparison to a literal
4046       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4047       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4048         // signed left < 0x80000000? always false
4049         if (performedLt) emitCLRC; else emitSETC;
4050         goto correct_result_in_carry;
4051       } else if (lit == 0) {
4052         // compare left < 0; set CARRY if SIGNBIT(left) is set
4053         if (performedLt) emitSETC; else emitCLRC;
4054         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4055         if (performedLt) emitCLRC; else emitSETC;
4056         goto correct_result_in_carry;
4057       }
4058     } // if (!sign)
4059   } // right is literal
4060
4061   /*************************************************
4062    * perform a general case comparison             *
4063    * make sure we get CARRY==1 <==> left >= right  *
4064    *************************************************/
4065   // compare most significant bytes
4066   //DEBUGpc ("comparing bytes at offset %d", size);
4067   if (!sign) {
4068     // unsigned comparison
4069     pic14_mov2w_regOrLit (AOP(right), lit, size);
4070     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4071   } else {
4072     // signed comparison
4073     // (add 2^n to both operands then perform an unsigned comparison)
4074     if (isAOP_LIT(right)) {
4075       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4076       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4077
4078       if (litbyte == 0x80) {
4079         // left >= 0x80 -- always true, but more bytes to come
4080         mov2w (AOP(left), size);
4081         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4082         emitSETC;
4083       } else {
4084         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4085         mov2w (AOP(left), size);
4086         emitpcode (POC_ADDLW, popGetLit (0x80));
4087         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4088       } // if
4089     } else {
4090       pCodeOp *pctemp = popGetTempReg();
4091       mov2w (AOP(left), size);
4092       emitpcode (POC_ADDLW, popGetLit (0x80));
4093       emitpcode (POC_MOVWF, pctemp);
4094       mov2w (AOP(right), size);
4095       emitpcode (POC_ADDLW, popGetLit (0x80));
4096       emitpcode (POC_SUBFW, pctemp);
4097       popReleaseTempReg(pctemp);
4098     }
4099   } // if (!sign)
4100
4101   // compare remaining bytes (treat as unsigned case from above)
4102   templbl = newiTempLabel ( NULL );
4103   offs = size;
4104   while (offs--) {
4105     //DEBUGpc ("comparing bytes at offset %d", offs);
4106     emitSKPZ;
4107     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4108     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4109     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4110   } // while (offs)
4111   emitpLabel (templbl->key);
4112   goto result_in_carry;
4113
4114 result_in_carry:
4115   
4116   /****************************************************
4117    * now CARRY contains the result of the comparison: *
4118    * SUBWF sets CARRY iff                             *
4119    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4120    * (F=left, W=right)                                *
4121    ****************************************************/
4122
4123   if (performedLt) {
4124     invert_result = 1;
4125     // value will be used in the following genSkipc()
4126     rIfx.condition ^= 1;
4127   } // if
4128
4129 correct_result_in_carry:
4130
4131   // assign result to variable (if neccessary)
4132   if (result && AOP_TYPE(result) != AOP_CRY) {
4133     //DEBUGpc ("assign result");
4134     size = AOP_SIZE(result);
4135     while (size--) {
4136       emitpcode (POC_CLRF, popGet (AOP(result), size));
4137     } // while
4138     if (invert_result) {
4139       emitSKPC;
4140       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4141     } else {
4142       emitpcode (POC_RLF, popGet (AOP(result), 0));
4143     }
4144   } // if (result)
4145
4146   // perform conditional jump
4147   if (ifx) {
4148     //DEBUGpc ("generate control flow");
4149     genSkipc (&rIfx);
4150     ifx->generated = 1;
4151   } // if
4152 }
4153
4154
4155 #if 0
4156 /* OLD VERSION -- BUGGY, DO NOT USE */
4157
4158 /*-----------------------------------------------------------------*/
4159 /* genCmp :- greater or less than comparison                       */
4160 /*-----------------------------------------------------------------*/
4161 static void genCmp (operand *left,operand *right,
4162                                         operand *result, iCode *ifx, int sign)
4163 {
4164         int size; //, offset = 0 ;
4165         unsigned long lit = 0L,i = 0;
4166         resolvedIfx rFalseIfx;
4167         //  resolvedIfx rTrueIfx;
4168         symbol *truelbl;
4169
4170         FENTRY;
4171         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4172         /*
4173         if(ifx) {
4174         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4175         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4176         }
4177         */
4178         
4179         resolveIfx(&rFalseIfx,ifx);
4180         truelbl  = newiTempLabel(NULL);
4181         size = max(AOP_SIZE(left),AOP_SIZE(right));
4182         
4183         DEBUGpic14_AopType(__LINE__,left,right,result);
4184         
4185 #define _swapp
4186         
4187         /* if literal is on the right then swap with left */
4188         if ((AOP_TYPE(right) == AOP_LIT)) {
4189                 operand *tmp = right ;
4190                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4191                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4192 #ifdef _swapp
4193                 
4194                 lit = (lit - 1) & mask;
4195                 right = left;
4196                 left = tmp;
4197                 rFalseIfx.condition ^= 1;
4198 #endif
4199                 
4200         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4201                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4202         }
4203         
4204         
4205         //if(IC_TRUE(ifx) == NULL)
4206         /* if left & right are bit variables */
4207         if (AOP_TYPE(left) == AOP_CRY &&
4208                 AOP_TYPE(right) == AOP_CRY ) {
4209                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4210                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4211         } else {
4212         /* subtract right from left if at the
4213         end the carry flag is set then we know that
4214                 left is greater than right */
4215                 
4216                 symbol *lbl  = newiTempLabel(NULL);
4217                 
4218 #ifndef _swapp
4219                 if(AOP_TYPE(right) == AOP_LIT) {
4220                         
4221                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4222                         
4223                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4224                         
4225                         /* special cases */
4226                         
4227                         if(lit == 0) {
4228                                 
4229                                 if(sign != 0) 
4230                                         genSkipCond(&rFalseIfx,left,size-1,7);
4231                                 else 
4232                                         /* no need to compare to 0...*/
4233                                         /* NOTE: this is a de-generate compare that most certainly 
4234                                         *       creates some dead code. */
4235                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4236                                 
4237                                 if(ifx) ifx->generated = 1;
4238                                 return;
4239                                 
4240                         }
4241                         size--;
4242                         
4243                         if(size == 0) {
4244                                 //i = (lit >> (size*8)) & 0xff;
4245                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4246                                 
4247                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4248                                 
4249                                 i = ((0-lit) & 0xff);
4250                                 if(sign) {
4251                                         if( i == 0x81) { 
4252                                         /* lit is 0x7f, all signed chars are less than
4253                                                 * this except for 0x7f itself */
4254                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4255                                                 genSkipz2(&rFalseIfx,0);
4256                                         } else {
4257                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4258                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4259                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4260                                         }
4261                                         
4262                                 } else {
4263                                         if(lit == 1) {
4264                                                 genSkipz2(&rFalseIfx,1);
4265                                         } else {
4266                                                 emitpcode(POC_ADDLW, popGetLit(i));
4267                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4268                                         }
4269                                 }
4270                                 
4271                                 if(ifx) ifx->generated = 1;
4272                                 return;
4273                         }
4274                         
4275                         /* chars are out of the way. now do ints and longs */
4276                         
4277                         
4278                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4279                         
4280                         /* special cases */
4281                         
4282                         if(sign) {
4283                                 
4284                                 if(lit == 0) {
4285                                         genSkipCond(&rFalseIfx,left,size,7);
4286                                         if(ifx) ifx->generated = 1;
4287                                         return;
4288                                 }
4289                                 
4290                                 if(lit <0x100) {
4291                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4292                                         
4293                                         //rFalseIfx.condition ^= 1;
4294                                         //genSkipCond(&rFalseIfx,left,size,7);
4295                                         //rFalseIfx.condition ^= 1;
4296                                         
4297                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4298                                         if(rFalseIfx.condition)
4299                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4300                                         else
4301                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4302                                         
4303                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4304                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4305                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4306                                         
4307                                         while(size > 1)
4308                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4309                                         
4310                                         if(rFalseIfx.condition) {
4311                                                 emitSKPZ;
4312                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4313                                                 
4314                                         } else {
4315                                                 emitSKPNZ;
4316                                         }
4317                                         
4318                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4319                                         emitpLabel(truelbl->key);
4320                                         if(ifx) ifx->generated = 1;
4321                                         return;
4322                                         
4323                                 }
4324                                 
4325                                 if(size == 1) {
4326                                         
4327                                         if( (lit & 0xff) == 0) {
4328                                                 /* lower byte is zero */
4329                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4330                                                 i = ((lit >> 8) & 0xff) ^0x80;
4331                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4332                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4333                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4334                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4335                                                 
4336                                                 
4337                                                 if(ifx) ifx->generated = 1;
4338                                                 return;
4339                                                 
4340                                         }
4341                                 } else {
4342                                         /* Special cases for signed longs */
4343                                         if( (lit & 0xffffff) == 0) {
4344                                                 /* lower byte is zero */
4345                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4346                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4347                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4348                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4349                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4350                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4351                                                 
4352                                                 
4353                                                 if(ifx) ifx->generated = 1;
4354                                                 return;
4355                                                 
4356                                         }
4357                                         
4358                                 }
4359                                 
4360                                 
4361                                 if(lit & (0x80 << (size*8))) {
4362                                         /* lit is negative */
4363                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4364                                         
4365                                         //genSkipCond(&rFalseIfx,left,size,7);
4366                                         
4367                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4368                                         
4369                                         if(rFalseIfx.condition)
4370                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4371                                         else
4372                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4373                                         
4374                                         
4375                                 } else {
4376                                         /* lit is positive */
4377                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4378                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4379                                         if(rFalseIfx.condition)
4380                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4381                                         else
4382                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4383                                         
4384                                 }
4385                                 
4386                                 /* There are no more special cases, so perform a general compare */
4387                                 
4388                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4389                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4390                                 
4391                                 while(size--) {
4392                                         
4393                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4394                                         emitSKPNZ;
4395                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4396                                 }
4397                                 //rFalseIfx.condition ^= 1;
4398                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4399                                 
4400                                 emitpLabel(truelbl->key);
4401                                 
4402                                 if(ifx) ifx->generated = 1;
4403                                 return;
4404                                 
4405                                 
4406                         }
4407
4408
4409                         /* sign is out of the way. So now do an unsigned compare */
4410                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4411
4412
4413                         /* General case - compare to an unsigned literal on the right.*/
4414
4415                         i = (lit >> (size*8)) & 0xff;
4416                         emitpcode(POC_MOVLW, popGetLit(i));
4417                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4418                         while(size--) {
4419                                 i = (lit >> (size*8)) & 0xff;
4420                                 
4421                                 if(i) {
4422                                         emitpcode(POC_MOVLW, popGetLit(i));
4423                                         emitSKPNZ;
4424                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4425                                 } else {
4426                                 /* this byte of the lit is zero, 
4427                                         *if it's not the last then OR in the variable */
4428                                         if(size)
4429                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4430                                 }
4431                         }
4432
4433
4434                 emitpLabel(lbl->key);
4435                 //if(emitFinalCheck)
4436                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4437                 if(sign)
4438                         emitpLabel(truelbl->key);
4439
4440                 if(ifx) ifx->generated = 1;
4441                 return;
4442
4443
4444                 }
4445 #endif  // _swapp
4446
4447                 if(AOP_TYPE(left) == AOP_LIT) {
4448                         //symbol *lbl = newiTempLabel(NULL);
4449                         
4450                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4451                         
4452                         
4453                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4454                         
4455                         /* Special cases */
4456                         if((lit == 0) && (sign == 0)){
4457                                 
4458                                 size--;
4459                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4460                                 while(size) 
4461                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4462                                 
4463                                 genSkipz2(&rFalseIfx,0);
4464                                 if(ifx) ifx->generated = 1;
4465                                 return;
4466                         }
4467                         
4468                         if(size==1) {
4469                                 /* Special cases */
4470                                 lit &= 0xff;
4471                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4472                                         /* degenerate compare can never be true */
4473                                         if(rFalseIfx.condition == 0)
4474                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4475                                         
4476                                         if(ifx) ifx->generated = 1;
4477                                         return;
4478                                 }
4479                                 
4480                                 if(sign) {
4481                                         /* signed comparisons to a literal byte */
4482                                         
4483                                         int lp1 = (lit+1) & 0xff;
4484                                         
4485                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4486                                         switch (lp1) {
4487                                         case 0:
4488                                                 rFalseIfx.condition ^= 1;
4489                                                 genSkipCond(&rFalseIfx,right,0,7);
4490                                                 break;
4491                                         case 0x7f:
4492                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4493                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4494                                                 genSkipz2(&rFalseIfx,1);
4495                                                 break;
4496                                         default:
4497                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4498                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4499                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4500                                                 rFalseIfx.condition ^= 1;
4501                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4502                                                 break;
4503                                         }
4504                                         if(ifx) ifx->generated = 1;
4505                                 } else {
4506                                         /* unsigned comparisons to a literal byte */
4507                                         
4508                                         switch(lit & 0xff ) {
4509                                         case 0:
4510                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4511                                                 genSkipz2(&rFalseIfx,0);
4512                                                 if(ifx) ifx->generated = 1;
4513                                                 break;
4514                                         case 0x7f:
4515                                                 genSkipCond(&rFalseIfx,right,0,7);
4516                                                 if(ifx) ifx->generated = 1;
4517                                                 break;
4518                                                 
4519                                         default:
4520                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4521                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4522                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4523                                                 rFalseIfx.condition ^= 1;
4524                                                 if (AOP_TYPE(result) == AOP_CRY) {
4525                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4526                                                         if(ifx) ifx->generated = 1;
4527                                                 } else {
4528                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4529                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4530                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4531                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4532                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4533                                                 }       
4534                                                 break;
4535                                         }
4536                                 }
4537                                 
4538                                 //goto check_carry;
4539                                 return;
4540                                 
4541                         } else {
4542                                 
4543                                 /* Size is greater than 1 */
4544                                 
4545                                 if(sign) {
4546                                         int lp1 = lit+1;
4547                                         
4548                                         size--;
4549                                         
4550                                         if(lp1 == 0) {
4551                                                 /* this means lit = 0xffffffff, or -1 */
4552                                                 
4553                                                 
4554                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4555                                                 rFalseIfx.condition ^= 1;
4556                                                 genSkipCond(&rFalseIfx,right,size,7);
4557                                                 if(ifx) ifx->generated = 1;
4558                                                 return;
4559                                         }
4560                                         
4561                                         if(lit == 0) {
4562                                                 int s = size;
4563                                                 
4564                                                 if(rFalseIfx.condition) {
4565                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4566                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4567                                                 }
4568                                                 
4569                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4570                                                 while(size--)
4571                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4572                                                 
4573                                                 
4574                                                 emitSKPZ;
4575                                                 if(rFalseIfx.condition) {
4576                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4577                                                         emitpLabel(truelbl->key);
4578                                                 }else {
4579                                                         rFalseIfx.condition ^= 1;
4580                                                         genSkipCond(&rFalseIfx,right,s,7);
4581                                                 }
4582                                                 
4583                                                 if(ifx) ifx->generated = 1;
4584                                                 return;
4585                                         }
4586                                         
4587                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4588                                                 /* lower byte of signed word is zero */
4589                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4590                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4591                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4592                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4593                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4594                                                 rFalseIfx.condition ^= 1;
4595                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4596                                                 
4597                                                 
4598                                                 if(ifx) ifx->generated = 1;
4599                                                 return;
4600                                         }
4601                                         
4602                                         if(lit & (0x80 << (size*8))) {
4603                                                 /* Lit is less than zero */
4604                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4605                                                 //rFalseIfx.condition ^= 1;
4606                                                 //genSkipCond(&rFalseIfx,left,size,7);
4607                                                 //rFalseIfx.condition ^= 1;
4608                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4609                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4610                                                 
4611                                                 if(rFalseIfx.condition)
4612                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4613                                                 else
4614                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4615                                                 
4616                                                 
4617                                         } else {
4618                                                 /* Lit is greater than or equal to zero */
4619                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4620                                                 //rFalseIfx.condition ^= 1;
4621                                                 //genSkipCond(&rFalseIfx,right,size,7);
4622                                                 //rFalseIfx.condition ^= 1;
4623                                                 
4624                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4625                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4626                                                 
4627                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4628                                                 if(rFalseIfx.condition)
4629                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4630                                                 else
4631                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4632                                                 
4633                                         }
4634                                         
4635                                         
4636                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4637                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4638                                         
4639                                         while(size--) {
4640                                                 
4641                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4642                                                 emitSKPNZ;
4643                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4644                                         }
4645                                         rFalseIfx.condition ^= 1;
4646                                         //rFalseIfx.condition = 1;
4647                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4648                                         
4649                                         emitpLabel(truelbl->key);
4650                                         
4651                                         if(ifx) ifx->generated = 1;
4652                                         return;
4653                                         // end of if (sign)
4654                                 } else {
4655                                         
4656                                         /* compare word or long to an unsigned literal on the right.*/
4657                                         
4658                                         
4659                                         size--;
4660                                         if(lit < 0xff) {
4661                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4662                                                 switch (lit) {
4663                                                 case 0:
4664                                                         break; /* handled above */
4665                                                 /*
4666                                                 case 0xff:
4667                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4668                                                         while(size--)
4669                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4670                                                         genSkipz2(&rFalseIfx,0);
4671                                                         break;
4672                                                 */
4673                                                 default:
4674                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4675                                                         while(--size)
4676                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4677                                                         
4678                                                         emitSKPZ;
4679                                                         if(rFalseIfx.condition)
4680                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4681                                                         else
4682                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4683                                                         
4684                                                         
4685                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4686                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4687                                                         
4688                                                         rFalseIfx.condition ^= 1;
4689                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4690                                                 }
4691                                                 
4692                                                 emitpLabel(truelbl->key);
4693                                                 
4694                                                 if(ifx) ifx->generated = 1;
4695                                                 return;
4696                                         }
4697                                         
4698                                         
4699                                         lit++;
4700                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4701                                         i = (lit >> (size*8)) & 0xff;
4702                                         
4703                                         emitpcode(POC_MOVLW, popGetLit(i));
4704                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4705                                         
4706                                         while(size--) {
4707                                                 i = (lit >> (size*8)) & 0xff;
4708                                                 
4709                                                 if(i) {
4710                                                         emitpcode(POC_MOVLW, popGetLit(i));
4711                                                         emitSKPNZ;
4712                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4713                                                 } else {
4714                                                 /* this byte of the lit is zero, 
4715                                                         *if it's not the last then OR in the variable */
4716                                                         if(size)
4717                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4718                                                 }
4719                                         }
4720                                         
4721                                         
4722                                         emitpLabel(lbl->key);
4723                                         
4724                                         rFalseIfx.condition ^= 1;
4725                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4726                                 }
4727                                 
4728                                 if(sign)
4729                                         emitpLabel(truelbl->key);
4730                                 if(ifx) ifx->generated = 1;
4731                                 return;
4732                         }
4733                 }
4734                 /* Compare two variables */
4735                 
4736                 DEBUGpic14_emitcode(";sign","%d",sign);
4737                 
4738                 size--;
4739                 if(sign) {
4740                         /* Sigh. thus sucks... */
4741                         if(size) {
4742                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4743                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4744                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4745                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4746                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4747                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4748                         } else {
4749                                 /* Signed char comparison */
4750                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4751                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4752                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4753                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4754                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4755                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4756                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4757                                 
4758                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4759                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4760                                 
4761                                 if(ifx) ifx->generated = 1;
4762                                 return;
4763                         }
4764                         
4765                 } else {
4766                         
4767                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4768                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4769                 }
4770                 
4771                 
4772                 /* The rest of the bytes of a multi-byte compare */
4773                 while (size) {
4774                         
4775                         emitSKPZ;
4776                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4777                         size--;
4778                         
4779                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4780                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4781                         
4782                         
4783                 }
4784                 
4785                 emitpLabel(lbl->key);
4786                 
4787                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4788                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4789                         (AOP_TYPE(result) == AOP_REG)) {
4790                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4791                         emitpcode(POC_RLF, popGet(AOP(result),0));
4792                 } else {
4793                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4794                 }       
4795                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4796                 if(ifx) ifx->generated = 1;
4797                 
4798                 return;
4799                 
4800         }
4801         
4802         // check_carry:
4803         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4804                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4805                 pic14_outBitC(result);
4806         } else {
4807                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4808                 /* if the result is used in the next
4809                 ifx conditional branch then generate
4810                 code a little differently */
4811                 if (ifx )
4812                         genIfxJump (ifx,"c");
4813                 else
4814                         pic14_outBitC(result);
4815                 /* leave the result in acc */
4816         }
4817         
4818 }
4819 #endif
4820
4821 /*-----------------------------------------------------------------*/
4822 /* genCmpGt :- greater than comparison                             */
4823 /*-----------------------------------------------------------------*/
4824 static void genCmpGt (iCode *ic, iCode *ifx)
4825 {
4826         operand *left, *right, *result;
4827         sym_link *letype , *retype;
4828         int sign ;
4829         
4830         FENTRY;
4831         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4832         left = IC_LEFT(ic);
4833         right= IC_RIGHT(ic);
4834         result = IC_RESULT(ic);
4835         
4836         letype = getSpec(operandType(left));
4837         retype =getSpec(operandType(right));
4838         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4839         /* assign the amsops */
4840         aopOp (left,ic,FALSE);
4841         aopOp (right,ic,FALSE);
4842         aopOp (result,ic,TRUE);
4843         
4844         genCmp(right, left, result, ifx, sign);
4845         
4846         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4847         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4848         freeAsmop(result,NULL,ic,TRUE); 
4849 }
4850
4851 /*-----------------------------------------------------------------*/
4852 /* genCmpLt - less than comparisons                                */
4853 /*-----------------------------------------------------------------*/
4854 static void genCmpLt (iCode *ic, iCode *ifx)
4855 {
4856         operand *left, *right, *result;
4857         sym_link *letype , *retype;
4858         int sign ;
4859         
4860         FENTRY;
4861         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4862         left = IC_LEFT(ic);
4863         right= IC_RIGHT(ic);
4864         result = IC_RESULT(ic);
4865         
4866         letype = getSpec(operandType(left));
4867         retype =getSpec(operandType(right));
4868         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4869         
4870         /* assign the amsops */
4871         aopOp (left,ic,FALSE);
4872         aopOp (right,ic,FALSE);
4873         aopOp (result,ic,TRUE);
4874         
4875         genCmp(left, right, result, ifx, sign);
4876         
4877         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4878         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4879         freeAsmop(result,NULL,ic,TRUE); 
4880 }
4881
4882 #if 0
4883 /*-----------------------------------------------------------------*/
4884 /* genc16bit2lit - compare a 16 bit value to a literal             */
4885 /*-----------------------------------------------------------------*/
4886 static void genc16bit2lit(operand *op, int lit, int offset)
4887 {
4888         int i;
4889         
4890         FENTRY;
4891         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4892         if( (lit&0xff) == 0) 
4893                 i=1;
4894         else
4895                 i=0;
4896         
4897         switch( BYTEofLONG(lit,i)) { 
4898         case 0:
4899                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4900                 break;
4901         case 1:
4902                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4903                 break;
4904         case 0xff:
4905                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4906                 break;
4907         default:
4908                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4909                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4910         }
4911         
4912         i ^= 1;
4913         
4914         switch( BYTEofLONG(lit,i)) { 
4915         case 0:
4916                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4917                 break;
4918         case 1:
4919                 emitSKPNZ;
4920                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4921                 break;
4922         case 0xff:
4923                 emitSKPNZ;
4924                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4925                 break;
4926         default:
4927                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4928                 emitSKPNZ;
4929                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4930                 
4931         }
4932         
4933 }
4934 #endif
4935
4936 #if 0
4937 /*-----------------------------------------------------------------*/
4938 /* gencjneshort - compare and jump if not equal                    */
4939 /*-----------------------------------------------------------------*/
4940 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4941 {
4942         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4943         int offset = 0;
4944         //resolvedIfx rIfx;
4945         symbol *lbl;
4946         
4947         //unsigned long lit = 0L;
4948         FENTRY;
4949         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4950           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4951           return;
4952         }
4953         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4954         DEBUGpic14_AopType(__LINE__,left,right,result);
4955         
4956         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4957         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4958         if (AOP_SIZE(result)) {
4959           for (offset = 0; offset < AOP_SIZE(result); offset++)
4960             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4961         }
4962         
4963         assert (AOP_SIZE(left) == AOP_SIZE(right));
4964         //resolveIfx(&rIfx,ifx);
4965         lbl = newiTempLabel (NULL);
4966         while (size--)
4967         {
4968           mov2w (AOP(right),size);
4969           emitpcode (POC_XORFW, popGet (AOP(left), size));
4970           if (size)
4971           {
4972             emitSKPZ;
4973             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4974           }
4975         } // while
4976         emitpLabel (lbl->key);
4977         if (AOP_SIZE(result)) {
4978           emitSKPNZ;
4979           emitpcode (POC_INCF, popGet (AOP(result), 0));
4980         } else {
4981           assert (ifx);
4982           genSkipz (ifx, NULL != IC_TRUE(ifx));
4983           ifx->generated = 1;
4984         }
4985         return;
4986 #if 0   
4987         if(result)
4988         {
4989                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4990                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4991                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4992                 for (offset=0; offset < AOP_SIZE(result); offset++)
4993                 {
4994                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4995                 } // for offset
4996         }
4997         
4998         
4999         /* if the left side is a literal or 
5000         if the right is in a pointer register and left 
5001         is not */
5002         if ((AOP_TYPE(left) == AOP_LIT) || 
5003                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5004                 operand *t = right;
5005                 right = left;
5006                 left = t;
5007         }
5008         if(AOP_TYPE(right) == AOP_LIT)
5009                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5010         
5011         /* if the right side is a literal then anything goes */
5012         if (AOP_TYPE(right) == AOP_LIT &&
5013                 AOP_TYPE(left) != AOP_DIR ) {
5014                 switch(size) {
5015                 case 2:
5016                         genc16bit2lit(left, lit, 0);
5017                         emitSKPNZ;
5018                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5019                         break;
5020                 default:
5021                         offset = 0;
5022                         while (size--) {
5023                                 if(lit & 0xff) {
5024                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5025                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5026                                 } else {
5027                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5028                                 }
5029                                 
5030                                 emitSKPNZ;
5031                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5032                                 offset++;
5033                                 lit >>= 8;
5034                         }
5035                         break;
5036                 }
5037         }
5038         
5039         /* if the right side is in a register or in direct space or
5040         if the left is a pointer register & right is not */    
5041         else if (AOP_TYPE(right) == AOP_REG ||
5042                 AOP_TYPE(right) == AOP_DIR || 
5043                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5044                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5045                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5046                 int lbl_key = lbl->key;
5047                 
5048                 if(!result) {
5049                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5050                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5051                                 __FUNCTION__,__LINE__);
5052                         return;
5053                 }
5054                 
5055                 /*     switch(size) { */
5056                 /*     case 2: */
5057                 /*       genc16bit2lit(left, lit, 0); */
5058                 /*       emitSKPNZ; */
5059                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5060                 /*       break; */
5061                 /*     default: */
5062                 offset = 0;
5063                 while (size--) {
5064                         int emit_skip=1;
5065                         if((AOP_TYPE(left) == AOP_DIR) && 
5066                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5067                                 
5068                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5069                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5070                                 
5071                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5072                                 
5073                                 switch (lit & 0xff) {
5074                                 case 0:
5075                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5076                                         break;
5077                                 case 1:
5078                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5079                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5080                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5081                                         emit_skip=0;
5082                                         break;
5083                                 case 0xff:
5084                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5085                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5086                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5087                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5088                                         emit_skip=0;
5089                                         break;
5090                                 default:
5091                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5092                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5093                                 }
5094                                 lit >>= 8;
5095                                 
5096                         } else {
5097                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5098                         }
5099                         if(emit_skip) {
5100                                 if(AOP_TYPE(result) == AOP_CRY) {
5101                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5102                                         if(rIfx.condition)
5103                                                 emitSKPNZ;
5104                                         else
5105                                                 emitSKPZ;
5106                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5107                                 } else {
5108                                         /* fix me. probably need to check result size too */
5109                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5110                                         if(rIfx.condition)
5111                                                 emitSKPZ;
5112                                         else
5113                                                 emitSKPNZ;
5114                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5115                                 }
5116                                 if(ifx)
5117                                         ifx->generated=1;
5118                         }
5119                         emit_skip++;
5120                         offset++;
5121                 }
5122                 /*       break; */
5123                 /*     } */
5124         } else if(AOP_TYPE(right) == AOP_REG &&
5125                 AOP_TYPE(left) != AOP_DIR){
5126
5127                 offset = 0;
5128                 while(size--) {
5129                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5130                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5131                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5132                         if(rIfx.condition)
5133                                 emitSKPNZ;
5134                         else
5135                                 emitSKPZ;
5136                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5137                         offset++;
5138                 }
5139                 
5140         }else{
5141                 /* right is a pointer reg need both a & b */
5142                 offset = 0;
5143                 while(size--) {
5144                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5145                         if(strcmp(l,"b"))
5146                                 pic14_emitcode("mov","b,%s",l);
5147                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5148                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5149                         offset++;
5150                 }
5151         }
5152         
5153         emitpcode(POC_INCF,popGet(AOP(result),0));
5154         if(!rIfx.condition)
5155                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5156         
5157         emitpLabel(lbl->key);
5158         
5159         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5160         
5161         if(ifx)
5162                 ifx->generated = 1;
5163 #endif
5164 }
5165 #endif
5166
5167 #if 0
5168 /*-----------------------------------------------------------------*/
5169 /* gencjne - compare and jump if not equal                         */
5170 /*-----------------------------------------------------------------*/
5171 static void gencjne(operand *left, operand *right, iCode *ifx)
5172 {
5173         symbol *tlbl  = newiTempLabel(NULL);
5174         
5175         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5176         gencjneshort(left, right, lbl);
5177         
5178         pic14_emitcode("mov","a,%s",one);
5179         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5180         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5181         pic14_emitcode("clr","a");
5182         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5183         
5184         emitpLabel(lbl->key);
5185         emitpLabel(tlbl->key);
5186         
5187 }
5188 #endif
5189
5190 /*-----------------------------------------------------------------*/
5191 /* genCmpEq - generates code for equal to                          */
5192 /*-----------------------------------------------------------------*/
5193 static void genCmpEq (iCode *ic, iCode *ifx)
5194 {
5195   operand *left, *right, *result;
5196   int size;
5197   symbol *false_label;
5198
5199   FENTRY;
5200   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5201
5202   if(ifx)
5203     DEBUGpic14_emitcode ("; ifx is non-null","");
5204   else
5205     DEBUGpic14_emitcode ("; ifx is null","");
5206
5207   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5208   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5209   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5210
5211   DEBUGpic14_AopType(__LINE__,left,right,result);
5212
5213   /* if literal, move literal to right */ 
5214   if (op_isLitLike (IC_LEFT(ic))) {
5215     operand *tmp = right ;
5216     right = left;
5217     left = tmp;
5218   }
5219
5220   false_label = NULL;
5221   if (ifx && !IC_TRUE(ifx))
5222   {
5223     assert (IC_FALSE(ifx));
5224     false_label = IC_FALSE(ifx);
5225   }
5226
5227   size = min(AOP_SIZE(left),AOP_SIZE(right));
5228   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5229   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5230
5231   /* assume left != right */
5232   {
5233     int i;
5234     for (i=0; i < AOP_SIZE(result); i++)
5235     {
5236       emitpcode(POC_CLRF, popGet(AOP(result),i));
5237     }
5238   }
5239
5240   if (AOP_TYPE(right) == AOP_LIT)
5241   {
5242     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5243     int i;
5244     size = AOP_SIZE(left);
5245     assert(!op_isLitLike(left));
5246
5247     switch (lit)
5248     {
5249       case 0:
5250         mov2w(AOP(left), 0);
5251         for (i=1; i < size; i++)
5252           emitpcode(POC_IORFW,popGet(AOP(left),i));
5253         /* now Z is set iff `left == right' */
5254         emitSKPZ;
5255         if (!false_label) false_label = newiTempLabel(NULL);
5256         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5257         break;
5258
5259       default:
5260         for (i=0; i < size; i++)
5261         {
5262           mov2w(AOP(left),i);
5263           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5264           /* now Z is cleared if `left != right' */
5265           emitSKPZ;
5266           if (!false_label) false_label = newiTempLabel(NULL);
5267           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5268         } // for i
5269         break;
5270     } // switch (lit)
5271   }
5272   else
5273   {
5274     /* right is no literal */
5275     int i;
5276
5277     for (i=0; i < size; i++)
5278     {
5279       mov2w(AOP(right),i);
5280       emitpcode(POC_XORFW,popGet(AOP(left),i));
5281       /* now Z is cleared if `left != right' */
5282       emitSKPZ;
5283       if (!false_label) false_label = newiTempLabel(NULL);
5284       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5285     } // for i
5286   }
5287
5288   /* if we reach here, left == right */
5289
5290   if (AOP_SIZE(result) > 0)
5291   {
5292     emitpcode(POC_INCF, popGet(AOP(result),0));
5293   }
5294
5295   if (ifx && IC_TRUE(ifx))
5296   {
5297     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5298   }
5299
5300   if (false_label && (!ifx || IC_TRUE(ifx)))
5301     emitpLabel(false_label->key);
5302
5303   if (ifx) ifx->generated = 1;
5304
5305   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5306   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5307   freeAsmop(result,NULL,ic,TRUE);
5308 }
5309
5310 /*-----------------------------------------------------------------*/
5311 /* ifxForOp - returns the icode containing the ifx for operand     */
5312 /*-----------------------------------------------------------------*/
5313 static iCode *ifxForOp ( operand *op, iCode *ic )
5314 {
5315         FENTRY;
5316         /* if true symbol then needs to be assigned */
5317         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5318         if (IS_TRUE_SYMOP(op))
5319                 return NULL ;
5320         
5321         /* if this has register type condition and
5322         the next instruction is ifx with the same operand
5323         and live to of the operand is upto the ifx only then */
5324         if (ic->next &&
5325                 ic->next->op == IFX &&
5326                 IC_COND(ic->next)->key == op->key &&
5327                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5328                 return ic->next;
5329         
5330         if (ic->next &&
5331                 ic->next->op == IFX &&
5332                 IC_COND(ic->next)->key == op->key) {
5333                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5334                 return ic->next;
5335         }
5336         
5337         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5338         if (ic->next &&
5339                 ic->next->op == IFX)
5340                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5341         
5342         if (ic->next &&
5343                 ic->next->op == IFX &&
5344                 IC_COND(ic->next)->key == op->key) {
5345                 DEBUGpic14_emitcode ("; "," key is okay");
5346                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5347                         OP_SYMBOL(op)->liveTo,
5348                         ic->next->seq);
5349         }
5350         
5351         
5352         return NULL;
5353 }
5354 /*-----------------------------------------------------------------*/
5355 /* genAndOp - for && operation                                     */
5356 /*-----------------------------------------------------------------*/
5357 static void genAndOp (iCode *ic)
5358 {
5359         operand *left,*right, *result;
5360         /*     symbol *tlbl; */
5361         
5362         FENTRY;
5363         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5364         /* note here that && operations that are in an
5365         if statement are taken away by backPatchLabels
5366         only those used in arthmetic operations remain */
5367         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5368         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5369         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5370         
5371         DEBUGpic14_AopType(__LINE__,left,right,result);
5372         
5373         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5374         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5375         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5376         
5377         /* if both are bit variables */
5378         /*     if (AOP_TYPE(left) == AOP_CRY && */
5379         /*         AOP_TYPE(right) == AOP_CRY ) { */
5380         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5381         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5382         /*         pic14_outBitC(result); */
5383         /*     } else { */
5384         /*         tlbl = newiTempLabel(NULL); */
5385         /*         pic14_toBoolean(left);     */
5386         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5387         /*         pic14_toBoolean(right); */
5388         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5389         /*         pic14_outBitAcc(result); */
5390         /*     } */
5391         
5392         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5393         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5394         freeAsmop(result,NULL,ic,TRUE);
5395 }
5396
5397
5398 /*-----------------------------------------------------------------*/
5399 /* genOrOp - for || operation                                      */
5400 /*-----------------------------------------------------------------*/
5401 /*
5402 tsd pic port -
5403 modified this code, but it doesn't appear to ever get called
5404 */
5405
5406 static void genOrOp (iCode *ic)
5407 {
5408         operand *left,*right, *result;
5409         symbol *tlbl;
5410         int i;
5411         
5412         /* note here that || operations that are in an
5413         if statement are taken away by backPatchLabels
5414         only those used in arthmetic operations remain */
5415         FENTRY;
5416         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5417         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5418         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5419         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5420         
5421         DEBUGpic14_AopType(__LINE__,left,right,result);
5422
5423         for (i=0; i < AOP_SIZE(result); i++)
5424         {
5425                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5426         } // for i
5427
5428         tlbl = newiTempLabel(NULL);
5429         pic14_toBoolean(left);
5430         emitSKPZ;
5431         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5432         pic14_toBoolean(right);
5433         emitpLabel(tlbl->key);
5434         /* here Z is clear IFF `left || right' */
5435         emitSKPZ;
5436         emitpcode(POC_INCF, popGet(AOP(result), 0));
5437         
5438         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5439         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5440         freeAsmop(result,NULL,ic,TRUE);            
5441 }
5442
5443 /*-----------------------------------------------------------------*/
5444 /* isLiteralBit - test if lit == 2^n                               */
5445 /*-----------------------------------------------------------------*/
5446 static int isLiteralBit(unsigned long lit)
5447 {
5448         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5449                 0x100L,0x200L,0x400L,0x800L,
5450                 0x1000L,0x2000L,0x4000L,0x8000L,
5451                 0x10000L,0x20000L,0x40000L,0x80000L,
5452                 0x100000L,0x200000L,0x400000L,0x800000L,
5453                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5454                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5455         int idx;
5456         
5457         FENTRY;
5458         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5459         for(idx = 0; idx < 32; idx++)
5460                 if(lit == pw[idx])
5461                         return idx+1;
5462                 return 0;
5463 }
5464
5465 /*-----------------------------------------------------------------*/
5466 /* continueIfTrue -                                                */
5467 /*-----------------------------------------------------------------*/
5468 static void continueIfTrue (iCode *ic)
5469 {
5470         FENTRY;
5471         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5472         if(IC_TRUE(ic))
5473                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5474         ic->generated = 1;
5475 }
5476
5477 /*-----------------------------------------------------------------*/
5478 /* jmpIfTrue -                                                     */
5479 /*-----------------------------------------------------------------*/
5480 static void jumpIfTrue (iCode *ic)
5481 {
5482         FENTRY;
5483         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5484         if(!IC_TRUE(ic))
5485                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5486         ic->generated = 1;
5487 }
5488
5489 /*-----------------------------------------------------------------*/
5490 /* jmpTrueOrFalse -                                                */
5491 /*-----------------------------------------------------------------*/
5492 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5493 {
5494         FENTRY;
5495         // ugly but optimized by peephole
5496         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5497         if(IC_TRUE(ic)){
5498                 symbol *nlbl = newiTempLabel(NULL);
5499                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5500                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5501                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5502                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5503         }
5504         else{
5505                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5506                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5507         }
5508         ic->generated = 1;
5509 }
5510
5511 /*-----------------------------------------------------------------*/
5512 /* genAnd  - code for and                                          */
5513 /*-----------------------------------------------------------------*/
5514 static void genAnd (iCode *ic, iCode *ifx)
5515 {
5516         operand *left, *right, *result;
5517         int size, offset=0;  
5518         unsigned long lit = 0L;
5519         int bytelit = 0;
5520         resolvedIfx rIfx;
5521         
5522         FENTRY;
5523         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5524         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5525         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5526         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5527         
5528         resolveIfx(&rIfx,ifx);
5529         
5530         /* if left is a literal & right is not then exchange them */
5531         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5532                 AOP_NEEDSACC(left)) {
5533                 operand *tmp = right ;
5534                 right = left;
5535                 left = tmp;
5536         }
5537         
5538         /* if result = right then exchange them */
5539         if(pic14_sameRegs(AOP(result),AOP(right))){
5540                 operand *tmp = right ;
5541                 right = left;
5542                 left = tmp;
5543         }
5544         
5545         /* if right is bit then exchange them */
5546         if (AOP_TYPE(right) == AOP_CRY &&
5547                 AOP_TYPE(left) != AOP_CRY){
5548                 operand *tmp = right ;
5549                 right = left;
5550                 left = tmp;
5551         }
5552         if(AOP_TYPE(right) == AOP_LIT)
5553                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5554         
5555         size = AOP_SIZE(result);
5556         
5557         DEBUGpic14_AopType(__LINE__,left,right,result);
5558         
5559         // if(bit & yy)
5560         // result = bit & yy;
5561         if (AOP_TYPE(left) == AOP_CRY){
5562                 // c = bit & literal;
5563                 if(AOP_TYPE(right) == AOP_LIT){
5564                         if(lit & 1) {
5565                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5566                                         // no change
5567                                         goto release;
5568                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5569                         } else {
5570                                 // bit(result) = 0;
5571                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5572                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5573                                         goto release;
5574                                 }
5575                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5576                                         jumpIfTrue(ifx);
5577                                         goto release;
5578                                 }
5579                                 pic14_emitcode("clr","c");
5580                         }
5581                 } else {
5582                         if (AOP_TYPE(right) == AOP_CRY){
5583                                 // c = bit & bit;
5584                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5585                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5586                         } else {
5587                                 // c = bit & val;
5588                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5589                                 // c = lsb
5590                                 pic14_emitcode("rrc","a");
5591                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5592                         }
5593                 }
5594                 // bit = c
5595                 // val = c
5596                 if(size)
5597                         pic14_outBitC(result);
5598                 // if(bit & ...)
5599                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5600                         genIfxJump(ifx, "c");           
5601                 goto release ;
5602         }
5603         
5604         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5605         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5606         if((AOP_TYPE(right) == AOP_LIT) &&
5607                 (AOP_TYPE(result) == AOP_CRY) &&
5608                 (AOP_TYPE(left) != AOP_CRY)){
5609                 int posbit = isLiteralBit(lit);
5610                 /* left &  2^n */
5611                 if(posbit){
5612                         posbit--;
5613                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5614                         // bit = left & 2^n
5615                         if(size)
5616                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5617                         // if(left &  2^n)
5618                         else{
5619                                 if(ifx){
5620                                         int offset = 0;
5621                                         while (posbit > 7) {
5622                                                 posbit -= 8;
5623                                                 offset++;
5624                                         }
5625                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5626                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5627                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5628                                         
5629                                         ifx->generated = 1;
5630                                 }
5631                                 goto release;
5632                         }
5633                 } else {
5634                         symbol *tlbl = newiTempLabel(NULL);
5635                         int sizel = AOP_SIZE(left);
5636                         if(size)
5637                                 pic14_emitcode("setb","c");
5638                         while(sizel--){
5639                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5640                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5641                                         // byte ==  2^n ?
5642                                         if((posbit = isLiteralBit(bytelit)) != 0)
5643                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5644                                         else{
5645                                                 if(bytelit != 0x0FFL)
5646                                                         pic14_emitcode("anl","a,%s",
5647                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5648                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5649                                         }
5650                                 }
5651                                 offset++;
5652                         }
5653                         // bit = left & literal
5654                         if(size){
5655                                 pic14_emitcode("clr","c");
5656                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5657                         }
5658                         // if(left & literal)
5659                         else{
5660                                 if(ifx)
5661                                         jmpTrueOrFalse(ifx, tlbl);
5662                                 goto release ;
5663                         }
5664                 }
5665                 pic14_outBitC(result);
5666                 goto release ;
5667         }
5668         
5669         /* if left is same as result */
5670         if(pic14_sameRegs(AOP(result),AOP(left))){
5671                 int know_W = -1;
5672                 for(;size--; offset++,lit>>=8) {
5673                         if(AOP_TYPE(right) == AOP_LIT){
5674                                 switch(lit & 0xff) {
5675                                 case 0x00:
5676                                         /*  and'ing with 0 has clears the result */
5677                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5678                                         break;
5679                                 case 0xff:
5680                                         /* and'ing with 0xff is a nop when the result and left are the same */
5681                                         break;
5682                                         
5683                                 default:
5684                                         {
5685                                                 int p = my_powof2( (~lit) & 0xff );
5686                                                 if(p>=0) {
5687                                                         /* only one bit is set in the literal, so use a bcf instruction */
5688                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5689                                                         
5690                                                 } else {
5691                                                         if(know_W != (int)(lit&0xff))
5692                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5693                                                         know_W = lit &0xff;
5694                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5695                                                 }
5696                                         }    
5697                                 }
5698                         } else {
5699                                 if (AOP_TYPE(left) == AOP_ACC) {
5700                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5701                                 } else {        
5702                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5703                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5704                                         
5705                                 }
5706                         }
5707                 }
5708                 
5709         } else {
5710                 // left & result in different registers
5711                 if(AOP_TYPE(result) == AOP_CRY){
5712                         // result = bit
5713                         // if(size), result in bit
5714                         // if(!size && ifx), conditional oper: if(left & right)
5715                         symbol *tlbl = newiTempLabel(NULL);
5716                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5717                         if(size)
5718                                 pic14_emitcode("setb","c");
5719                         while(sizer--){
5720                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5721                                 pic14_emitcode("anl","a,%s",
5722                                         aopGet(AOP(left),offset,FALSE,FALSE));
5723                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5724                                 offset++;
5725                         }
5726                         if(size){
5727                                 CLRC;
5728                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5729                                 pic14_outBitC(result);
5730                         } else if(ifx)
5731                                 jmpTrueOrFalse(ifx, tlbl);
5732                 } else {
5733                         for(;(size--);offset++) {
5734                                 // normal case
5735                                 // result = left & right
5736                                 if(AOP_TYPE(right) == AOP_LIT){
5737                                         int t = (lit >> (offset*8)) & 0x0FFL;
5738                                         switch(t) { 
5739                                         case 0x00:
5740                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5741                                                 break;
5742                                         case 0xff:
5743                                                 if(AOP_TYPE(left) != AOP_ACC) {
5744                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5745                                                 }
5746                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5747                                                 break;
5748                                         default:
5749                                                 if(AOP_TYPE(left) == AOP_ACC) {
5750                                                         emitpcode(POC_ANDLW, popGetLit(t));
5751                                                 } else {
5752                                                         emitpcode(POC_MOVLW, popGetLit(t));
5753                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5754                                                 }
5755                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5756                                         }
5757                                         continue;
5758                                 }
5759                                 
5760                                 if (AOP_TYPE(left) == AOP_ACC) {
5761                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5762                                 } else {
5763                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5764                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5765                                 }
5766                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5767                         }
5768                 }
5769         }
5770         
5771 release :
5772         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5773         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5774         freeAsmop(result,NULL,ic,TRUE);     
5775 }
5776
5777 /*-----------------------------------------------------------------*/
5778 /* genOr  - code for or                                            */
5779 /*-----------------------------------------------------------------*/
5780 static void genOr (iCode *ic, iCode *ifx)
5781 {
5782         operand *left, *right, *result;
5783         int size, offset=0;
5784         unsigned long lit = 0L;
5785         
5786         FENTRY;
5787         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5788         
5789         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5790         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5791         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5792         
5793         DEBUGpic14_AopType(__LINE__,left,right,result);
5794         
5795         /* if left is a literal & right is not then exchange them */
5796         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5797                 AOP_NEEDSACC(left)) {
5798                 operand *tmp = right ;
5799                 right = left;
5800                 left = tmp;
5801         }
5802         
5803         /* if result = right then exchange them */
5804         if(pic14_sameRegs(AOP(result),AOP(right))){
5805                 operand *tmp = right ;
5806                 right = left;
5807                 left = tmp;
5808         }
5809         
5810         /* if right is bit then exchange them */
5811         if (AOP_TYPE(right) == AOP_CRY &&
5812                 AOP_TYPE(left) != AOP_CRY){
5813                 operand *tmp = right ;
5814                 right = left;
5815                 left = tmp;
5816         }
5817         
5818         DEBUGpic14_AopType(__LINE__,left,right,result);
5819         
5820         if(AOP_TYPE(right) == AOP_LIT)
5821                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5822         
5823         size = AOP_SIZE(result);
5824         
5825         // if(bit | yy)
5826         // xx = bit | yy;
5827         if (AOP_TYPE(left) == AOP_CRY){
5828                 if(AOP_TYPE(right) == AOP_LIT){
5829                         // c = bit & literal;
5830                         if(lit){
5831                                 // lit != 0 => result = 1
5832                                 if(AOP_TYPE(result) == AOP_CRY){
5833                                         if(size)
5834                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5835                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5836                                         //   AOP(result)->aopu.aop_dir,
5837                                         //   AOP(result)->aopu.aop_dir);
5838                                         else if(ifx)
5839                                                 continueIfTrue(ifx);
5840                                         goto release;
5841                                 }
5842                         } else {
5843                                 // lit == 0 => result = left
5844                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5845                                         goto release;
5846                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5847                         }
5848                 } else {
5849                         if (AOP_TYPE(right) == AOP_CRY){
5850                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5851                                         // c = bit | bit;
5852                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5853                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5854                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5855                                         
5856                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5857                                                 AOP(result)->aopu.aop_dir,
5858                                                 AOP(result)->aopu.aop_dir);
5859                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5860                                                 AOP(right)->aopu.aop_dir,
5861                                                 AOP(right)->aopu.aop_dir);
5862                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5863                                                 AOP(result)->aopu.aop_dir,
5864                                                 AOP(result)->aopu.aop_dir);
5865                                 } else {
5866                                         if( AOP_TYPE(result) == AOP_ACC) {
5867                                                 emitpcode(POC_MOVLW, popGetLit(0));
5868                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5869                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5870                                                 emitpcode(POC_MOVLW, popGetLit(1));
5871                                                 
5872                                         } else {
5873                                                 
5874                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5875                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5876                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5877                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5878                                                 
5879                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5880                                                         AOP(result)->aopu.aop_dir,
5881                                                         AOP(result)->aopu.aop_dir);
5882                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5883                                                         AOP(right)->aopu.aop_dir,
5884                                                         AOP(right)->aopu.aop_dir);
5885                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5886                                                         AOP(left)->aopu.aop_dir,
5887                                                         AOP(left)->aopu.aop_dir);
5888                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5889                                                         AOP(result)->aopu.aop_dir,
5890                                                         AOP(result)->aopu.aop_dir);
5891                                         }
5892                                 }
5893                         } else {
5894                                 // c = bit | val;
5895                                 symbol *tlbl = newiTempLabel(NULL);
5896                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5897                                 
5898                                 
5899                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5900                                 if( AOP_TYPE(right) == AOP_ACC) {
5901                                         emitpcode(POC_IORLW, popGetLit(0));
5902                                         emitSKPNZ;
5903                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5904                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5905                                 }
5906                                 
5907                                 
5908                                 
5909                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5910                                         pic14_emitcode(";XXX setb","c");
5911                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5912                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5913                                 pic14_toBoolean(right);
5914                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5915                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5916                                         jmpTrueOrFalse(ifx, tlbl);
5917                                         goto release;
5918                                 } else {
5919                                         CLRC;
5920                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5921                                 }
5922                         }
5923                 }
5924                 // bit = c
5925                 // val = c
5926                 if(size)
5927                         pic14_outBitC(result);
5928                 // if(bit | ...)
5929                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5930                         genIfxJump(ifx, "c");           
5931                 goto release ;
5932         }
5933
5934         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5935         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5936         if((AOP_TYPE(right) == AOP_LIT) &&
5937           (AOP_TYPE(result) == AOP_CRY) &&
5938           (AOP_TYPE(left) != AOP_CRY)){
5939                 if(lit){
5940                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5941                         // result = 1
5942                         if(size)
5943                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5944                         else 
5945                                 continueIfTrue(ifx);
5946                         goto release;
5947                 } else {
5948                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5949                         // lit = 0, result = boolean(left)
5950                         if(size)
5951                                 pic14_emitcode(";XXX setb","c");
5952                         pic14_toBoolean(right);
5953                         if(size){
5954                                 symbol *tlbl = newiTempLabel(NULL);
5955                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5956                                 CLRC;
5957                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5958                         } else {
5959                                 genIfxJump (ifx,"a");
5960                                 goto release;
5961                         }
5962                 }
5963                 pic14_outBitC(result);
5964                 goto release ;
5965         }
5966
5967         /* if left is same as result */
5968         if(pic14_sameRegs(AOP(result),AOP(left))){
5969                 int know_W = -1;
5970                 for(;size--; offset++,lit>>=8) {
5971                         if(AOP_TYPE(right) == AOP_LIT){
5972                                 if((lit & 0xff) == 0)
5973                                         /*  or'ing with 0 has no effect */
5974                                         continue;
5975                                 else {
5976                                         int p = my_powof2(lit & 0xff);
5977                                         if(p>=0) {
5978                                                 /* only one bit is set in the literal, so use a bsf instruction */
5979                                                 emitpcode(POC_BSF,
5980                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5981                                         } else {
5982                                                 if(know_W != (int)(lit & 0xff))
5983                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5984                                                 know_W = lit & 0xff;
5985                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5986                                         }
5987                                         
5988                                 }
5989                         } else {
5990                                 if (AOP_TYPE(left) == AOP_ACC) {
5991                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5992                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5993                                 } else {        
5994                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5995                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5996                                         
5997                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5998                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5999                                         
6000                                 }
6001                         }
6002                 }
6003         } else {
6004                 // left & result in different registers
6005                 if(AOP_TYPE(result) == AOP_CRY){
6006                         // result = bit
6007                         // if(size), result in bit
6008                         // if(!size && ifx), conditional oper: if(left | right)
6009                         symbol *tlbl = newiTempLabel(NULL);
6010                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6011                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6012                         
6013                         
6014                         if(size)
6015                                 pic14_emitcode(";XXX setb","c");
6016                         while(sizer--){
6017                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6018                                 pic14_emitcode(";XXX orl","a,%s",
6019                                         aopGet(AOP(left),offset,FALSE,FALSE));
6020                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6021                                 offset++;
6022                         }
6023                         if(size){
6024                                 CLRC;
6025                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6026                                 pic14_outBitC(result);
6027                         } else if(ifx)
6028                                 jmpTrueOrFalse(ifx, tlbl);
6029                 } else for(;(size--);offset++){
6030                         // normal case
6031                         // result = left | right
6032                         if(AOP_TYPE(right) == AOP_LIT){
6033                                 int t = (lit >> (offset*8)) & 0x0FFL;
6034                                 switch(t) { 
6035                                 case 0x00:
6036                                         if (AOP_TYPE(left) != AOP_ACC) {
6037                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6038                                         }
6039                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6040                                         
6041                                         break;
6042                                 default:
6043                                         if (AOP_TYPE(left) == AOP_ACC) {
6044                                                 emitpcode(POC_IORLW,  popGetLit(t));
6045                                         } else {
6046                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6047                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6048                                         }
6049                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6050                                 }
6051                                 continue;
6052                         }
6053                         
6054                         // faster than result <- left, anl result,right
6055                         // and better if result is SFR
6056                         if (AOP_TYPE(left) == AOP_ACC) {
6057                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6058                         } else {
6059                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6060                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6061                         }
6062                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6063                 }
6064         }
6065
6066 release :
6067         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6068         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6069         freeAsmop(result,NULL,ic,TRUE);     
6070 }
6071
6072 /*-----------------------------------------------------------------*/
6073 /* genXor - code for xclusive or                                   */
6074 /*-----------------------------------------------------------------*/
6075 static void genXor (iCode *ic, iCode *ifx)
6076 {
6077         operand *left, *right, *result;
6078         int size, offset=0;
6079         unsigned long lit = 0L;
6080         
6081         FENTRY;
6082         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6083         
6084         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6085         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6086         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6087         
6088         /* if left is a literal & right is not ||
6089         if left needs acc & right does not */
6090         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6091                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6092                 operand *tmp = right ;
6093                 right = left;
6094                 left = tmp;
6095         }
6096         
6097         /* if result = right then exchange them */
6098         if(pic14_sameRegs(AOP(result),AOP(right))){
6099                 operand *tmp = right ;
6100                 right = left;
6101                 left = tmp;
6102         }
6103         
6104         /* if right is bit then exchange them */
6105         if (AOP_TYPE(right) == AOP_CRY &&
6106                 AOP_TYPE(left) != AOP_CRY){
6107                 operand *tmp = right ;
6108                 right = left;
6109                 left = tmp;
6110         }
6111         if(AOP_TYPE(right) == AOP_LIT)
6112                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6113         
6114         size = AOP_SIZE(result);
6115         
6116         // if(bit ^ yy)
6117         // xx = bit ^ yy;
6118         if (AOP_TYPE(left) == AOP_CRY){
6119                 if(AOP_TYPE(right) == AOP_LIT){
6120                         // c = bit & literal;
6121                         if(lit>>1){
6122                                 // lit>>1  != 0 => result = 1
6123                                 if(AOP_TYPE(result) == AOP_CRY){
6124                                         if(size)
6125                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6126                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6127                                         else if(ifx)
6128                                                 continueIfTrue(ifx);
6129                                         goto release;
6130                                 }
6131                                 pic14_emitcode("setb","c");
6132                         } else{
6133                                 // lit == (0 or 1)
6134                                 if(lit == 0){
6135                                         // lit == 0, result = left
6136                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6137                                                 goto release;
6138                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6139                                 } else{
6140                                         // lit == 1, result = not(left)
6141                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6142                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6143                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6144                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6145                                                 goto release;
6146                                         } else {
6147                                                 assert ( !"incomplete genXor" );
6148                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6149                                                 pic14_emitcode("cpl","c");
6150                                         }
6151                                 }
6152                         }
6153                         
6154                 } else {
6155                         // right != literal
6156                         symbol *tlbl = newiTempLabel(NULL);
6157                         if (AOP_TYPE(right) == AOP_CRY){
6158                                 // c = bit ^ bit;
6159                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6160                         }
6161                         else{
6162                                 int sizer = AOP_SIZE(right);
6163                                 // c = bit ^ val
6164                                 // if val>>1 != 0, result = 1
6165                                 pic14_emitcode("setb","c");
6166                                 while(sizer){
6167                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6168                                         if(sizer == 1)
6169                                                 // test the msb of the lsb
6170                                                 pic14_emitcode("anl","a,#0xfe");
6171                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6172                                         sizer--;
6173                                 }
6174                                 // val = (0,1)
6175                                 pic14_emitcode("rrc","a");
6176                         }
6177                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6178                         pic14_emitcode("cpl","c");
6179                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6180                 }
6181                 // bit = c
6182                 // val = c
6183                 if(size)
6184                         pic14_outBitC(result);
6185                 // if(bit | ...)
6186                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6187                         genIfxJump(ifx, "c");           
6188                 goto release ;
6189         }
6190         
6191         if(pic14_sameRegs(AOP(result),AOP(left))){
6192                 /* if left is same as result */
6193                 for(;size--; offset++) {
6194                         if(AOP_TYPE(right) == AOP_LIT){
6195                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6196                                 if(t == 0x00L)
6197                                         continue;
6198                                 else
6199                                         if (IS_AOP_PREG(left)) {
6200                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6201                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6202                                                 aopPut(AOP(result),"a",offset);
6203                                         } else {
6204                                                 emitpcode(POC_MOVLW, popGetLit(t));
6205                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6206                                                 pic14_emitcode("xrl","%s,%s",
6207                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6208                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6209                                         }
6210                         } else {
6211                                 if (AOP_TYPE(left) == AOP_ACC)
6212                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6213                                 else {
6214                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6215                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6216                                         /*
6217                                         if (IS_AOP_PREG(left)) {
6218                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6219                                         aopPut(AOP(result),"a",offset);
6220                                         } else
6221                                         pic14_emitcode("xrl","%s,a",
6222                                         aopGet(AOP(left),offset,FALSE,TRUE));
6223                                         */
6224                                 }
6225                         }
6226                 }
6227         } else {
6228                 // left & result in different registers
6229                 if(AOP_TYPE(result) == AOP_CRY){
6230                         // result = bit
6231                         // if(size), result in bit
6232                         // if(!size && ifx), conditional oper: if(left ^ right)
6233                         symbol *tlbl = newiTempLabel(NULL);
6234                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6235                         if(size)
6236                                 pic14_emitcode("setb","c");
6237                         while(sizer--){
6238                                 if((AOP_TYPE(right) == AOP_LIT) &&
6239                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6240                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6241                                 } else {
6242                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6243                                         pic14_emitcode("xrl","a,%s",
6244                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6245                                 }
6246                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6247                                 offset++;
6248                         }
6249                         if(size){
6250                                 CLRC;
6251                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6252                                 pic14_outBitC(result);
6253                         } else if(ifx)
6254                                 jmpTrueOrFalse(ifx, tlbl);
6255                 } else for(;(size--);offset++){
6256                         // normal case
6257                         // result = left & right
6258                         if(AOP_TYPE(right) == AOP_LIT){
6259                                 int t = (lit >> (offset*8)) & 0x0FFL;
6260                                 switch(t) { 
6261                                 case 0x00:
6262                                         if (AOP_TYPE(left) != AOP_ACC) {
6263                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6264                                         }
6265                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6266                                         pic14_emitcode("movf","%s,w",
6267                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6268                                         pic14_emitcode("movwf","%s",
6269                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6270                                         break;
6271                                 case 0xff:
6272                                         if (AOP_TYPE(left) == AOP_ACC) {
6273                                                 emitpcode(POC_XORLW, popGetLit(t));
6274                                         } else {
6275                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6276                                         }
6277                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6278                                         break;
6279                                 default:
6280                                         if (AOP_TYPE(left) == AOP_ACC) {
6281                                                 emitpcode(POC_XORLW, popGetLit(t));
6282                                         } else {
6283                                                 emitpcode(POC_MOVLW, popGetLit(t));
6284                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6285                                         }
6286                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6287                                         pic14_emitcode("movlw","0x%x",t);
6288                                         pic14_emitcode("xorwf","%s,w",
6289                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6290                                         pic14_emitcode("movwf","%s",
6291                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6292                                         
6293                                 }
6294                                 continue;
6295                         }
6296                         
6297                         // faster than result <- left, anl result,right
6298                         // and better if result is SFR
6299                         if (AOP_TYPE(left) == AOP_ACC) {
6300                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6301                         } else {
6302                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6303                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6304                         }
6305                         if ( AOP_TYPE(result) != AOP_ACC){
6306                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6307                         }
6308                 }
6309         }
6310         
6311 release :
6312         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6313         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6314         freeAsmop(result,NULL,ic,TRUE);     
6315 }
6316
6317 /*-----------------------------------------------------------------*/
6318 /* genInline - write the inline code out                           */
6319 /*-----------------------------------------------------------------*/
6320 static void genInline (iCode *ic)
6321 {
6322   char *buffer, *bp, *bp1;
6323
6324   FENTRY;
6325   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6326
6327   _G.inLine += (!options.asmpeep);
6328
6329   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6330   strcpy(buffer,IC_INLINE(ic));
6331
6332   /* emit each line as a code */
6333   while (*bp) {
6334     if (*bp == '\n') {
6335       *bp++ = '\0';
6336       
6337       if(*bp1)
6338         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6339       bp1 = bp;
6340     } else {
6341       if (*bp == ':') {
6342         bp++;
6343         *bp = '\0';
6344         bp++;
6345
6346         /* print label, use this special format with NULL directive
6347          * to denote that the argument should not be indented with tab */
6348         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6349
6350         bp1 = bp;
6351       } else
6352         bp++;
6353     }
6354   }
6355   if ((bp1 != bp) && *bp1)
6356     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6357
6358   Safe_free(buffer);
6359
6360   _G.inLine -= (!options.asmpeep);
6361 }
6362
6363 /*-----------------------------------------------------------------*/
6364 /* genRRC - rotate right with carry                                */
6365 /*-----------------------------------------------------------------*/
6366 static void genRRC (iCode *ic)
6367 {
6368         operand *left , *result ;
6369         int size, offset = 0, same;
6370         
6371         FENTRY;
6372         /* rotate right with carry */
6373         left = IC_LEFT(ic);
6374         result=IC_RESULT(ic);
6375         aopOp (left,ic,FALSE);
6376         aopOp (result,ic,FALSE);
6377         
6378         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6379         
6380         same = pic14_sameRegs(AOP(result),AOP(left));
6381         
6382         size = AOP_SIZE(result);    
6383         
6384         /* get the lsb and put it into the carry */
6385         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6386         
6387         offset = 0 ;
6388         
6389         while(size--) {
6390                 
6391                 if(same) {
6392                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6393                 } else {
6394                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6395                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6396                 }
6397                 
6398                 offset++;
6399         }
6400         
6401         freeAsmop(left,NULL,ic,TRUE);
6402         freeAsmop(result,NULL,ic,TRUE);
6403 }
6404
6405 /*-----------------------------------------------------------------*/
6406 /* genRLC - generate code for rotate left with carry               */
6407 /*-----------------------------------------------------------------*/
6408 static void genRLC (iCode *ic)
6409 {    
6410         operand *left , *result ;
6411         int size, offset = 0;
6412         int same;
6413         
6414         FENTRY;
6415         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6416         /* rotate right with carry */
6417         left = IC_LEFT(ic);
6418         result=IC_RESULT(ic);
6419         aopOp (left,ic,FALSE);
6420         aopOp (result,ic,FALSE);
6421         
6422         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6423         
6424         same = pic14_sameRegs(AOP(result),AOP(left));
6425         
6426         /* move it to the result */
6427         size = AOP_SIZE(result);    
6428         
6429         /* get the msb and put it into the carry */
6430         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6431         
6432         offset = 0 ;
6433         
6434         while(size--) {
6435                 
6436                 if(same) {
6437                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6438                 } else {
6439                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6440                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6441                 }
6442                 
6443                 offset++;
6444         }
6445         
6446         
6447         freeAsmop(left,NULL,ic,TRUE);
6448         freeAsmop(result,NULL,ic,TRUE);
6449 }
6450
6451 /*-----------------------------------------------------------------*/
6452 /* genGetHbit - generates code get highest order bit               */
6453 /*-----------------------------------------------------------------*/
6454 static void genGetHbit (iCode *ic)
6455 {
6456         operand *left, *result;
6457         left = IC_LEFT(ic);
6458         result=IC_RESULT(ic);
6459         aopOp (left,ic,FALSE);
6460         aopOp (result,ic,FALSE);
6461         
6462         FENTRY;
6463         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6464         /* get the highest order byte into a */
6465         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6466         if(AOP_TYPE(result) == AOP_CRY){
6467                 pic14_emitcode("rlc","a");
6468                 pic14_outBitC(result);
6469         }
6470         else{
6471                 pic14_emitcode("rl","a");
6472                 pic14_emitcode("anl","a,#0x01");
6473                 pic14_outAcc(result);
6474         }
6475         
6476         
6477         freeAsmop(left,NULL,ic,TRUE);
6478         freeAsmop(result,NULL,ic,TRUE);
6479 }
6480
6481 /*-----------------------------------------------------------------*/
6482 /* AccLsh - shift left accumulator by known count                  */
6483 /* MARK: pic14 always rotates through CARRY!                       */
6484 /*-----------------------------------------------------------------*/
6485 static void AccLsh (pCodeOp *pcop,int shCount)
6486 {
6487         FENTRY;
6488         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6489         shCount &= 0x0007;              // shCount : 0..7
6490         switch(shCount){
6491         case 0 :
6492                 return;
6493                 break;
6494         case 1 :
6495                 emitCLRC;
6496                 emitpcode(POC_RLF,pcop);
6497                 return;
6498                 break;
6499         case 2 :
6500                 emitpcode(POC_RLF,pcop);
6501                 emitpcode(POC_RLF,pcop);
6502                 break;
6503         case 3 :
6504                 emitpcode(POC_RLF,pcop);
6505                 emitpcode(POC_RLF,pcop);
6506                 emitpcode(POC_RLF,pcop);
6507                 break;
6508         case 4 :
6509                 emitpcode(POC_SWAPF,pcop);
6510                 break;
6511         case 5 :
6512                 emitpcode(POC_SWAPF,pcop);
6513                 emitpcode(POC_RLF,pcop);
6514                 break;
6515         case 6 :
6516                 emitpcode(POC_SWAPF,pcop);
6517                 emitpcode(POC_RLF,pcop);
6518                 emitpcode(POC_RLF,pcop);
6519                 break;
6520         case 7 :
6521                 emitpcode(POC_RRFW,pcop);
6522                 emitpcode(POC_RRF,pcop);
6523                 break;
6524         }
6525         /* clear invalid bits */
6526         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6527         emitpcode(POC_ANDWF, pcop);
6528 }
6529
6530 /*-----------------------------------------------------------------*/
6531 /* AccRsh - shift right accumulator by known count                 */
6532 /* MARK: pic14 always rotates through CARRY!                       */
6533 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6534 /*            1: mask out invalid bits (zero-extend)               */
6535 /*            2: sign-extend result (pretty slow)                  */
6536 /*-----------------------------------------------------------------*/
6537 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6538 {
6539         FENTRY;
6540         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6541         shCount &= 0x0007;              // shCount : 0..7
6542         switch(shCount){
6543         case 0 :
6544                 return;
6545                 break;
6546         case 1 :
6547                 /* load sign if needed */
6548                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6549                 else if (mask_mode == 1) emitCLRC;
6550                 emitpcode(POC_RRF,pcop);
6551                 return;
6552                 break;
6553         case 2 :
6554                 /* load sign if needed */
6555                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6556                 emitpcode(POC_RRF,pcop);
6557                 /* load sign if needed */
6558                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6559                 emitpcode(POC_RRF,pcop);
6560                 if (mask_mode == 2) return;
6561                 break;
6562         case 3 :
6563                 /* load sign if needed */
6564                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6565                 emitpcode(POC_RRF,pcop);
6566                 /* load sign if needed */
6567                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6568                 emitpcode(POC_RRF,pcop);
6569                 /* load sign if needed */
6570                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6571                 emitpcode(POC_RRF,pcop);
6572                 if (mask_mode == 2) return;
6573                 break;
6574         case 4 :
6575                 emitpcode(POC_SWAPF,pcop);
6576                 break;
6577         case 5 :
6578                 emitpcode(POC_SWAPF,pcop);
6579                 emitpcode(POC_RRF,pcop);
6580                 break;
6581         case 6 :
6582                 emitpcode(POC_SWAPF,pcop);
6583                 emitpcode(POC_RRF,pcop);
6584                 emitpcode(POC_RRF,pcop);
6585                 break;
6586         case 7 :
6587                 if (mask_mode == 2)
6588                 {
6589                         /* load sign */
6590                         emitpcode(POC_RLFW,pcop);
6591                         emitpcode(POC_CLRF,pcop);
6592                         emitSKPNC;
6593                         emitpcode(POC_COMF,pcop);
6594                         return;
6595                 } else {
6596                         emitpcode(POC_RLFW,pcop);
6597                         emitpcode(POC_RLF,pcop);
6598                 }
6599                 break;
6600         }
6601
6602         if (mask_mode == 0)
6603         {
6604                 /* leave invalid bits undefined */
6605                 return;
6606         }
6607         
6608         /* clear invalid bits -- zero-extend */
6609         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6610         emitpcode(POC_ANDWF, pcop);
6611
6612         if (mask_mode == 2) {
6613           /* sign-extend */
6614           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6615           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6616           emitpcode(POC_IORWF, pcop);
6617         }
6618 }
6619
6620 #if 0
6621 /*-----------------------------------------------------------------*/
6622 /* AccSRsh - signed right shift accumulator by known count                 */
6623 /*-----------------------------------------------------------------*/
6624 static void AccSRsh (int shCount)
6625 {
6626         symbol *tlbl ;
6627         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6628         if(shCount != 0){
6629                 if(shCount == 1){
6630                         pic14_emitcode("mov","c,acc.7");
6631                         pic14_emitcode("rrc","a");
6632                 } else if(shCount == 2){
6633                         pic14_emitcode("mov","c,acc.7");
6634                         pic14_emitcode("rrc","a");
6635                         pic14_emitcode("mov","c,acc.7");
6636                         pic14_emitcode("rrc","a");
6637                 } else {
6638                         tlbl = newiTempLabel(NULL);
6639                         /* rotate right accumulator */
6640                         AccRol(8 - shCount);
6641                         /* and kill the higher order bits */
6642                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6643                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6644                         pic14_emitcode("orl","a,#0x%02x",
6645                                 (unsigned char)~SRMask[shCount]);
6646                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6647                 }
6648         }
6649 }
6650
6651 /*-----------------------------------------------------------------*/
6652 /* shiftR1Left2Result - shift right one byte from left to result   */
6653 /*-----------------------------------------------------------------*/
6654 static void shiftR1Left2ResultSigned (operand *left, int offl,
6655                                                                           operand *result, int offr,
6656                                                                           int shCount)
6657 {
6658         int same;
6659         
6660         FENTRY;
6661         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6662         
6663         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6664         
6665         switch(shCount) {
6666         case 1:
6667                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6668                 if(same) 
6669                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6670                 else {
6671                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6672                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6673                 }
6674                 
6675                 break;
6676         case 2:
6677                 
6678                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6679                 if(same) 
6680                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6681                 else {
6682                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6683                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6684                 }
6685                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6686                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6687                 
6688                 break;
6689                 
6690         case 3:
6691                 if(same)
6692                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6693                 else {
6694                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6695                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6696                 }
6697                 
6698                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6699                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6700                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6701                 
6702                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6703                 emitpcode(POC_IORLW, popGetLit(0xe0));
6704                 
6705                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6706                 break;
6707                 
6708         case 4:
6709                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6710                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6711                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6712                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6713                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6714                 break;
6715         case 5:
6716                 if(same) {
6717                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6718                 } else {
6719                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6720                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6721                 }
6722                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6723                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6724                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6725                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6726                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6727                 break;
6728                 
6729         case 6:
6730                 if(same) {
6731                         emitpcode(POC_MOVLW, popGetLit(0x00));
6732                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6733                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6734                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6735                         emitpcode(POC_IORLW, popGetLit(0x01));
6736                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6737                 } else {
6738                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6739                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6740                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6741                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6742                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6743                 }
6744                 break;
6745                 
6746         case 7:
6747                 if(same) {
6748                         emitpcode(POC_MOVLW, popGetLit(0x00));
6749                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6750                         emitpcode(POC_MOVLW, popGetLit(0xff));
6751                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6752                 } else {
6753                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6754                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6755                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6756                 }
6757                 
6758         default:
6759                 break;
6760         }
6761 }
6762
6763 /*-----------------------------------------------------------------*/
6764 /* shiftR1Left2Result - shift right one byte from left to result   */
6765 /*-----------------------------------------------------------------*/
6766 static void shiftR1Left2Result (operand *left, int offl,
6767                                                                 operand *result, int offr,
6768                                                                 int shCount, int sign)
6769 {
6770         int same;
6771         
6772         FENTRY;
6773         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6774         
6775         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6776         
6777         /* Copy the msb into the carry if signed. */
6778         if(sign) {
6779                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6780                 return;
6781         }
6782         
6783         
6784         
6785         switch(shCount) {
6786         case 1:
6787                 emitCLRC;
6788                 if(same) 
6789                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6790                 else {
6791                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6792                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6793                 }
6794                 break;
6795         case 2:
6796                 emitCLRC;
6797                 if(same) {
6798                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6799                 } else {
6800                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6801                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6802                 }
6803                 emitCLRC;
6804                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6805                 
6806                 break;
6807         case 3:
6808                 if(same)
6809                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6810                 else {
6811                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6812                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6813                 }
6814                 
6815                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6816                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6817                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6818                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6819                 break;
6820                 
6821         case 4:
6822                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6823                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6824                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6825                 break;
6826                 
6827         case 5:
6828                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6829                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6830                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6831                 emitCLRC;
6832                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6833                 
6834                 break;
6835         case 6:
6836                 
6837                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6838                 emitpcode(POC_ANDLW, popGetLit(0x80));
6839                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6840                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6841                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6842                 break;
6843                 
6844         case 7:
6845                 
6846                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6847                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6848                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6849                 
6850                 break;
6851                 
6852         default:
6853                 break;
6854         }
6855 }
6856
6857 /*-----------------------------------------------------------------*/
6858 /* shiftL1Left2Result - shift left one byte from left to result    */
6859 /*-----------------------------------------------------------------*/
6860 static void shiftL1Left2Result (operand *left, int offl,
6861                                                                 operand *result, int offr, int shCount)
6862 {
6863         int same;
6864         
6865         //    char *l;
6866         FENTRY;
6867         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6868         
6869         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6870         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6871         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6872         //    MOVA(l);
6873         /* shift left accumulator */
6874         //AccLsh(shCount); // don't comment out just yet...
6875         //    aopPut(AOP(result),"a",offr);
6876         
6877         switch(shCount) {
6878         case 1:
6879                 /* Shift left 1 bit position */
6880                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6881                 if(same) {
6882                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6883                 } else {
6884                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6885                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6886                 }
6887                 break;
6888         case 2:
6889                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6890                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6891                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6892                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6893                 break;
6894         case 3:
6895                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6896                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6897                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6898                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6899                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6900                 break;
6901         case 4:
6902                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6903                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6904                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6905                 break;
6906         case 5:
6907                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6908                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6909                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6910                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6911                 break;
6912         case 6:
6913                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6914                 emitpcode(POC_ANDLW, popGetLit(0x30));
6915                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6916                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6917                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6918                 break;
6919         case 7:
6920                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6921                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6922                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6923                 break;
6924                 
6925         default:
6926                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6927         }
6928         
6929 }
6930 #endif
6931
6932 /*-----------------------------------------------------------------*/
6933 /* movLeft2Result - move byte from left to result                  */
6934 /*-----------------------------------------------------------------*/
6935 static void movLeft2Result (operand *left, int offl,
6936                                                         operand *result, int offr)
6937 {
6938         char *l;
6939         FENTRY;
6940         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6941         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6942                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6943                 
6944                 if (*l == '@' && (IS_AOP_PREG(result))) {
6945                         pic14_emitcode("mov","a,%s",l);
6946                         aopPut(AOP(result),"a",offr);
6947                 } else {
6948                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6949                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6950                 }
6951         }
6952 }
6953
6954 /*-----------------------------------------------------------------*/
6955 /* shiftLeft_Left2ResultLit - shift left by known count            */
6956 /*-----------------------------------------------------------------*/
6957
6958 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6959 {
6960         int size, same, offr, i;
6961
6962         size = AOP_SIZE(left);
6963         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6964         
6965         same = pic14_sameRegs (AOP(left), AOP(result));
6966         
6967         offr = shCount / 8;
6968         shCount = shCount & 0x07;
6969
6970         size -= offr;
6971
6972         switch (shCount)
6973         {
6974         case 0: /* takes 0 or 2N cycles (for offr==0) */
6975                 if (!same || offr) {
6976                         for (i=size-1; i >= 0; i--)
6977                                 movLeft2Result (left, i, result, offr + i);
6978                 } // if
6979                 break;
6980                 
6981         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6982                 if (same && offr) {
6983                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6984                         shiftLeft_Left2ResultLit (result, result, shCount);
6985                         return; /* prevent clearing result again */
6986                 } else {
6987                         emitCLRC;
6988                         for (i=0; i < size; i++) {
6989                                 if (same && !offr) {
6990                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6991                                 } else {
6992                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6993                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6994                                 } // if
6995                         } // for
6996                 } // if (offr)
6997                 break;
6998                 
6999         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7000                 /* works in-place/with offr as well */
7001                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7002                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7003                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7004
7005                 for (i = size - 2; i >= 0; i--)
7006                 {
7007                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7008                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7009                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7010                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7011                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7012                 } // for i
7013                 break;
7014                 
7015         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7016                 /* works in-place/with offr as well */
7017                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7018                 for (i = size-2; i >= 0; i--) {
7019                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7020                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7021                 } // for i
7022                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7023                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7024                 break;
7025         
7026         default:
7027                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7028                 shiftLeft_Left2ResultLit (result, result, 1);
7029                 return; /* prevent clearing result again */
7030                 break;
7031         } // switch
7032
7033         while (0 < offr--)
7034         {
7035                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7036         } // while
7037 }
7038
7039 /*-----------------------------------------------------------------*/
7040 /* shiftRight_Left2ResultLit - shift right by known count          */
7041 /*-----------------------------------------------------------------*/
7042
7043 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7044 {
7045         int size, same, offr, i;
7046
7047         size = AOP_SIZE(left);
7048         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7049         
7050         same = pic14_sameRegs (AOP(left), AOP(result));
7051         
7052         offr = shCount / 8;
7053         shCount = shCount & 0x07;
7054
7055         size -= offr;
7056
7057         if (size)
7058         {
7059                 switch (shCount)
7060                 {
7061                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7062                         if (!same || offr) {
7063                                 for (i=0; i < size; i++)
7064                                         movLeft2Result (left, i + offr, result, i);
7065                         } // if
7066                         break;
7067                         
7068                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7069                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7070                         if (same && offr) {
7071                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7072                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7073                                 return; /* prevent sign-extending result again */
7074                         } else {
7075                                 emitCLRC;
7076                                 if (sign) {
7077                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7078                                         emitSETC;
7079                                 }
7080                                 for (i = size-1; i >= 0; i--) {
7081                                         if (same && !offr) {
7082                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7083                                         } else {
7084                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7085                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7086                                         }
7087                                 } // for i
7088                         } // if (offr)
7089                         break;
7090                         
7091                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7092                         /* works in-place/with offr as well */
7093                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7094                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7095                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7096
7097                         for (i = 1; i < size; i++)
7098                         {
7099                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7100                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7101                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7102                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7103                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7104                         } // for i
7105
7106                         if (sign)
7107                         {
7108                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7109                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7110                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7111                         } // if
7112                         break;
7113                         
7114                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7115                         /* works in-place/with offr as well */
7116                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7117                         for (i = 0; i < size-1; i++) {
7118                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7119                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7120                         } // for i
7121                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7122                         if (!sign) {
7123                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7124                         } else {
7125                                 emitSKPNC;
7126                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7127                         }
7128                         break;
7129                 
7130                 default:
7131                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7132                         shiftRight_Left2ResultLit (result, result, 1, sign);
7133                         return; /* prevent sign extending result again */
7134                         break;
7135                 } // switch
7136         } // if
7137
7138         addSign (result, size, sign);
7139 }
7140
7141 #if 0
7142 /*-----------------------------------------------------------------*/
7143 /* shiftL2Left2Result - shift left two bytes from left to result   */
7144 /*-----------------------------------------------------------------*/
7145 static void shiftL2Left2Result (operand *left, int offl,
7146                                                                 operand *result, int offr, int shCount)
7147 {
7148         FENTRY;
7149         
7150         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7151         
7152         if(pic14_sameRegs(AOP(result), AOP(left))) {
7153                 switch(shCount) {
7154                 case 0:
7155                         break;
7156                 case 1:
7157                 case 2:
7158                 case 3:
7159                         
7160                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7161                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7162                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7163                         
7164                         while(--shCount) {
7165                                 emitCLRC;
7166                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7167                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7168                         }
7169                         
7170                         break;
7171                 case 4:
7172                 case 5:
7173                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7174                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7175                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7176                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7177                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7178                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7179                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7180                         if(shCount >=5) {
7181                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7182                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7183                         }
7184                         break;
7185                 case 6:
7186                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7187                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7188                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7189                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7190                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7191                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7192                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7193                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7194                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7195                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7196                         break;
7197                 case 7:
7198                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7199                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7200                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7201                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7202                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7203                 }
7204                 
7205         } else {
7206                 switch(shCount) {
7207                 case 0:
7208                         break;
7209                 case 1:
7210                 case 2:
7211                 case 3:
7212                 /* note, use a mov/add for the shift since the mov has a
7213                         chance of getting optimized out */
7214                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7215                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7216                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7217                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7218                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7219                         
7220                         while(--shCount) {
7221                                 emitCLRC;
7222                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7223                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7224                         }
7225                         break;
7226                         
7227                 case 4:
7228                 case 5:
7229                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7230                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7231                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7232                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7233                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7234                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7235                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7236                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7237                         
7238                         
7239                         if(shCount == 5) {
7240                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7241                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7242                         }
7243                         break;
7244                 case 6:
7245                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7246                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7247                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7248                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7249                         
7250                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7251                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7252                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7253                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7254                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7255                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7256                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7257                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7258                         break;
7259                 case 7:
7260                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7261                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7262                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7263                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7264                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7265                 }
7266         }
7267         
7268 }
7269
7270 /*-----------------------------------------------------------------*/
7271 /* shiftR2Left2Result - shift right two bytes from left to result  */
7272 /*-----------------------------------------------------------------*/
7273 static void shiftR2Left2Result (operand *left, int offl,
7274                                                                 operand *result, int offr,
7275                                                                 int shCount, int sign)
7276 {
7277         int same=0;
7278         
7279         FENTRY;
7280         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7281         same = pic14_sameRegs(AOP(result), AOP(left));
7282         
7283         if(same && ((offl + MSB16) == offr)){
7284                 same=1;
7285                 /* don't crash result[offr] */
7286                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7287                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7288         }
7289         /* else {
7290         movLeft2Result(left,offl, result, offr);
7291         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7292         }
7293         */
7294         /* a:x >> shCount (x = lsb(result))*/
7295         /*
7296         if(sign)
7297         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7298         else {
7299         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7300         */
7301         switch(shCount) {
7302         case 0:
7303                 break;
7304         case 1:
7305         case 2:
7306         case 3:
7307                 if(sign)
7308                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7309                 else
7310                         emitCLRC;
7311                 
7312                 if(same) {
7313                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7314                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7315                 } else {
7316                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7317                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7318                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7319                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7320                 }
7321                 
7322                 while(--shCount) {
7323                         if(sign)
7324                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7325                         else
7326                                 emitCLRC;
7327                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7328                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7329                 }
7330                 break;
7331         case 4:
7332         case 5:
7333                 if(same) {
7334                         
7335                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7336                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7337                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7338                         
7339                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7340                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7341                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7342                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7343                 } else {
7344                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7345                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7346                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7347                         
7348                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7349                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7350                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7351                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7352                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7353                 }
7354                 
7355                 if(shCount >=5) {
7356                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7357                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7358                 }
7359                 
7360                 if(sign) {
7361                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7362                         emitpcode(POC_BTFSC, 
7363                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7364                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7365                 }
7366                 
7367                 break;
7368                 
7369         case 6:
7370                 if(same) {
7371                         
7372                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7373                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7374                         
7375                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7376                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7377                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7378                         emitpcode(POC_ANDLW,popGetLit(0x03));
7379                         if(sign) {
7380                                 emitpcode(POC_BTFSC, 
7381                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7382                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7383                         }
7384                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7385                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7386                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7387                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7388                 } else {
7389                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7390                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7391                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7392                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7393                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7394                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7395                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7396                         emitpcode(POC_ANDLW,popGetLit(0x03));
7397                         if(sign) {
7398                                 emitpcode(POC_BTFSC, 
7399                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7400                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7401                         }
7402                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7403                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7404                         
7405                         
7406                 }
7407                 
7408                 break;
7409         case 7:
7410                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7411                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7412                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7413                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7414                 if(sign) {
7415                         emitSKPNC;
7416                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7417                 } else 
7418                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7419   }
7420 }
7421
7422 /*-----------------------------------------------------------------*/
7423 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7424 /*-----------------------------------------------------------------*/
7425 static void shiftLLeftOrResult (operand *left, int offl,
7426                                                                 operand *result, int offr, int shCount)
7427 {
7428         FENTRY;
7429         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7430         
7431         /* shift left accumulator */
7432         AccLsh(left,offl,shCount);
7433         /* or with result */
7434         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7435         assert ( !"broken (modifies left, fails for left==result))" );
7436 }
7437
7438 /*-----------------------------------------------------------------*/
7439 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7440 /*-----------------------------------------------------------------*/
7441 static void shiftRLeftOrResult (operand *left, int offl,
7442                                                                 operand *result, int offr, int shCount)
7443 {
7444         FENTRY;
7445         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7446         
7447         /* shift right accumulator */
7448         AccRsh(left,offl,shCount);
7449         /* or with result */
7450         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7451         assert ( !"broken (modifies left, fails for left==result))" );
7452 }
7453
7454 /*-----------------------------------------------------------------*/
7455 /* genlshOne - left shift a one byte quantity by known count       */
7456 /*-----------------------------------------------------------------*/
7457 static void genlshOne (operand *result, operand *left, int shCount)
7458 {       
7459         FENTRY;
7460         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7461         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7462 }
7463
7464 /*-----------------------------------------------------------------*/
7465 /* genlshTwo - left shift two bytes by known amount != 0           */
7466 /*-----------------------------------------------------------------*/
7467 static void genlshTwo (operand *result,operand *left, int shCount)
7468 {
7469         int size;
7470         
7471         FENTRY;
7472         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7473         size = pic14_getDataSize(result);
7474         
7475         /* if shCount >= 8 */
7476         if (shCount >= 8) {
7477                 shCount -= 8 ;
7478                 
7479                 if (size > 1){
7480                         if (shCount)
7481                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7482                         else 
7483                                 movLeft2Result(left, LSB, result, MSB16);
7484                 }
7485                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7486         }
7487         
7488         /*  1 <= shCount <= 7 */
7489         else {  
7490                 if(size == 1)
7491                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7492                 else 
7493                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7494         }
7495 }
7496
7497 /*-----------------------------------------------------------------*/
7498 /* shiftLLong - shift left one long from left to result            */
7499 /* offl = LSB or MSB16                                             */
7500 /*-----------------------------------------------------------------*/
7501 static void shiftLLong (operand *left, operand *result, int offr )
7502 {
7503         char *l;
7504         int size = AOP_SIZE(result);
7505         
7506         FENTRY;
7507         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7508         if(size >= LSB+offr){
7509                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7510                 MOVA(l);
7511                 pic14_emitcode("add","a,acc");
7512                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7513                         size >= MSB16+offr && offr != LSB )
7514                         pic14_emitcode("xch","a,%s",
7515                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7516                 else      
7517                         aopPut(AOP(result),"a",LSB+offr);
7518         }
7519         
7520         if(size >= MSB16+offr){
7521                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7522                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7523                         MOVA(l);
7524                 }
7525                 pic14_emitcode("rlc","a");
7526                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7527                         size >= MSB24+offr && offr != LSB)
7528                         pic14_emitcode("xch","a,%s",
7529                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7530                 else      
7531                         aopPut(AOP(result),"a",MSB16+offr);
7532         }
7533         
7534         if(size >= MSB24+offr){
7535                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7536                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7537                         MOVA(l);
7538                 }
7539                 pic14_emitcode("rlc","a");
7540                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7541                         size >= MSB32+offr && offr != LSB )
7542                         pic14_emitcode("xch","a,%s",
7543                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7544                 else      
7545                         aopPut(AOP(result),"a",MSB24+offr);
7546         }
7547         
7548         if(size > MSB32+offr){
7549                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7550                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7551                         MOVA(l);  
7552                 }
7553                 pic14_emitcode("rlc","a");
7554                 aopPut(AOP(result),"a",MSB32+offr);
7555         }
7556         if(offr != LSB)
7557                 aopPut(AOP(result),zero,LSB);       
7558 }
7559
7560 /*-----------------------------------------------------------------*/
7561 /* genlshFour - shift four byte by a known amount != 0             */
7562 /*-----------------------------------------------------------------*/
7563 static void genlshFour (operand *result, operand *left, int shCount)
7564 {
7565         int size;
7566         
7567         FENTRY;
7568         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7569         size = AOP_SIZE(result);
7570         
7571         /* if shifting more that 3 bytes */
7572         if (shCount >= 24 ) {
7573                 shCount -= 24;
7574                 if (shCount)
7575                 /* lowest order of left goes to the highest
7576                 order of the destination */
7577                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7578                 else
7579                         movLeft2Result(left, LSB, result, MSB32);
7580                 aopPut(AOP(result),zero,LSB);
7581                 aopPut(AOP(result),zero,MSB16);
7582                 aopPut(AOP(result),zero,MSB32);
7583                 return;
7584         }
7585         
7586         /* more than two bytes */
7587         else if ( shCount >= 16 ) {
7588                 /* lower order two bytes goes to higher order two bytes */
7589                 shCount -= 16;
7590                 /* if some more remaining */
7591                 if (shCount)
7592                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7593                 else {
7594                         movLeft2Result(left, MSB16, result, MSB32);
7595                         movLeft2Result(left, LSB, result, MSB24);
7596                 }
7597                 aopPut(AOP(result),zero,MSB16);
7598                 aopPut(AOP(result),zero,LSB);
7599                 return;
7600         }    
7601         
7602         /* if more than 1 byte */
7603         else if ( shCount >= 8 ) {
7604                 /* lower order three bytes goes to higher order  three bytes */
7605                 shCount -= 8;
7606                 if(size == 2){
7607                         if(shCount)
7608                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7609                         else
7610                                 movLeft2Result(left, LSB, result, MSB16);
7611                 }
7612                 else{   /* size = 4 */
7613                         if(shCount == 0){
7614                                 movLeft2Result(left, MSB24, result, MSB32);
7615                                 movLeft2Result(left, MSB16, result, MSB24);
7616                                 movLeft2Result(left, LSB, result, MSB16);
7617                                 aopPut(AOP(result),zero,LSB);
7618                         }
7619                         else if(shCount == 1)
7620                                 shiftLLong(left, result, MSB16);
7621                         else{
7622                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7623                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7624                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7625                                 aopPut(AOP(result),zero,LSB);
7626                         }
7627                 }
7628         }
7629         
7630         /* 1 <= shCount <= 7 */
7631         else if(shCount <= 2){
7632                 shiftLLong(left, result, LSB);
7633                 if(shCount == 2)
7634                         shiftLLong(result, result, LSB);
7635         }
7636         /* 3 <= shCount <= 7, optimize */
7637         else{
7638                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7639                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7640                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7641         }
7642 }
7643 #endif
7644
7645 #if 0
7646 /*-----------------------------------------------------------------*/
7647 /* genLeftShiftLiteral - left shifting by known count              */
7648 /*-----------------------------------------------------------------*/
7649 static void genLeftShiftLiteral (operand *left,
7650                                                                  operand *right,
7651                                                                  operand *result,
7652                                                                  iCode *ic)
7653 {    
7654         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7655         //int size;
7656         
7657         FENTRY;
7658         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7659         freeAsmop(right,NULL,ic,TRUE);
7660         
7661         aopOp(left,ic,FALSE);
7662         aopOp(result,ic,FALSE);
7663
7664         size = getSize(operandType(result));
7665         
7666 #if VIEW_SIZE
7667         pic14_emitcode("; shift left ","result %d, left %d",size,
7668                 AOP_SIZE(left));
7669 #endif
7670         
7671         /* I suppose that the left size >= result size */
7672         if(shCount == 0){
7673                 while(size--){
7674                         movLeft2Result(left, size, result, size);
7675                 }
7676         }
7677         
7678         else if(shCount >= (size * 8))
7679                 while(size--)
7680                         aopPut(AOP(result),zero,size);
7681                 else{
7682                         switch (size) {
7683                         case 1:
7684                                 genlshOne (result,left,shCount);
7685                                 break;
7686                                 
7687                         case 2:
7688                         case 3:
7689                                 genlshTwo (result,left,shCount);
7690                                 break;
7691                                 
7692                         case 4:
7693                                 genlshFour (result,left,shCount);
7694                                 break;
7695                         }
7696                 }
7697                 freeAsmop(left,NULL,ic,TRUE);
7698                 freeAsmop(result,NULL,ic,TRUE);
7699 }
7700 #endif
7701
7702 /*-----------------------------------------------------------------*
7703 * genMultiAsm - repeat assembly instruction for size of register.
7704 * if endian == 1, then the high byte (i.e base address + size of 
7705 * register) is used first else the low byte is used first;
7706 *-----------------------------------------------------------------*/
7707 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7708 {
7709         
7710         int offset = 0;
7711         
7712         FENTRY;
7713         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7714         
7715         if(!reg)
7716                 return;
7717         
7718         if(!endian) {
7719                 endian = 1;
7720         } else {
7721                 endian = -1;
7722                 offset = size-1;
7723         }
7724         
7725         while(size--) {
7726                 emitpcode(poc,    popGet(AOP(reg),offset));
7727                 offset += endian;
7728         }
7729         
7730 }
7731
7732 #if 0
7733 /*-----------------------------------------------------------------*/
7734 /* genLeftShift - generates code for left shifting                 */
7735 /*-----------------------------------------------------------------*/
7736 static void genLeftShift (iCode *ic)
7737 {
7738         operand *left,*right, *result;
7739         int size, offset;
7740         unsigned long lit = 0L;
7741         char *l;
7742         symbol *tlbl , *tlbl1;
7743         pCodeOp *pctemp;
7744         
7745         FENTRY;
7746         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7747         
7748         right = IC_RIGHT(ic);
7749         left  = IC_LEFT(ic);
7750         result = IC_RESULT(ic);
7751         
7752         aopOp(right,ic,FALSE);
7753         aopOp(left,ic,FALSE);
7754         aopOp(result,ic,FALSE);
7755         
7756         
7757         /* if the shift count is known then do it 
7758         as efficiently as possible */
7759         if (AOP_TYPE(right) == AOP_LIT) {
7760                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7761                 return ;
7762         }
7763         
7764         /* shift count is unknown then we have to form 
7765         a loop get the loop count in B : Note: we take
7766         only the lower order byte since shifting
7767         more that 32 bits make no sense anyway, ( the
7768         largest size of an object can be only 32 bits ) */  
7769         
7770         /* this code fails for RIGHT == RESULT */
7771         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7772         
7773         /* now move the left to the result if they are not the
7774         same */
7775         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7776                 AOP_SIZE(result) > 1) {
7777                 
7778                 size = AOP_SIZE(result);
7779                 offset=0;
7780                 while (size--) {
7781                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7782                         if (*l == '@' && (IS_AOP_PREG(result))) {
7783                                 
7784                                 pic14_emitcode("mov","a,%s",l);
7785                                 aopPut(AOP(result),"a",offset);
7786                         } else {
7787                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7788                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7789                                 //aopPut(AOP(result),l,offset);
7790                         }
7791                         offset++;
7792                 }
7793         }
7794         
7795         if(AOP_TYPE(left) == AOP_LIT)
7796                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7797
7798         size = AOP_SIZE(result);
7799         
7800         /* if it is only one byte then */
7801         if (size == 1) {
7802                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7803                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7804                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7805                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7806                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7807                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7808                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7809                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7810                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7811                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7812                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7813                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7814                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7815                 } else {
7816                         
7817                         tlbl = newiTempLabel(NULL);
7818                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7819                                 mov2w (AOP(left), 0);
7820                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7821                         }
7822                         
7823                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7824                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7825                         emitpLabel(tlbl->key);
7826                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7827                         emitpcode(POC_ADDLW,  popGetLit(1));
7828                         emitSKPC;
7829                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7830                 }
7831                 goto release ;
7832         }
7833         
7834         if (pic14_sameRegs(AOP(left),AOP(result))) {
7835                 
7836                 tlbl = newiTempLabel(NULL);
7837                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7838                 genMultiAsm(POC_RRF, result, size,1);
7839                 emitpLabel(tlbl->key);
7840                 genMultiAsm(POC_RLF, result, size,0);
7841                 emitpcode(POC_ADDLW,  popGetLit(1));
7842                 emitSKPC;
7843                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7844                 goto release;
7845         }
7846         
7847         //tlbl = newiTempLabel(NULL);
7848         //offset = 0 ;   
7849         //tlbl1 = newiTempLabel(NULL);
7850         
7851         //reAdjustPreg(AOP(result));    
7852         
7853         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7854         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7855         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7856         //MOVA(l);
7857         //pic14_emitcode("add","a,acc");         
7858         //aopPut(AOP(result),"a",offset++);
7859         //while (--size) {
7860         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7861         //  MOVA(l);
7862         //  pic14_emitcode("rlc","a");         
7863         //  aopPut(AOP(result),"a",offset++);
7864         //}
7865         //reAdjustPreg(AOP(result));
7866         
7867         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7868         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7869         
7870         
7871         tlbl = newiTempLabel(NULL);
7872         tlbl1= newiTempLabel(NULL);
7873         
7874         size = AOP_SIZE(result);
7875         offset = 1;
7876         
7877         pctemp = popGetTempReg();  /* grab a temporary working register. */
7878         
7879         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7880         
7881         /* offset should be 0, 1 or 3 */
7882         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7883         emitSKPNZ;
7884         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7885         
7886         emitpcode(POC_MOVWF, pctemp);
7887         
7888         
7889         emitpLabel(tlbl->key);
7890         
7891         emitCLRC;
7892         emitpcode(POC_RLF,  popGet(AOP(result),0));
7893         while(--size)
7894                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7895         
7896         emitpcode(POC_DECFSZ,  pctemp);
7897         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7898         emitpLabel(tlbl1->key);
7899         
7900         popReleaseTempReg(pctemp);
7901         
7902         
7903 release:
7904         freeAsmop (right,NULL,ic,TRUE);
7905         freeAsmop(left,NULL,ic,TRUE);
7906         freeAsmop(result,NULL,ic,TRUE);
7907 }
7908 #endif
7909
7910 #if 0
7911 /*-----------------------------------------------------------------*/
7912 /* genrshOne - right shift a one byte quantity by known count      */
7913 /*-----------------------------------------------------------------*/
7914 static void genrshOne (operand *result, operand *left,
7915                                            int shCount, int sign)
7916 {
7917         FENTRY;
7918         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7919         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7920 }
7921
7922 /*-----------------------------------------------------------------*/
7923 /* genrshTwo - right shift two bytes by known amount != 0          */
7924 /*-----------------------------------------------------------------*/
7925 static void genrshTwo (operand *result,operand *left,
7926                                            int shCount, int sign)
7927 {
7928         FENTRY;
7929         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7930         /* if shCount >= 8 */
7931         if (shCount >= 8) {
7932                 shCount -= 8 ;
7933                 if (shCount)
7934                         shiftR1Left2Result(left, MSB16, result, LSB,
7935                         shCount, sign);
7936                 else
7937                         movLeft2Result(left, MSB16, result, LSB);
7938                 
7939                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7940                 
7941                 if(sign) {
7942                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7943                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7944                 }
7945         }
7946         
7947         /*  1 <= shCount <= 7 */
7948         else
7949                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7950 }
7951
7952 /*-----------------------------------------------------------------*/
7953 /* shiftRLong - shift right one long from left to result           */
7954 /* offl = LSB or MSB16                                             */
7955 /*-----------------------------------------------------------------*/
7956 static void shiftRLong (operand *left, int offl,
7957                                                 operand *result, int sign)
7958 {
7959         int size, same;
7960         
7961         FENTRY;
7962         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7963         
7964         size = AOP_SIZE(left);
7965         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7966         
7967         if (sign)
7968                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7969         else
7970                 emitCLRC;
7971
7972         assert (offl >= 0 && offl < size);
7973
7974         same = pic14_sameRegs (AOP(left), AOP(result));
7975
7976         /* perform the shift */
7977         while (size--)
7978         {
7979                 if (same && !offl) {
7980                         emitpcode (POC_RRF, popGet (AOP(result), size));
7981                 } else {
7982                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7983                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7984                 }
7985         } // while
7986
7987         addSign (result, AOP_SIZE(left) - offl, sign);
7988 }
7989
7990 /*-----------------------------------------------------------------*/
7991 /* genrshFour - shift four byte by a known amount != 0             */
7992 /*-----------------------------------------------------------------*/
7993 static void genrshFour (operand *result, operand *left,
7994                                                 int shCount, int sign)
7995 {
7996         FENTRY;
7997         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7998         /* if shifting more that 3 bytes */
7999         if(shCount >= 24 ) {
8000                 shCount -= 24;
8001                 if(shCount)
8002                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8003                 else
8004                         movLeft2Result(left, MSB32, result, LSB);
8005                 
8006                 addSign(result, MSB16, sign);
8007         }
8008         else if(shCount >= 16){
8009                 shCount -= 16;
8010                 if(shCount)
8011                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8012                 else{
8013                         movLeft2Result(left, MSB24, result, LSB);
8014                         movLeft2Result(left, MSB32, result, MSB16);
8015                 }
8016                 addSign(result, MSB24, sign);
8017         }
8018         else if(shCount >= 8){
8019                 shCount -= 8;
8020                 if(shCount == 1)
8021                         shiftRLong(left, MSB16, result, sign);
8022                 else if(shCount == 0){
8023                         movLeft2Result(left, MSB16, result, LSB);
8024                         movLeft2Result(left, MSB24, result, MSB16);
8025                         movLeft2Result(left, MSB32, result, MSB24);
8026                         addSign(result, MSB32, sign);
8027                 }
8028                 else{
8029                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8030                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8031                         /* the last shift is signed */
8032                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8033                         addSign(result, MSB32, sign);
8034                 }
8035         }
8036         else{   /* 1 <= shCount <= 7 */
8037                 if(shCount <= 2){
8038                         shiftRLong(left, LSB, result, sign);
8039                         if(shCount == 2)
8040                                 shiftRLong(result, LSB, result, sign);
8041                 }
8042                 else{
8043                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8044                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8045                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8046                 }
8047         }
8048 }
8049
8050 /*-----------------------------------------------------------------*/
8051 /* genRightShiftLiteral - right shifting by known count            */
8052 /*-----------------------------------------------------------------*/
8053 static void genRightShiftLiteral (operand *left,
8054                                                                   operand *right,
8055                                                                   operand *result,
8056                                                                   iCode *ic,
8057                                                                   int sign)
8058 {    
8059         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8060         int lsize,res_size;
8061         
8062         FENTRY;
8063         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8064         freeAsmop(right,NULL,ic,TRUE);
8065         
8066         aopOp(left,ic,FALSE);
8067         aopOp(result,ic,FALSE);
8068         
8069 #if VIEW_SIZE
8070         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8071                 AOP_SIZE(left));
8072 #endif
8073         
8074         lsize = pic14_getDataSize(left);
8075         res_size = pic14_getDataSize(result);
8076         /* test the LEFT size !!! */
8077         
8078         /* I suppose that the left size >= result size */
8079         if(shCount == 0){
8080                 while(res_size--)
8081                         movLeft2Result(left, res_size, result, res_size);
8082         }
8083         
8084         else if(shCount >= (lsize * 8)){
8085                 
8086                 if(res_size == 1) {
8087                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8088                         if(sign) {
8089                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8090                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8091                         }
8092                 } else {
8093                         
8094                         if(sign) {
8095                                 emitpcode(POC_MOVLW, popGetLit(0));
8096                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8097                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8098                                 while(res_size--)
8099                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8100                                 
8101                         } else {
8102                                 
8103                                 while(res_size--)
8104                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8105                         }
8106                 }
8107         } else {
8108                 
8109                 switch (res_size) {
8110                 case 1:
8111                         genrshOne (result,left,shCount,sign);
8112                         break;
8113                         
8114                 case 2:
8115                         genrshTwo (result,left,shCount,sign);
8116                         break;
8117                         
8118                 case 4:
8119                         genrshFour (result,left,shCount,sign);
8120                         break;
8121                 default :
8122                         break;
8123                 }
8124                 
8125         }
8126
8127         freeAsmop(left,NULL,ic,TRUE);
8128         freeAsmop(result,NULL,ic,TRUE);
8129 }
8130 #endif
8131
8132 #if 0
8133 /*-----------------------------------------------------------------*/
8134 /* genSignedRightShift - right shift of signed number              */
8135 /*-----------------------------------------------------------------*/
8136 static void genSignedRightShift (iCode *ic)
8137 {
8138         operand *right, *left, *result;
8139         int size, offset;
8140         //  char *l;
8141         symbol *tlbl, *tlbl1 ;
8142         pCodeOp *pctemp;
8143         
8144         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8145         
8146         /* we do it the hard way put the shift count in b
8147         and loop thru preserving the sign */
8148         FENTRY;
8149         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8150         
8151         right = IC_RIGHT(ic);
8152         left  = IC_LEFT(ic);
8153         result = IC_RESULT(ic);
8154         
8155         aopOp(right,ic,FALSE);  
8156         aopOp(left,ic,FALSE);
8157         aopOp(result,ic,FALSE);
8158         
8159         
8160         if ( AOP_TYPE(right) == AOP_LIT) {
8161                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8162                 //genRightShiftLiteral (left,right,result,ic,1);
8163                 return ;
8164         }
8165         /* shift count is unknown then we have to form 
8166         a loop get the loop count in B : Note: we take
8167         only the lower order byte since shifting
8168         more that 32 bits make no sense anyway, ( the
8169         largest size of an object can be only 32 bits ) */  
8170         
8171         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8172         //pic14_emitcode("inc","b");
8173         //freeAsmop (right,NULL,ic,TRUE);
8174         //aopOp(left,ic,FALSE);
8175         //aopOp(result,ic,FALSE);
8176         
8177         /* now move the left to the result if they are not the
8178         same */
8179         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8180                 AOP_SIZE(result) > 1) {
8181                 
8182                 size = AOP_SIZE(result);
8183                 offset=0;
8184                 while (size--) { 
8185                         /*
8186                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8187                         if (*l == '@' && IS_AOP_PREG(result)) {
8188                                 pic14_emitcode("mov","a,%s",l);
8189                                 aopPut(AOP(result),"a",offset);
8190                         } else
8191                         aopPut(AOP(result),l,offset);
8192                         */
8193                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8194                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8195                         
8196                         offset++;
8197                 }
8198         }
8199         
8200         /* mov the highest order bit to OVR */    
8201         tlbl = newiTempLabel(NULL);
8202         tlbl1= newiTempLabel(NULL);
8203         
8204         size = AOP_SIZE(result);
8205         offset = size - 1;
8206         
8207         pctemp = popGetTempReg();  /* grab a temporary working register. */
8208         
8209         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8210         
8211         /* offset should be 0, 1 or 3 */
8212         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8213         emitSKPNZ;
8214         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8215         
8216         emitpcode(POC_MOVWF, pctemp);
8217         
8218         
8219         emitpLabel(tlbl->key);
8220         
8221         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8222         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8223         
8224         while(--size) {
8225                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8226         }
8227         
8228         emitpcode(POC_DECFSZ,  pctemp);
8229         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8230         emitpLabel(tlbl1->key);
8231         
8232         popReleaseTempReg(pctemp);
8233 #if 0
8234         size = AOP_SIZE(result);
8235         offset = size - 1;
8236         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8237         pic14_emitcode("rlc","a");
8238         pic14_emitcode("mov","ov,c");
8239         /* if it is only one byte then */
8240         if (size == 1) {
8241                 l = aopGet(AOP(left),0,FALSE,FALSE);
8242                 MOVA(l);
8243                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8244                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8245                 pic14_emitcode("mov","c,ov");
8246                 pic14_emitcode("rrc","a");
8247                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8248                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8249                 aopPut(AOP(result),"a",0);
8250                 goto release ;
8251         }
8252         
8253         reAdjustPreg(AOP(result));
8254         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8255         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8256         pic14_emitcode("mov","c,ov");
8257         while (size--) {
8258                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8259                 MOVA(l);
8260                 pic14_emitcode("rrc","a");         
8261                 aopPut(AOP(result),"a",offset--);
8262         }
8263         reAdjustPreg(AOP(result));
8264         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8265         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8266         
8267 release:
8268 #endif
8269         
8270         freeAsmop(left,NULL,ic,TRUE);
8271         freeAsmop(result,NULL,ic,TRUE);
8272         freeAsmop(right,NULL,ic,TRUE);
8273 }
8274 #endif
8275
8276 /*-----------------------------------------------------------------*/
8277 /* loadSignToC - load the operand's sign bit into CARRY            */
8278 /*-----------------------------------------------------------------*/
8279
8280 static void loadSignToC (operand *op)
8281 {
8282         FENTRY;
8283         assert (op && AOP(op) && AOP_SIZE(op));
8284
8285         emitCLRC;
8286         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8287         emitSETC;
8288 }
8289
8290 /*-----------------------------------------------------------------*/
8291 /* genRightShift - generate code for right shifting                */
8292 /*-----------------------------------------------------------------*/
8293 static void genGenericShift (iCode *ic, int shiftRight)
8294 {
8295         operand *right, *left, *result;
8296         sym_link *retype ;
8297         int size;
8298         symbol *tlbl, *tlbl1, *inverselbl;
8299         
8300         FENTRY;
8301         /* if signed then we do it the hard way preserve the
8302         sign bit moving it inwards */
8303         retype = getSpec(operandType(IC_RESULT(ic)));
8304         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8305         
8306         /* signed & unsigned types are treated the same : i.e. the
8307         signed is NOT propagated inwards : quoting from the
8308         ANSI - standard : "for E1 >> E2, is equivalent to division
8309         by 2**E2 if unsigned or if it has a non-negative value,
8310         otherwise the result is implementation defined ", MY definition
8311         is that the sign does not get propagated */
8312         
8313         right = IC_RIGHT(ic);
8314         left  = IC_LEFT(ic);
8315         result = IC_RESULT(ic);
8316         
8317         aopOp(right,ic,FALSE);
8318         aopOp(left,ic,FALSE);
8319         aopOp(result,ic,FALSE);
8320         
8321         /* if the shift count is known then do it 
8322         as efficiently as possible */
8323         if (AOP_TYPE(right) == AOP_LIT) {
8324                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8325                 if (lit < 0)
8326                 {
8327                         lit = -lit;
8328                         shiftRight = !shiftRight;
8329                 }
8330                 
8331                 if (shiftRight)
8332                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8333                 else
8334                         shiftLeft_Left2ResultLit (left, result, lit);
8335                 //genRightShiftLiteral (left,right,result,ic, 0);
8336                 return ;
8337         }
8338         
8339         /* shift count is unknown then we have to form 
8340         a loop get the loop count in B : Note: we take
8341         only the lower order byte since shifting
8342         more that 32 bits make no sense anyway, ( the
8343         largest size of an object can be only 32 bits ) */  
8344
8345         /* we must not overwrite the shift counter */
8346         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8347         
8348         /* now move the left to the result if they are not the
8349         same */
8350         if (!pic14_sameRegs(AOP(left),AOP(result)))
8351         {
8352                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8353                 while (size--) {
8354                         mov2w(AOP(left), size);
8355                         movwf(AOP(result), size);
8356                 }
8357                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8358         }
8359         
8360         tlbl = newiTempLabel(NULL);
8361         tlbl1= newiTempLabel(NULL);
8362         inverselbl = NULL;
8363         size = AOP_SIZE(result);
8364
8365         mov2w(AOP(right),0);
8366         if (!SPEC_USIGN(operandType(right)))
8367         {
8368                 inverselbl = newiTempLabel(NULL);
8369                 /* signed shift count -- invert shift direction for c<0 */
8370                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8371                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8372         } // if
8373         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8374         /* check for `a = b >> c' with `-c == 0' */
8375         emitSKPNZ;
8376         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8377         emitpLabel(tlbl->key);
8378         /* propagate the sign bit inwards for SIGNED result */
8379         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8380         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8381         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8382         emitSKPC;
8383         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8384
8385         if (!SPEC_USIGN(operandType(right)))
8386         {
8387                 symbol *inv_loop = newiTempLabel(NULL);
8388
8389                 shiftRight = !shiftRight;       /* invert shift direction */
8390                 
8391                 /* we came here from the code above -- we are done */
8392                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8393                 
8394                 /* emit code for shifting N<0 steps, count is already in W */
8395                 emitpLabel(inverselbl->key);
8396                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8397                 emitpLabel(inv_loop->key);
8398                 /* propagate the sign bit inwards for SIGNED result */
8399                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8400                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8401                 emitpcode(POC_ADDLW, popGetLit(1));
8402                 emitSKPC;
8403                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8404         } // if
8405         
8406         emitpLabel(tlbl1->key);
8407         
8408         freeAsmop(left,NULL,ic,TRUE);
8409         freeAsmop (right,NULL,ic,TRUE);
8410         freeAsmop(result,NULL,ic,TRUE);
8411 }
8412
8413 static void genRightShift (iCode *ic)
8414 {
8415         genGenericShift(ic, 1);
8416 }
8417
8418 static void genLeftShift (iCode *ic)
8419 {
8420         genGenericShift(ic, 0);
8421 }
8422
8423 /*-----------------------------------------------------------------*/
8424 /* SetIrp - Set IRP bit                                            */
8425 /*-----------------------------------------------------------------*/
8426 void SetIrp(operand *result) {
8427         FENTRY;
8428         if (AOP_TYPE(result) == AOP_LIT) {
8429                 unsigned lit = (unsigned)operandLitValue(result);
8430                 if (lit&0x100)
8431                         emitSETIRP;
8432                 else
8433                         emitCLRIRP;
8434         } else {
8435                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8436                         int addrs = PCOL(AOP(result))->lit;
8437                         if (addrs & 0x100)
8438                                 emitSETIRP;
8439                         else
8440                                 emitCLRIRP;
8441                 } else {
8442                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8443                         if(AOP_SIZE(result) > 1) {
8444                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8445                                 emitSETIRP;
8446                         }
8447                 }
8448         }
8449 }
8450
8451 static void
8452 setup_fsr (operand *ptr)
8453 {
8454   mov2w_op(ptr, 0);
8455   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8456
8457   /* also setup-up IRP */
8458   SetIrp (ptr);
8459 }
8460
8461 /*-----------------------------------------------------------------*/
8462 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8463 /*                  arbitrary pointer (__code, __data, generic)    */
8464 /*-----------------------------------------------------------------*/
8465 static void
8466 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8467 {
8468     FENTRY;
8469     switch (p_type)
8470     {
8471     case POINTER:
8472     case FPOINTER:
8473       if (!alreadyAddressed) setup_fsr (src);
8474       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8475       break;
8476     
8477     case CPOINTER:
8478       assert( AOP_SIZE(src) == 2 );
8479       mov2w_op(src, 0);
8480       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8481       mov2w_op(src, 1);
8482       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8483       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8484       call_libraryfunc ("__gptrget1");
8485       break;
8486     
8487     case GPOINTER:
8488       assert( AOP_SIZE(src) == 3 );
8489       mov2w_op(src, 0);
8490       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8491       mov2w_op(src, 1);
8492       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8493       mov2w_op(src, 2);
8494       call_libraryfunc ("__gptrget1");
8495       break;
8496     
8497     default:
8498       assert( !"unhandled pointer type" );
8499       break;
8500     }
8501 }
8502
8503 /*-----------------------------------------------------------------*/
8504 /* emitPtrByteSet - emits code to set a byte from src through a    */
8505 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8506 /*-----------------------------------------------------------------*/
8507 static void
8508 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8509 {
8510     FENTRY;
8511     switch (p_type)
8512     {
8513     case POINTER:
8514     case FPOINTER:
8515       if (!alreadyAddressed) setup_fsr (dst);
8516       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8517       break;
8518     
8519     case CPOINTER:
8520       assert( !"trying to assign to __code pointer" );
8521       break;
8522     
8523     case GPOINTER:
8524       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8525       mov2w_op(dst, 0);
8526       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8527       mov2w_op(dst, 1);
8528       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8529       mov2w_op(dst, 2);
8530       call_libraryfunc ("__gptrput1");
8531       break;
8532
8533     default:
8534       assert( !"unhandled pointer type" );
8535       break;
8536     }
8537 }
8538
8539 /*-----------------------------------------------------------------*/
8540 /* genUnpackBits - generates code for unpacking bits               */
8541 /*-----------------------------------------------------------------*/
8542 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8543 {    
8544   int rsize;            /* result size */
8545   sym_link *etype;      /* bitfield type information */
8546   int blen;             /* bitfield length */
8547   int bstr;             /* bitfield starting bit within byte */
8548
8549   FENTRY;
8550   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8551   etype = getSpec(operandType(result));
8552   rsize = getSize (operandType (result));
8553   blen = SPEC_BLEN (etype);
8554   bstr = SPEC_BSTR (etype);
8555
8556   /* single bit field case */
8557   if (blen == 1) {
8558     if (ifx) { /* that is for an if statement */
8559       pCodeOp *pcop;
8560       resolvedIfx rIfx;
8561       resolveIfx(&rIfx,ifx);
8562       if (ptype == -1) /* direct */
8563         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8564       else
8565         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8566       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8567       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8568       ifx->generated=1;
8569     } else {
8570       int i;
8571       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8572       for (i=0; i < AOP_SIZE(result); i++)
8573         emitpcode (POC_CLRF, popGet (AOP(result), i));
8574
8575       switch (ptype)
8576       {
8577       case -1:
8578         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8579         /* adjust result below */
8580         break;
8581         
8582       case POINTER:
8583       case FPOINTER:
8584       case GPOINTER:
8585       case CPOINTER:
8586         emitPtrByteGet (left, ptype, FALSE);
8587         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8588         emitSKPZ;
8589         /* adjust result below */
8590         break;
8591         
8592       default:
8593         assert( !"unhandled pointer type" );
8594       } // switch
8595
8596       /* move sign-/zero extended bit to result */
8597       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8598         emitpcode (POC_INCF, popGet (AOP(result), 0));
8599       } else {
8600         emitpcode (POC_DECF, popGet (AOP(result), 0));
8601       }
8602       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8603     }
8604     return;
8605   }
8606   else if (blen <= 8 && ((blen + bstr) <= 8))
8607   {
8608     /* blen > 1 */
8609     int i;
8610
8611     for (i=0; i < AOP_SIZE(result); i++)
8612       emitpcode (POC_CLRF, popGet (AOP(result), i));
8613
8614     switch (ptype)
8615     {
8616     case -1:
8617       mov2w(AOP(left), 0);
8618       break;
8619       
8620     case POINTER:
8621     case FPOINTER:
8622     case GPOINTER:
8623     case CPOINTER:
8624       emitPtrByteGet (left, ptype, FALSE);
8625       break;
8626       
8627     default:
8628       assert( !"unhandled pointer type" );
8629     } // switch
8630
8631     if (blen < 8)
8632       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8633     movwf(AOP(result), 0);
8634     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8635
8636     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8637     {
8638       /* signed bitfield */
8639       assert (bstr + blen > 0);
8640       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8641       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8642       emitpcode(POC_IORWF, popGet(AOP(result),0));
8643     }
8644     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8645     return;
8646   }
8647
8648   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8649 }
8650
8651 #if 1
8652 /*-----------------------------------------------------------------*/
8653 /* genDataPointerGet - generates code when ptr offset is known     */
8654 /*-----------------------------------------------------------------*/
8655 static void genDataPointerGet (operand *left, 
8656         operand *result, 
8657         iCode *ic)
8658 {
8659         int size , offset = 0;
8660                 
8661         FENTRY;
8662         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8663         
8664         
8665         /* optimization - most of the time, left and result are the same
8666         * address, but different types. for the pic code, we could omit
8667         * the following
8668         */
8669         aopOp(result,ic,TRUE);
8670         
8671         if (pic14_sameRegs (AOP(left), AOP(result)))
8672                 return;
8673         
8674         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8675         
8676         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8677         
8678         size = AOP_SIZE(result);
8679         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8680         
8681         offset = 0;
8682         while (size--) {
8683                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8684                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8685                 offset++;
8686         }
8687         
8688         freeAsmop(left,NULL,ic,TRUE);
8689         freeAsmop(result,NULL,ic,TRUE);
8690 }
8691 #endif
8692
8693 /*-----------------------------------------------------------------*/
8694 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8695 /*-----------------------------------------------------------------*/
8696 static void genNearPointerGet (operand *left, 
8697                                                            operand *result, 
8698                                                            iCode *ic)
8699 {
8700         asmop *aop = NULL;
8701         sym_link *ltype = operandType(left);
8702         sym_link *rtype = operandType(result);
8703         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8704         int direct = 0;
8705
8706         FENTRY;
8707         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8708         
8709         
8710         aopOp(left,ic,FALSE);
8711         
8712         /* if left is rematerialisable and
8713         result is not bit variable type and
8714         the left is pointer to data space i.e
8715         lower 128 bytes of space */
8716         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8717                 !IS_BITVAR(retype)         &&
8718                 PIC_IS_DATA_PTR(ltype)) {
8719                 genDataPointerGet (left,result,ic);
8720                 return ;
8721         }
8722         
8723         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8724         aopOp (result,ic,FALSE);
8725         
8726         /* Check if can access directly instead of via a pointer */
8727         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8728                 && AOP_SIZE(result) == 1)
8729         {
8730                 direct = 1;
8731         }
8732
8733         if (IS_BITFIELD(getSpec(operandType(result)))) 
8734         {
8735                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8736                 goto release;
8737         }
8738         
8739         /* If the pointer value is not in a the FSR then need to put it in */
8740         /* Must set/reset IRP bit for use with FSR. */
8741         if (!direct)
8742           setup_fsr (left);
8743         
8744 //      sym_link *etype;
8745         /* if bitfield then unpack the bits */
8746         {
8747                 /* we have can just get the values */
8748                 int size = AOP_SIZE(result);
8749                 int offset = 0 ;  
8750                 
8751                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8752                 
8753                 while(size--) {
8754                         if (direct)
8755                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8756                         else
8757                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8758                         if (AOP_TYPE(result) == AOP_LIT) {
8759                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8760                         } else {
8761                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8762                         }
8763                         if (size && !direct)
8764                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8765                         offset++;
8766                 }
8767         }
8768         
8769         /* now some housekeeping stuff */
8770         if (aop) {
8771                 /* we had to allocate for this iCode */
8772                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8773                 freeAsmop(NULL,aop,ic,TRUE);
8774         } else { 
8775                 /* we did not allocate which means left
8776                 already in a pointer register, then
8777                 if size > 0 && this could be used again
8778                 we have to point it back to where it 
8779                 belongs */
8780                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8781                 if (AOP_SIZE(result) > 1 &&
8782                         !OP_SYMBOL(left)->remat &&
8783                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8784                         ic->depth )) {
8785                         int size = AOP_SIZE(result) - 1;
8786                         while (size--)
8787                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8788                 }
8789         }
8790         
8791 release:
8792         /* done */
8793         freeAsmop(left,NULL,ic,TRUE);
8794         freeAsmop(result,NULL,ic,TRUE);
8795
8796 }
8797
8798 #if 0
8799 /*-----------------------------------------------------------------*/
8800 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8801 /*-----------------------------------------------------------------*/
8802 static void genPagedPointerGet (operand *left, 
8803                                                                 operand *result, 
8804                                                                 iCode *ic)
8805 {
8806         asmop *aop = NULL;
8807         regs *preg = NULL ;
8808         char *rname ;
8809         sym_link *rtype, *retype;    
8810         
8811         FENTRY;
8812         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8813         
8814         rtype = operandType(result);
8815         retype= getSpec(rtype);
8816         
8817         aopOp(left,ic,FALSE);
8818         
8819         /* if the value is already in a pointer register
8820         then don't need anything more */
8821         if (!AOP_INPREG(AOP(left))) {
8822                 /* otherwise get a free pointer register */
8823                 aop = newAsmop(0);
8824                 preg = getFreePtr(ic,&aop,FALSE);
8825                 pic14_emitcode("mov","%s,%s",
8826                         preg->name,
8827                         aopGet(AOP(left),0,FALSE,TRUE));
8828                 rname = preg->name ;
8829         } else
8830                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8831         
8832         freeAsmop(left,NULL,ic,TRUE);
8833         aopOp (result,ic,FALSE);
8834         
8835         /* if bitfield then unpack the bits */
8836         if (IS_BITFIELD(retype)) 
8837                 genUnpackBits (result,left,rname,PPOINTER,0);
8838         else {
8839                 /* we have can just get the values */
8840                 int size = AOP_SIZE(result);
8841                 int offset = 0 ;  
8842                 
8843                 while (size--) {
8844                         
8845                         pic14_emitcode("movx","a,@%s",rname);
8846                         aopPut(AOP(result),"a",offset);
8847                         
8848                         offset++ ;
8849                         
8850                         if (size)
8851                                 pic14_emitcode("inc","%s",rname);
8852                 }
8853         }
8854         
8855         /* now some housekeeping stuff */
8856         if (aop) {
8857                 /* we had to allocate for this iCode */
8858                 freeAsmop(NULL,aop,ic,TRUE);
8859         } else { 
8860         /* we did not allocate which means left
8861         already in a pointer register, then
8862         if size > 0 && this could be used again
8863         we have to point it back to where it 
8864                 belongs */
8865                 if (AOP_SIZE(result) > 1 &&
8866                         !OP_SYMBOL(left)->remat &&
8867                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8868                         ic->depth )) {
8869                         int size = AOP_SIZE(result) - 1;
8870                         while (size--)
8871                                 pic14_emitcode("dec","%s",rname);
8872                 }
8873         }
8874         
8875         /* done */
8876         freeAsmop(result,NULL,ic,TRUE);
8877         
8878         
8879 }
8880
8881 /*-----------------------------------------------------------------*/
8882 /* genFarPointerGet - gget value from far space                    */
8883 /*-----------------------------------------------------------------*/
8884 static void genFarPointerGet (operand *left,
8885                                                           operand *result, iCode *ic)
8886 {
8887         int size, offset ;
8888         sym_link *retype = getSpec(operandType(result));
8889         
8890         FENTRY;
8891         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8892         
8893         aopOp(left,ic,FALSE);
8894         
8895         /* if the operand is already in dptr 
8896         then we do nothing else we move the value to dptr */
8897         if (AOP_TYPE(left) != AOP_STR) {
8898                 /* if this is remateriazable */
8899                 if (AOP_TYPE(left) == AOP_IMMD)
8900                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8901                 else { /* we need to get it byte by byte */
8902                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8903                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8904                         if (options.model == MODEL_FLAT24)
8905                         {
8906                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8907                         }
8908                 }
8909         }
8910         /* so dptr know contains the address */
8911         freeAsmop(left,NULL,ic,TRUE);
8912         aopOp(result,ic,FALSE);
8913         
8914         /* if bit then unpack */
8915         if (IS_BITFIELD(retype)) 
8916                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8917         else {
8918                 size = AOP_SIZE(result);
8919                 offset = 0 ;
8920                 
8921                 while (size--) {
8922                         pic14_emitcode("movx","a,@dptr");
8923                         aopPut(AOP(result),"a",offset++);
8924                         if (size)
8925                                 pic14_emitcode("inc","dptr");
8926                 }
8927         }
8928         
8929         freeAsmop(result,NULL,ic,TRUE);
8930 }
8931 #endif
8932
8933 #if 0
8934 /*-----------------------------------------------------------------*/
8935 /* genCodePointerGet - get value from code space                  */
8936 /*-----------------------------------------------------------------*/
8937 static void genCodePointerGet (operand *left,
8938                                                            operand *result, iCode *ic)
8939 {
8940         int size, offset ;
8941         sym_link *retype = getSpec(operandType(result));
8942         
8943         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8944         
8945         aopOp(left,ic,FALSE);
8946         
8947         /* if the operand is already in dptr 
8948         then we do nothing else we move the value to dptr */
8949         if (AOP_TYPE(left) != AOP_STR) {
8950                 /* if this is remateriazable */
8951                 if (AOP_TYPE(left) == AOP_IMMD)
8952                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8953                 else { /* we need to get it byte by byte */
8954                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8955                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8956                         if (options.model == MODEL_FLAT24)
8957                         {
8958                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8959                         }
8960                 }
8961         }
8962         /* so dptr know contains the address */
8963         freeAsmop(left,NULL,ic,TRUE);
8964         aopOp(result,ic,FALSE);
8965         
8966         /* if bit then unpack */
8967         if (IS_BITFIELD(retype)) 
8968                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8969         else {
8970                 size = AOP_SIZE(result);
8971                 offset = 0 ;
8972                 
8973                 while (size--) {
8974                         pic14_emitcode("clr","a");
8975                         pic14_emitcode("movc","a,@a+dptr");
8976                         aopPut(AOP(result),"a",offset++);
8977                         if (size)
8978                                 pic14_emitcode("inc","dptr");
8979                 }
8980         }
8981         
8982         freeAsmop(result,NULL,ic,TRUE);
8983 }
8984 #endif
8985 /*-----------------------------------------------------------------*/
8986 /* genGenPointerGet - gget value from generic pointer space        */
8987 /*-----------------------------------------------------------------*/
8988 static void genGenPointerGet (operand *left,
8989                                                           operand *result, iCode *ic)
8990 {
8991         FENTRY;
8992         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8993         aopOp(left,ic,FALSE);
8994         aopOp(result,ic,FALSE);
8995         
8996         
8997         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8998
8999         if (IS_BITFIELD(getSpec(operandType(result))))
9000         {
9001           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9002           return;
9003         }
9004
9005         {
9006           /* emit call to __gptrget */
9007           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9008           int size = AOP_SIZE(result);
9009           int idx = 0;
9010
9011           assert (size > 0 && size <= 4);
9012
9013           /* pass arguments */
9014           assert (AOP_SIZE(left) == 3);
9015           mov2w(AOP(left), 0);
9016           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9017           mov2w(AOP(left), 1);
9018           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9019           mov2w(AOP(left), 2);
9020           call_libraryfunc (func[size]);
9021           
9022           /* save result */
9023           movwf (AOP(result), --size);
9024           while (size--) {
9025             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9026             movwf (AOP(result), size);
9027           } // while
9028         }
9029         
9030         freeAsmop(left,NULL,ic,TRUE);
9031         freeAsmop(result,NULL,ic,TRUE);
9032         
9033 }
9034
9035 /*-----------------------------------------------------------------*/
9036 /* genConstPointerGet - get value from const generic pointer space */
9037 /*-----------------------------------------------------------------*/
9038 static void genConstPointerGet (operand *left,
9039                                                                 operand *result, iCode *ic)
9040 {
9041         //sym_link *retype = getSpec(operandType(result));
9042         #if 0
9043         symbol *albl, *blbl;//, *clbl;
9044         pCodeOp *pcop;
9045         #endif
9046         PIC_OPCODE poc;
9047         int i, size, lit;
9048         
9049         FENTRY;
9050         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9051         aopOp(left,ic,FALSE);
9052         aopOp(result,ic,FALSE);
9053         
9054         size = AOP_SIZE(result);
9055         
9056         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9057         
9058         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9059
9060         lit = op_isLitLike (left);
9061         poc = lit ? POC_MOVLW : POC_MOVFW;
9062
9063         if (IS_BITFIELD(getSpec(operandType(result))))
9064         {
9065                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9066                 goto release;
9067         }
9068
9069         {
9070                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9071                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9072                 assert (size > 0 && size <= 4);
9073                 
9074                 mov2w_op(left, 0);
9075                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9076                 mov2w_op(left, 1);
9077                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9078                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9079                 call_libraryfunc (func[size]);
9080
9081                 movwf(AOP(result),size-1);
9082                 for (i = 1; i < size; i++)
9083                 {
9084                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9085                         movwf(AOP(result),size - 1 - i);
9086                 } // for
9087         }
9088         
9089 release:
9090         freeAsmop(left,NULL,ic,TRUE);
9091         freeAsmop(result,NULL,ic,TRUE);
9092         
9093 }
9094 /*-----------------------------------------------------------------*/
9095 /* genPointerGet - generate code for pointer get                   */
9096 /*-----------------------------------------------------------------*/
9097 static void genPointerGet (iCode *ic)
9098 {
9099         operand *left, *result ;
9100         sym_link *type, *etype;
9101         int p_type = -1;
9102         
9103         FENTRY;
9104         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9105         
9106         left = IC_LEFT(ic);
9107         result = IC_RESULT(ic) ;
9108         
9109         /* depending on the type of pointer we need to
9110         move it to the correct pointer register */
9111         type = operandType(left);
9112         etype = getSpec(type);
9113         
9114         if (IS_PTR_CONST(type))
9115                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9116         
9117         /* if left is of type of pointer then it is simple */
9118         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9119                 p_type = DCL_TYPE(type);
9120         else {
9121                 /* we have to go by the storage class */
9122                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9123                 
9124                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9125                 
9126                 if (SPEC_OCLS(etype)->codesp ) {
9127                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9128                         //p_type = CPOINTER ; 
9129                 }
9130                 else
9131                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9132                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9133                         /*p_type = FPOINTER ;*/ 
9134                         else
9135                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9136                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9137                                 /*        p_type = PPOINTER; */
9138                                 else
9139                                         if (SPEC_OCLS(etype) == idata )
9140                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9141                                         /*      p_type = IPOINTER; */
9142                                         else
9143                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9144                                         /*      p_type = POINTER ; */
9145         }
9146         
9147         /* now that we have the pointer type we assign
9148         the pointer values */
9149         switch (p_type) {
9150                 
9151         case POINTER: 
9152         case FPOINTER:
9153         //case IPOINTER:
9154                 genNearPointerGet (left,result,ic);
9155                 break;
9156 /*
9157         case PPOINTER:
9158                 genPagedPointerGet(left,result,ic);
9159                 break;
9160                 
9161         case FPOINTER:
9162                 genFarPointerGet (left,result,ic);
9163                 break;
9164 */              
9165         case CPOINTER:
9166                 genConstPointerGet (left,result,ic);
9167                 break;
9168                 
9169         case GPOINTER:
9170                 genGenPointerGet (left,result,ic);
9171                 break;
9172         default:
9173                 assert ( !"unhandled pointer type" );
9174                 break;
9175         }
9176         
9177 }
9178
9179 /*-----------------------------------------------------------------*/
9180 /* genPackBits - generates code for packed bit storage             */
9181 /*-----------------------------------------------------------------*/
9182 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9183 {
9184   int blen;             /* bitfield length */
9185   int bstr;             /* bitfield starting bit within byte */
9186   int litval;           /* source literal value (if AOP_LIT) */
9187   unsigned char mask;   /* bitmask within current byte */
9188
9189   FENTRY;
9190   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9191
9192   blen = SPEC_BLEN (etype);
9193   bstr = SPEC_BSTR (etype);
9194
9195   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9196   if ((blen <= 8) && ((bstr + blen) <= 8))
9197   {
9198     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9199             (unsigned char) (0xFF >> (8 - bstr)));
9200
9201     if (AOP_TYPE (right) == AOP_LIT)
9202     {
9203       /* Case with a bitfield length <8 and literal source */
9204       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9205       if (blen == 1) {
9206         pCodeOp *pcop;
9207         
9208         switch (p_type)
9209         {
9210         case -1:
9211           if (AOP(result)->type == AOP_PCODE)
9212             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9213           else
9214             pcop = popGet(AOP(result),0);
9215           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9216           break;
9217         
9218         case POINTER:
9219         case FPOINTER:
9220           setup_fsr (result);
9221           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9222           break;
9223         
9224         case CPOINTER:
9225           assert( !"trying to assign to bitfield via pointer to __code space" );
9226           break;
9227         
9228         case GPOINTER:
9229           emitPtrByteGet(result, p_type, FALSE);
9230           if (lit) {
9231             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9232           } else {
9233             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9234           }
9235           emitPtrByteSet(result, p_type, TRUE);
9236           break;
9237         
9238         default:
9239           assert( !"unhandled pointer type" );
9240           break;
9241         } // switch (p_type)
9242       } else {
9243         /* blen > 1 */
9244         litval = lit << bstr;
9245         litval &= (~mask) & 0x00ff;
9246         
9247         switch (p_type)
9248         {
9249         case -1:
9250           mov2w (AOP(result), 0);
9251           if ((litval|mask) != 0x00ff)
9252             emitpcode(POC_ANDLW, popGetLit (mask));
9253           if (litval != 0x00)
9254             emitpcode(POC_IORLW, popGetLit (litval));
9255           movwf (AOP(result), 0);
9256           break;
9257         
9258         case POINTER:
9259         case FPOINTER:
9260         case GPOINTER:
9261           emitPtrByteGet(result, p_type, FALSE);
9262           if ((litval|mask) != 0x00ff)
9263             emitpcode(POC_ANDLW, popGetLit (mask));
9264           if (litval != 0x00)
9265             emitpcode(POC_IORLW, popGetLit (litval));
9266           emitPtrByteSet(result, p_type, TRUE);
9267           break;
9268         
9269         case CPOINTER:
9270           assert( !"trying to assign to bitfield via pointer to __code space" );
9271           break;
9272         
9273         default:
9274           assert( !"unhandled pointer type" );
9275           break;
9276         } // switch
9277       } // if (blen > 1)
9278     }
9279     else
9280     {
9281       /* right is no literal */
9282       if (blen==1) {
9283         switch (p_type)
9284         {
9285         case -1:
9286           /* Note more efficient code, of pre clearing bit then only setting it if required,
9287            * can only be done if it is known that the result is not a SFR */
9288           emitpcode(POC_RRFW,popGet(AOP(right),0));
9289           emitSKPC;
9290           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9291           emitSKPNC;
9292           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9293           break;
9294         
9295         case POINTER:
9296         case FPOINTER:
9297         case GPOINTER:
9298           emitPtrByteGet (result, p_type, FALSE);
9299           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9300           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9301           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9302           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9303           emitPtrByteSet (result, p_type, TRUE);
9304           break;
9305         
9306         case CPOINTER:
9307           assert( !"trying to assign to bitfield via pointer to __code space" );
9308           break;
9309         
9310         default:
9311           assert( !"unhandled pointer type" );
9312           break;
9313         } // switch
9314         return;
9315       } else {
9316         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9317         pCodeOp *temp = popGetTempReg ();
9318
9319         mov2w (AOP(right), 0);
9320         if (blen < 8) {
9321           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9322         }
9323         emitpcode(POC_MOVWF, temp);
9324         if (bstr) {
9325           AccLsh (temp, bstr);
9326         }
9327         
9328         switch (p_type)
9329         {
9330         case -1:
9331           mov2w (AOP(result), 0);
9332           emitpcode(POC_ANDLW, popGetLit (mask));
9333           emitpcode(POC_IORFW, temp);
9334           movwf (AOP(result), 0);
9335           break;
9336         
9337         case POINTER:
9338         case FPOINTER:
9339         case GPOINTER:
9340           emitPtrByteGet (result, p_type, FALSE);
9341           emitpcode(POC_ANDLW, popGetLit (mask));
9342           emitpcode(POC_IORFW, temp);
9343           emitPtrByteSet (result, p_type, TRUE);
9344           break;
9345         
9346         case CPOINTER:
9347           assert( !"trying to assign to bitfield via pointer to __code space" );
9348           break;
9349         
9350         default:
9351           assert( !"unhandled pointer type" );
9352           break;
9353         } // switch
9354
9355         popReleaseTempReg (temp);
9356       } // if (blen > 1)
9357     } // if (AOP(right)->type != AOP_LIT)
9358     return;
9359   } // if (blen <= 8 && ((blen + bstr) <= 8))
9360
9361   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9362 }
9363
9364 unsigned long
9365 bitpatternFromVal (value *val)
9366 {
9367   union {
9368     float d;
9369     uint32_t l;
9370   } float_long;
9371
9372   assert (sizeof (float) == sizeof (uint32_t));
9373
9374   //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
9375
9376   switch (SPEC_NOUN(val->type))
9377   {
9378   case V_INT:
9379   case V_CHAR:
9380     return (unsigned long)floatFromVal (val);
9381     
9382   case V_FLOAT:
9383   case V_DOUBLE:
9384     float_long.d = floatFromVal (val);
9385     return float_long.l;
9386     
9387   default:
9388     assert( !"unhandled value type" );
9389     break;
9390   }
9391
9392   float_long.d = floatFromVal (val);
9393   return float_long.l;
9394 }
9395
9396 /*-----------------------------------------------------------------*/
9397 /* genDataPointerSet - remat pointer to data space                 */
9398 /*-----------------------------------------------------------------*/
9399 static void genDataPointerSet(operand *right,
9400         operand *result,
9401         iCode *ic)
9402 {
9403         int size, offset = 0 ;
9404         int ressize;
9405         
9406         FENTRY;
9407         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9408         aopOp(right,ic,FALSE);
9409         aopOp(result,ic,FALSE);
9410         
9411         assert (IS_SYMOP(result));
9412         assert (IS_PTR(OP_SYM_TYPE(result)));
9413         
9414         size = AOP_SIZE(right);
9415         ressize = getSize(OP_SYM_ETYPE(result));
9416         if (size > ressize) size = ressize;
9417         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9418         
9419         //assert( !"what's going on here?" );
9420
9421         /*
9422         if ( AOP_TYPE(result) == AOP_PCODE) {
9423         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9424         AOP(result)->aopu.pcop->name,
9425         PCOI(AOP(result)->aopu.pcop)->offset);
9426         }
9427         */
9428         
9429         // tsd, was l+1 - the underline `_' prefix was being stripped
9430         while (size--) {
9431                 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9432                 
9433                 if (AOP_TYPE(right) == AOP_LIT) {
9434                         /* XXX: might be float... */
9435                         unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9436                         lit = lit >> (8*offset);
9437                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9438                         if(lit&0xff) {
9439                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9440                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9441                         } else {
9442                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9443                         }
9444                 } else {
9445                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9446                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9447                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9448                 }
9449                 
9450                 offset++;
9451         }
9452         
9453         freeAsmop(right,NULL,ic,TRUE);
9454         freeAsmop(result,NULL,ic,TRUE);
9455 }
9456
9457 /*-----------------------------------------------------------------*/
9458 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9459 /*-----------------------------------------------------------------*/
9460 static void genNearPointerSet (operand *right,
9461                                                            operand *result, 
9462                                                            iCode *ic)
9463 {
9464         asmop *aop = NULL;
9465         sym_link *ptype = operandType(result);
9466         sym_link *retype = getSpec(operandType(right));
9467         sym_link *letype = getSpec(ptype);
9468         int direct = 0;
9469         
9470         
9471         FENTRY;
9472         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9473         aopOp(result,ic,FALSE);
9474         
9475 #if 1
9476         /* if the result is rematerializable &
9477         in data space & not a bit variable */
9478         //if (AOP_TYPE(result) == AOP_IMMD &&
9479         if (AOP_TYPE(result) == AOP_PCODE &&
9480                 PIC_IS_DATA_PTR(ptype) &&
9481                 !IS_BITVAR (retype) &&
9482                 !IS_BITVAR (letype)) {
9483                 genDataPointerSet (right,result,ic);
9484                 freeAsmop(result,NULL,ic,TRUE);
9485                 return;
9486         }
9487 #endif
9488
9489         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9490         aopOp(right,ic,FALSE);
9491         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9492         
9493         /* Check if can access directly instead of via a pointer */
9494         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9495                 direct = 1;
9496         }
9497         
9498         if (IS_BITFIELD (letype))
9499         {
9500           genPackBits (letype, result, right, direct?-1:POINTER);
9501           return;
9502         }
9503         
9504         /* If the pointer value is not in a the FSR then need to put it in */
9505         /* Must set/reset IRP bit for use with FSR. */
9506         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9507         if (!direct)
9508                 setup_fsr (result);
9509
9510         {
9511                 /* we have can just get the values */
9512                 int size = AOP_SIZE(right);
9513                 int offset = 0 ;    
9514                 
9515                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9516                 while (size--) {
9517                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9518                         if (*l == '@' ) {
9519                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9520                         } else {
9521                                 if (AOP_TYPE(right) == AOP_LIT) {
9522                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9523                                 } else {
9524                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9525                                 }
9526                                 if (direct)
9527                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9528                                 else
9529                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9530                         }
9531                         if (size && !direct)
9532                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9533                         offset++;
9534                 }
9535         }
9536         
9537         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9538         /* now some housekeeping stuff */
9539         if (aop) {
9540                 /* we had to allocate for this iCode */
9541                 freeAsmop(NULL,aop,ic,TRUE);
9542         } else { 
9543                 /* we did not allocate which means left
9544                 already in a pointer register, then
9545                 if size > 0 && this could be used again
9546                 we have to point it back to where it 
9547                 belongs */
9548                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9549                 if (AOP_SIZE(right) > 1 &&
9550                         !OP_SYMBOL(result)->remat &&
9551                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9552                         ic->depth )) {
9553                         int size = AOP_SIZE(right) - 1;
9554                         while (size--)
9555                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9556                 }
9557         }
9558         
9559         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9560         /* done */
9561
9562         freeAsmop(right,NULL,ic,TRUE);
9563         freeAsmop(result,NULL,ic,TRUE);
9564 }
9565
9566 #if 0
9567 /*-----------------------------------------------------------------*/
9568 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9569 /*-----------------------------------------------------------------*/
9570 static void genPagedPointerSet (operand *right,
9571                                                                 operand *result, 
9572                                                                 iCode *ic)
9573 {
9574         asmop *aop = NULL;
9575         regs *preg = NULL ;
9576         char *rname , *l;
9577         sym_link *retype;
9578         
9579         FENTRY;
9580         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9581         
9582         retype= getSpec(operandType(right));
9583         
9584         aopOp(result,ic,FALSE);
9585         
9586         /* if the value is already in a pointer register
9587         then don't need anything more */
9588         if (!AOP_INPREG(AOP(result))) {
9589                 /* otherwise get a free pointer register */
9590                 aop = newAsmop(0);
9591                 preg = getFreePtr(ic,&aop,FALSE);
9592                 pic14_emitcode("mov","%s,%s",
9593                         preg->name,
9594                         aopGet(AOP(result),0,FALSE,TRUE));
9595                 rname = preg->name ;
9596         } else
9597                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9598         
9599         freeAsmop(result,NULL,ic,TRUE);
9600         aopOp (right,ic,FALSE);
9601         
9602         /* if bitfield then unpack the bits */
9603         if (IS_BITFIELD(retype)) 
9604                 genPackBits (retype,result,right,rname,PPOINTER);
9605         else {
9606                 /* we have can just get the values */
9607                 int size = AOP_SIZE(right);
9608                 int offset = 0 ;  
9609                 
9610                 while (size--) {
9611                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9612                         
9613                         MOVA(l);
9614                         pic14_emitcode("movx","@%s,a",rname);
9615                         
9616                         if (size)
9617                                 pic14_emitcode("inc","%s",rname);
9618                         
9619                         offset++;
9620                 }
9621         }
9622         
9623         /* now some housekeeping stuff */
9624         if (aop) {
9625                 /* we had to allocate for this iCode */
9626                 freeAsmop(NULL,aop,ic,TRUE);
9627         } else { 
9628         /* we did not allocate which means left
9629         already in a pointer register, then
9630         if size > 0 && this could be used again
9631         we have to point it back to where it 
9632                 belongs */
9633                 if (AOP_SIZE(right) > 1 &&
9634                         !OP_SYMBOL(result)->remat &&
9635                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9636                         ic->depth )) {
9637                         int size = AOP_SIZE(right) - 1;
9638                         while (size--)
9639                                 pic14_emitcode("dec","%s",rname);
9640                 }
9641         }
9642         
9643         /* done */
9644         freeAsmop(right,NULL,ic,TRUE);
9645         
9646         
9647 }
9648
9649 /*-----------------------------------------------------------------*/
9650 /* genFarPointerSet - set value from far space                     */
9651 /*-----------------------------------------------------------------*/
9652 static void genFarPointerSet (operand *right,
9653                                                           operand *result, iCode *ic)
9654 {
9655         int size, offset ;
9656         sym_link *retype = getSpec(operandType(right));
9657         
9658         FENTRY;
9659         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9660         aopOp(result,ic,FALSE);
9661         
9662         /* if the operand is already in dptr 
9663         then we do nothing else we move the value to dptr */
9664         if (AOP_TYPE(result) != AOP_STR) {
9665                 /* if this is remateriazable */
9666                 if (AOP_TYPE(result) == AOP_IMMD)
9667                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9668                 else { /* we need to get it byte by byte */
9669                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9670                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9671                         if (options.model == MODEL_FLAT24)
9672                         {
9673                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9674                         }
9675                 }
9676         }
9677         /* so dptr know contains the address */
9678         freeAsmop(result,NULL,ic,TRUE);
9679         aopOp(right,ic,FALSE);
9680         
9681         /* if bit then unpack */
9682         if (IS_BITFIELD(retype)) 
9683                 genPackBits(retype,result,right,"dptr",FPOINTER);
9684         else {
9685                 size = AOP_SIZE(right);
9686                 offset = 0 ;
9687                 
9688                 while (size--) {
9689                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9690                         MOVA(l);
9691                         pic14_emitcode("movx","@dptr,a");
9692                         if (size)
9693                                 pic14_emitcode("inc","dptr");
9694                 }
9695         }
9696         
9697         freeAsmop(right,NULL,ic,TRUE);
9698 }
9699 #endif
9700
9701 /*-----------------------------------------------------------------*/
9702 /* genGenPointerSet - set value from generic pointer space         */
9703 /*-----------------------------------------------------------------*/
9704 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9705 {
9706         sym_link *retype = getSpec(operandType(result));
9707         
9708         FENTRY;
9709         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9710         aopOp(right,ic,FALSE);
9711         aopOp(result,ic,FALSE);
9712
9713         
9714         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9715
9716         if (IS_BITFIELD(retype))
9717         {
9718           genPackBits (retype, result, right, GPOINTER);
9719           return;
9720         }
9721
9722         {
9723           /* emit call to __gptrput */
9724           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9725           int size = AOP_SIZE(right);
9726           int idx = 0;
9727
9728           assert (size == getSize(OP_SYM_ETYPE(result)));
9729           assert (size > 0 && size <= 4);
9730
9731           /* pass arguments */
9732           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9733           {
9734             int off = size;
9735             idx = 2;
9736             while (off--)
9737             {
9738               mov2w_op (right, off);
9739               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9740             }
9741             idx = 0;
9742           }
9743           /* - address */
9744           assert (AOP_SIZE(result) == 3);
9745           mov2w(AOP(result), 0);
9746           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9747           mov2w(AOP(result), 1);
9748           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9749           mov2w(AOP(result), 2);
9750           call_libraryfunc (func[size]);
9751         }
9752         
9753         freeAsmop(right,NULL,ic,TRUE);
9754         freeAsmop(result,NULL,ic,TRUE);
9755 }
9756
9757 /*-----------------------------------------------------------------*/
9758 /* genPointerSet - stores the value into a pointer location        */
9759 /*-----------------------------------------------------------------*/
9760 static void genPointerSet (iCode *ic)
9761 {    
9762         operand *right, *result ;
9763         sym_link *type, *etype;
9764         int p_type;
9765         
9766         FENTRY;
9767         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9768         
9769         right = IC_RIGHT(ic);
9770         result = IC_RESULT(ic) ;
9771         
9772         /* depending on the type of pointer we need to
9773         move it to the correct pointer register */
9774         type = operandType(result);
9775         etype = getSpec(type);
9776         /* if left is of type of pointer then it is simple */
9777         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9778                 p_type = DCL_TYPE(type);
9779         }
9780         else {
9781                 /* we have to go by the storage class */
9782                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9783                 
9784                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9785                 /*      p_type = CPOINTER ;  */
9786                 /*  } */
9787                 /*  else */
9788                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9789                 /*    p_type = FPOINTER ; */
9790                 /*      else */
9791                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9792                 /*        p_type = PPOINTER ; */
9793                 /*    else */
9794                 /*        if (SPEC_OCLS(etype) == idata ) */
9795                 /*      p_type = IPOINTER ; */
9796                 /*        else */
9797                 /*      p_type = POINTER ; */
9798         }
9799         
9800         /* now that we have the pointer type we assign
9801         the pointer values */
9802         switch (p_type) {
9803                 
9804         case POINTER:
9805         case FPOINTER:
9806         //case IPOINTER:
9807                 genNearPointerSet (right,result,ic);
9808                 break;
9809 /*
9810         case PPOINTER:
9811                 genPagedPointerSet (right,result,ic);
9812                 break;
9813                 
9814         case FPOINTER:
9815                 genFarPointerSet (right,result,ic);
9816                 break;
9817 */
9818         case GPOINTER:
9819                 genGenPointerSet (right,result,ic);
9820                 break;
9821                 
9822         default:
9823                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9824                         "genPointerSet: illegal pointer type");
9825         }
9826 }
9827
9828 /*-----------------------------------------------------------------*/
9829 /* genIfx - generate code for Ifx statement                        */
9830 /*-----------------------------------------------------------------*/
9831 static void genIfx (iCode *ic, iCode *popIc)
9832 {
9833         operand *cond = IC_COND(ic);
9834         int isbit =0;
9835         
9836         FENTRY;
9837         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9838         
9839         aopOp(cond,ic,FALSE);
9840         
9841         /* get the value into acc */
9842         if (AOP_TYPE(cond) != AOP_CRY)
9843                 pic14_toBoolean(cond);
9844         else
9845                 isbit = 1;
9846         
9847         /* if there was something to be popped then do it */
9848         if (popIc)
9849                 genIpop(popIc);
9850         
9851         if (isbit)
9852         {
9853                 /* This assumes that CARRY is set iff cond is true */
9854                 if (IC_TRUE(ic))
9855                 {
9856                         assert (!IC_FALSE(ic));
9857                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9858                         //emitSKPNC;
9859                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9860                 } else {
9861                         assert (IC_FALSE(ic));
9862                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9863                         //emitSKPC;
9864                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9865                 }
9866                 if (0)
9867                 {
9868                         static int hasWarned = 0;
9869                         if (!hasWarned)
9870                         {
9871                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9872                                 hasWarned = 1;
9873                         }
9874                 }
9875         }
9876         else
9877         {
9878                 /* now Z is set iff !cond */
9879                 if (IC_TRUE(ic))
9880                 {
9881                         assert (!IC_FALSE(ic));
9882                         emitSKPZ;
9883                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9884                 } else {
9885                         emitSKPNZ;
9886                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9887                 }
9888         }
9889         
9890         ic->generated = 1;
9891         
9892         /* the result is now in the accumulator */
9893         freeAsmop(cond,NULL,ic,TRUE);
9894 }
9895
9896 /*-----------------------------------------------------------------*/
9897 /* genAddrOf - generates code for address of                       */
9898 /*-----------------------------------------------------------------*/
9899 static void genAddrOf (iCode *ic)
9900 {
9901         operand *right, *result, *left;
9902         int size, offset ;
9903         
9904         FENTRY;
9905         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9906         
9907         
9908         //aopOp(IC_RESULT(ic),ic,FALSE);
9909         
9910         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9911         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9912         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9913         
9914         DEBUGpic14_AopType(__LINE__,left,right,result);
9915         assert (IS_SYMOP (left));
9916         
9917         /* sanity check: generic pointers to code space are not yet supported,
9918          * pionters to codespace must not be assigned addresses of __data values. */
9919  #if 0
9920         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9921         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)));
9922         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)));
9923         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)));
9924         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)));
9925 #endif
9926
9927         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9928           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9929                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9930                 OP_SYMBOL(left)->name);
9931         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9932           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9933                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9934                 OP_SYMBOL(left)->name);
9935         }
9936         
9937         size = AOP_SIZE(IC_RESULT(ic));
9938         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9939                 /* strip tag */
9940                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9941         }
9942         offset = 0;
9943         
9944         while (size--) {
9945                 /* fixing bug #863624, reported from (errolv) */
9946                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9947                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9948                 
9949 #if 0
9950                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9951                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9952 #endif
9953                 offset++;
9954         }
9955
9956         if (IS_GENPTR(OP_SYM_TYPE(result)))
9957         {
9958                 /* provide correct tag */
9959                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9960                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9961                 movwf (AOP(result), 2);
9962         }
9963         
9964         freeAsmop(left,NULL,ic,FALSE);
9965         freeAsmop(result,NULL,ic,TRUE);
9966         
9967 }
9968
9969 #if 0
9970 /*-----------------------------------------------------------------*/
9971 /* genFarFarAssign - assignment when both are in far space         */
9972 /*-----------------------------------------------------------------*/
9973 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9974 {
9975         int size = AOP_SIZE(right);
9976         int offset = 0;
9977         char *l ;
9978         /* first push the right side on to the stack */
9979         while (size--) {
9980                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9981                 MOVA(l);
9982                 pic14_emitcode ("push","acc");
9983         }
9984         
9985         freeAsmop(right,NULL,ic,FALSE);
9986         /* now assign DPTR to result */
9987         aopOp(result,ic,FALSE);
9988         size = AOP_SIZE(result);
9989         while (size--) {
9990                 pic14_emitcode ("pop","acc");
9991                 aopPut(AOP(result),"a",--offset);
9992         }
9993         freeAsmop(result,NULL,ic,FALSE);
9994         
9995 }
9996 #endif
9997
9998 /*-----------------------------------------------------------------*/
9999 /* genAssign - generate code for assignment                        */
10000 /*-----------------------------------------------------------------*/
10001 static void genAssign (iCode *ic)
10002 {
10003         operand *result, *right;
10004         int size, offset,know_W;
10005         unsigned long lit = 0L;
10006         
10007         result = IC_RESULT(ic);
10008         right  = IC_RIGHT(ic) ;
10009         
10010         FENTRY;
10011         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10012         
10013         /* if they are the same */
10014         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10015                 return ;
10016         
10017         aopOp(right,ic,FALSE);
10018         aopOp(result,ic,TRUE);
10019         
10020         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10021         
10022         /* if they are the same registers */
10023         if (pic14_sameRegs(AOP(right),AOP(result)))
10024                 goto release;
10025
10026         /* special case: assign from __code */
10027         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10028                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10029                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10030                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10031                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10032         {
10033           emitpComment ("genAssign from CODESPACE");
10034           genConstPointerGet (right, result, ic);
10035           goto release;
10036         }
10037         
10038         /* just for symmetry reasons... */
10039         if (!IS_ITEMP(result)
10040                 && IS_SYMOP (result)
10041                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10042         {
10043           assert ( !"cannot write to CODESPACE" );
10044         }
10045
10046         /* if the result is a bit */
10047         if (AOP_TYPE(result) == AOP_CRY) {
10048                 
10049         /* if the right size is a literal then
10050                 we know what the value is */
10051                 if (AOP_TYPE(right) == AOP_LIT) {
10052                         
10053                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10054                                 popGet(AOP(result),0));
10055                         
10056                         if (((int) operandLitValue(right))) 
10057                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10058                                 AOP(result)->aopu.aop_dir,
10059                                 AOP(result)->aopu.aop_dir);
10060                         else
10061                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10062                                 AOP(result)->aopu.aop_dir,
10063                                 AOP(result)->aopu.aop_dir);
10064                         goto release;
10065                 }
10066                 
10067                 /* the right is also a bit variable */
10068                 if (AOP_TYPE(right) == AOP_CRY) {
10069                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10070                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10071                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10072                         
10073                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10074                                 AOP(result)->aopu.aop_dir,
10075                                 AOP(result)->aopu.aop_dir);
10076                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10077                                 AOP(right)->aopu.aop_dir,
10078                                 AOP(right)->aopu.aop_dir);
10079                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10080                                 AOP(result)->aopu.aop_dir,
10081                                 AOP(result)->aopu.aop_dir);
10082                         goto release ;
10083                 }
10084                 
10085                 /* we need to or */
10086                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10087                 pic14_toBoolean(right);
10088                 emitSKPZ;
10089                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10090                 //aopPut(AOP(result),"a",0);
10091                 goto release ;
10092         }
10093         
10094         /* bit variables done */
10095         /* general case */
10096         size = AOP_SIZE(result);
10097         offset = 0 ;
10098         if(AOP_TYPE(right) == AOP_LIT)
10099                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10100         
10101         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10102                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10103                 if(aopIdx(AOP(result),0) == 4) {
10104                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10105                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10106                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10107                         goto release;
10108                 } else
10109                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10110         }
10111         
10112         know_W=-1;
10113         while (size--) {
10114                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10115                 if(AOP_TYPE(right) == AOP_LIT) {
10116                         if(lit&0xff) {
10117                                 if(know_W != (int)(lit&0xff))
10118                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10119                                 know_W = lit&0xff;
10120                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10121                         } else
10122                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10123                         
10124                         lit >>= 8;
10125                         
10126                 } else if (AOP_TYPE(right) == AOP_CRY) {
10127                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10128                         if(offset == 0) {
10129                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10130                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10131                         }
10132                 } else {
10133                         mov2w_op (right, offset);
10134                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10135                 }
10136                 
10137                 offset++;
10138         }
10139         
10140         
10141 release:
10142         freeAsmop (right,NULL,ic,FALSE);
10143         freeAsmop (result,NULL,ic,TRUE);
10144 }   
10145
10146 /*-----------------------------------------------------------------*/
10147 /* genJumpTab - genrates code for jump table                       */
10148 /*-----------------------------------------------------------------*/
10149 static void genJumpTab (iCode *ic)
10150 {
10151         symbol *jtab;
10152         char *l;
10153         
10154         FENTRY;
10155         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10156         
10157         aopOp(IC_JTCOND(ic),ic,FALSE);
10158         /* get the condition into accumulator */
10159         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10160         MOVA(l);
10161         /* multiply by three */
10162         pic14_emitcode("add","a,acc");
10163         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10164         
10165         jtab = newiTempLabel(NULL);
10166         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10167         pic14_emitcode("jmp","@a+dptr");
10168         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10169         
10170         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10171         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10172         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10173         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10174         emitSKPNC;
10175         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10176         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10177         emitpLabel(jtab->key);
10178         
10179         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10180         
10181         /* now generate the jump labels */
10182         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10183         jtab = setNextItem(IC_JTLABELS(ic))) {
10184                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10185                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10186                 
10187         }
10188         
10189 }
10190
10191 /*-----------------------------------------------------------------*/
10192 /* genMixedOperation - gen code for operators between mixed types  */
10193 /*-----------------------------------------------------------------*/
10194 /*
10195 TSD - Written for the PIC port - but this unfortunately is buggy.
10196 This routine is good in that it is able to efficiently promote 
10197 types to different (larger) sizes. Unfortunately, the temporary
10198 variables that are optimized out by this routine are sometimes
10199 used in other places. So until I know how to really parse the 
10200 iCode tree, I'm going to not be using this routine :(.
10201 */
10202 static int genMixedOperation (iCode *ic)
10203 {
10204         FENTRY;
10205 #if 0
10206         operand *result = IC_RESULT(ic);
10207         sym_link *ctype = operandType(IC_LEFT(ic));
10208         operand *right = IC_RIGHT(ic);
10209         int ret = 0;
10210         int big,small;
10211         int offset;
10212         
10213         iCode *nextic;
10214         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10215         
10216         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10217         
10218         nextic = ic->next;
10219         if(!nextic)
10220                 return 0;
10221         
10222         nextright = IC_RIGHT(nextic);
10223         nextleft  = IC_LEFT(nextic);
10224         nextresult = IC_RESULT(nextic);
10225         
10226         aopOp(right,ic,FALSE);
10227         aopOp(result,ic,FALSE);
10228         aopOp(nextright,  nextic, FALSE);
10229         aopOp(nextleft,   nextic, FALSE);
10230         aopOp(nextresult, nextic, FALSE);
10231         
10232         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10233                 
10234                 operand *t = right;
10235                 right = nextright;
10236                 nextright = t; 
10237                 
10238                 pic14_emitcode(";remove right +","");
10239                 
10240         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10241         /*
10242         operand *t = right;
10243         right = nextleft;
10244         nextleft = t; 
10245                 */
10246                 pic14_emitcode(";remove left +","");
10247         } else
10248                 return 0;
10249         
10250         big = AOP_SIZE(nextleft);
10251         small = AOP_SIZE(nextright);
10252         
10253         switch(nextic->op) {
10254                 
10255         case '+':
10256                 pic14_emitcode(";optimize a +","");
10257                 /* if unsigned or not an integral type */
10258                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10259                         pic14_emitcode(";add a bit to something","");
10260                 } else {
10261                         
10262                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10263                         
10264                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10265                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10266                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10267                         } else
10268                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10269                         
10270                         offset = 0;
10271                         while(--big) {
10272                                 
10273                                 offset++;
10274                                 
10275                                 if(--small) {
10276                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10277                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10278                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10279                                         }
10280                                         
10281                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10282                                         emitSKPNC;
10283                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10284                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10285                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10286                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10287                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10288                                         
10289                                 } else {
10290                                         pic14_emitcode("rlf","known_zero,w");
10291                                         
10292                                         /*
10293                                         if right is signed
10294                                         btfsc  right,7
10295                                         addlw ff
10296                                         */
10297                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10298                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10299                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10300                                         } else {
10301                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10302                                         }
10303                                 }
10304                         }
10305                         ret = 1;
10306                 }
10307         }
10308         ret = 1;
10309         
10310 release:
10311         freeAsmop(right,NULL,ic,TRUE);
10312         freeAsmop(result,NULL,ic,TRUE);
10313         freeAsmop(nextright,NULL,ic,TRUE);
10314         freeAsmop(nextleft,NULL,ic,TRUE);
10315         if(ret)
10316                 nextic->generated = 1;
10317         
10318         return ret;
10319 #else
10320         return 0;
10321 #endif
10322 }
10323 /*-----------------------------------------------------------------*/
10324 /* genCast - gen code for casting                                  */
10325 /*-----------------------------------------------------------------*/
10326 static void genCast (iCode *ic)
10327 {
10328         operand *result = IC_RESULT(ic);
10329         sym_link *restype = operandType(result);
10330         sym_link *rtype = operandType(IC_RIGHT(ic));
10331         operand *right = IC_RIGHT(ic);
10332         int size, offset ;
10333         
10334         FENTRY;
10335         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10336         /* if they are equivalent then do nothing */
10337         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10338                 return ;
10339         
10340         aopOp(right,ic,FALSE) ;
10341         aopOp(result,ic,FALSE);
10342         
10343         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10344         
10345         /* if the result is a bit */
10346         if (AOP_TYPE(result) == AOP_CRY) {
10347                 assert(!"assigning to bit variables is not supported");
10348         }
10349         
10350         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10351                 int offset = 1;
10352                 size = AOP_SIZE(result);
10353                 
10354                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10355                 
10356                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10357                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10358                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10359                 
10360                 while (size--)
10361                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10362                 
10363                 goto release;
10364         }
10365         
10366         if (IS_PTR(restype))
10367         {
10368           operand *result = IC_RESULT(ic);
10369           //operand *left = IC_LEFT(ic);
10370           operand *right = IC_RIGHT(ic);
10371           int tag = 0xff;
10372           
10373           /* copy common part */
10374           int max, size = AOP_SIZE(result);
10375           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10376           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10377
10378           /* warn if we discard generic opinter tag */
10379           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10380           {
10381             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10382           } // if
10383
10384           max = size;
10385           while (size--)
10386           {
10387             mov2w_op (right, size);
10388             movwf (AOP(result), size);
10389           } // while
10390
10391           /* upcast into generic pointer type? */
10392           if (IS_GENPTR(restype)
10393                 && (size < AOP_SIZE(result))
10394                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10395           {
10396             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10397             if (IS_PTR(rtype))
10398             {
10399               switch (DCL_TYPE(rtype))
10400               {
10401               case POINTER:     /* __data */
10402               case FPOINTER:    /* __data */
10403                 assert (AOP_SIZE(right) == 2);
10404                 tag = GPTRTAG_DATA;
10405                 break;
10406
10407               case CPOINTER:    /* __code */
10408                 assert (AOP_SIZE(right) == 2);
10409                 tag = GPTRTAG_CODE;
10410                 break;
10411                 
10412               case GPOINTER:    /* unknown destination, __data or __code */
10413                 /* assume __data space (address of immediate) */
10414                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10415                 if (AOP(right)->code)
10416                   tag = GPTRTAG_CODE;
10417                 else
10418                   tag = GPTRTAG_DATA;
10419                 break;
10420                 
10421               default:
10422                 assert (!"unhandled pointer type");
10423               } // switch
10424             } else {
10425               /* convert other values into pointers to __data space */
10426               tag = GPTRTAG_DATA;
10427             }
10428
10429             assert (AOP_SIZE(result) == 3);
10430             if (tag == 0) {
10431               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10432             } else {
10433               emitpcode(POC_MOVLW, popGetLit(tag));
10434               movwf(AOP(result), 2);
10435             }
10436           } else {
10437             addSign(result, max, 0);
10438           } // if
10439           goto release;
10440         }
10441         
10442         /* if they are the same size : or less */
10443         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10444                 
10445                 /* if they are in the same place */
10446                 if (pic14_sameRegs(AOP(right),AOP(result)))
10447                         goto release;
10448                 
10449                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10450                 if (IS_PTR_CONST(rtype))
10451                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10452                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10453                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10454                 
10455                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10456                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10457                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10458                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10459                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10460                         if(AOP_SIZE(result) <2)
10461                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10462                         
10463                 } else {
10464                         
10465                         /* if they in different places then copy */
10466                         size = AOP_SIZE(result);
10467                         offset = 0 ;
10468                         while (size--) {
10469                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10470                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10471                                 
10472                                 //aopPut(AOP(result),
10473                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10474                                 // offset);
10475                                 
10476                                 offset++;
10477                         }
10478                 }
10479                 goto release;
10480         }
10481         
10482         /* so we now know that the size of destination is greater
10483         than the size of the source.
10484         Now, if the next iCode is an operator then we might be
10485         able to optimize the operation without performing a cast.
10486         */
10487         if(0 && genMixedOperation(ic)) {
10488                 /* XXX: cannot optimize: must copy regs! */
10489                 goto release;
10490         }
10491         
10492         /* we move to result for the size of source */
10493         size = AOP_SIZE(right);
10494         offset = 0 ;
10495         while (size--) {
10496                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10497                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10498                 offset++;
10499         }
10500
10501         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10502
10503 release:
10504         freeAsmop(right,NULL,ic,TRUE);
10505         freeAsmop(result,NULL,ic,TRUE);
10506         
10507 }
10508
10509 /*-----------------------------------------------------------------*/
10510 /* genDjnz - generate decrement & jump if not zero instrucion      */
10511 /*-----------------------------------------------------------------*/
10512 static int genDjnz (iCode *ic, iCode *ifx)
10513 {
10514         symbol *lbl, *lbl1;
10515         FENTRY;
10516         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10517         
10518         if (!ifx)
10519                 return 0;
10520         
10521                 /* if the if condition has a false label
10522         then we cannot save */
10523         if (IC_FALSE(ifx))
10524                 return 0;
10525         
10526                 /* if the minus is not of the form 
10527         a = a - 1 */
10528         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10529                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10530                 return 0;
10531         
10532         if (operandLitValue(IC_RIGHT(ic)) != 1)
10533                 return 0;
10534         
10535                 /* if the size of this greater than one then no
10536         saving */
10537         if (getSize(operandType(IC_RESULT(ic))) > 1)
10538                 return 0;
10539         
10540         /* otherwise we can save BIG */
10541         lbl = newiTempLabel(NULL);
10542         lbl1= newiTempLabel(NULL);
10543         
10544         aopOp(IC_RESULT(ic),ic,FALSE);
10545         
10546         if (IS_AOP_PREG(IC_RESULT(ic))) {
10547                 pic14_emitcode("dec","%s",
10548                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10549                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10550                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10551         } else {  
10552                 
10553                 
10554                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10555                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10556                 
10557                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10558                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10559                 
10560         }
10561         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10562         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10563         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10564         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10565         
10566         
10567         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10568         ifx->generated = 1;
10569         return 1;
10570 }
10571
10572 /*-----------------------------------------------------------------*/
10573 /* genReceive - generate code for a receive iCode                  */
10574 /*-----------------------------------------------------------------*/
10575 static void genReceive (iCode *ic)
10576 {
10577         FENTRY;
10578         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10579         
10580         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10581                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10582                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10583                 
10584                 int size = getSize(operandType(IC_RESULT(ic)));
10585                 int offset =  fReturnSizePic - size;
10586                 while (size--) {
10587                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10588                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10589                         offset++;
10590                 }
10591                 aopOp(IC_RESULT(ic),ic,FALSE);
10592                 size = AOP_SIZE(IC_RESULT(ic));
10593                 offset = 0;
10594                 while (size--) {
10595                         pic14_emitcode ("pop","acc");
10596                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10597                 }
10598                 
10599         } else {
10600                 _G.accInUse++;
10601                 aopOp(IC_RESULT(ic),ic,FALSE);
10602                 _G.accInUse--;
10603                 assignResultValue(IC_RESULT(ic));
10604         }
10605         
10606         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10607 }
10608
10609 /*-----------------------------------------------------------------*/
10610 /* genDummyRead - generate code for dummy read of volatiles        */
10611 /*-----------------------------------------------------------------*/
10612 static void
10613 genDummyRead (iCode * ic)
10614 {
10615         FENTRY;
10616         pic14_emitcode ("; genDummyRead","");
10617         pic14_emitcode ("; not implemented","");
10618         
10619         ic = ic;
10620 }
10621
10622 /*-----------------------------------------------------------------*/
10623 /* genpic14Code - generate code for pic14 based controllers        */
10624 /*-----------------------------------------------------------------*/
10625 /*
10626 * At this point, ralloc.c has gone through the iCode and attempted
10627 * to optimize in a way suitable for a PIC. Now we've got to generate
10628 * PIC instructions that correspond to the iCode.
10629 *
10630 * Once the instructions are generated, we'll pass through both the
10631 * peep hole optimizer and the pCode optimizer.
10632 *-----------------------------------------------------------------*/
10633
10634 void genpic14Code (iCode *lic)
10635 {
10636         iCode *ic;
10637         int cln = 0;
10638         const char *cline;
10639         
10640         FENTRY;
10641         lineHead = lineCurr = NULL;
10642         
10643         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10644         addpBlock(pb);
10645         
10646         /* if debug information required */
10647         if (options.debug && currFunc) { 
10648                 if (currFunc) {
10649                         debugFile->writeFunction (currFunc, lic);
10650                 }
10651         }
10652         
10653         
10654         for (ic = lic ; ic ; ic = ic->next ) {
10655                 
10656                 //DEBUGpic14_emitcode(";ic","");
10657                 //fprintf (stderr, "in ic loop\n");
10658                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10659                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10660                 
10661                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10662                   cln = ic->lineno;
10663                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10664                   cline = printCLine (ic->filename, ic->lineno);
10665                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10666                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10667                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10668                 }
10669                 
10670                 if (options.iCodeInAsm) {
10671                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10672                 }
10673                 /* if the result is marked as
10674                 spilt and rematerializable or code for
10675                 this has already been generated then
10676                 do nothing */
10677                 if (resultRemat(ic) || ic->generated ) 
10678                         continue ;
10679                 
10680                 /* depending on the operation */
10681                 switch (ic->op) {
10682                 case '!' :
10683                         genNot(ic);
10684                         break;
10685                         
10686                 case '~' :
10687                         genCpl(ic);
10688                         break;
10689                         
10690                 case UNARYMINUS:
10691                         genUminus (ic);
10692                         break;
10693                         
10694                 case IPUSH:
10695                         genIpush (ic);
10696                         break;
10697                         
10698                 case IPOP:
10699                         /* IPOP happens only when trying to restore a 
10700                         spilt live range, if there is an ifx statement
10701                         following this pop then the if statement might
10702                         be using some of the registers being popped which
10703                         would destory the contents of the register so
10704                         we need to check for this condition and handle it */
10705                         if (ic->next            && 
10706                                 ic->next->op == IFX &&
10707                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10708                                 genIfx (ic->next,ic);
10709                         else
10710                                 genIpop (ic);
10711                         break; 
10712                         
10713                 case CALL:
10714                         genCall (ic);
10715                         break;
10716                         
10717                 case PCALL:
10718                         genPcall (ic);
10719                         break;
10720                         
10721                 case FUNCTION:
10722                         genFunction (ic);
10723                         break;
10724                         
10725                 case ENDFUNCTION:
10726                         genEndFunction (ic);
10727                         break;
10728                         
10729                 case RETURN:
10730                         genRet (ic);
10731                         break;
10732                         
10733                 case LABEL:
10734                         genLabel (ic);
10735                         break;
10736                         
10737                 case GOTO:
10738                         genGoto (ic);
10739                         break;
10740                         
10741                 case '+' :
10742                         genPlus (ic) ;
10743                         break;
10744                         
10745                 case '-' :
10746                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10747                                 genMinus (ic);
10748                         break;
10749                         
10750                 case '*' :
10751                         genMult (ic);
10752                         break;
10753                         
10754                 case '/' :
10755                         genDiv (ic) ;
10756                         break;
10757                         
10758                 case '%' :
10759                         genMod (ic);
10760                         break;
10761                         
10762                 case '>' :
10763                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10764                         break;
10765                         
10766                 case '<' :
10767                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10768                         break;
10769                         
10770                 case LE_OP:
10771                 case GE_OP:
10772                 case NE_OP:
10773                         
10774                         /* note these two are xlated by algebraic equivalence
10775                         during parsing SDCC.y */
10776                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10777                                 "got '>=' or '<=' shouldn't have come here");
10778                         break;  
10779                         
10780                 case EQ_OP:
10781                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10782                         break;      
10783                         
10784                 case AND_OP:
10785                         genAndOp (ic);
10786                         break;
10787                         
10788                 case OR_OP:
10789                         genOrOp (ic);
10790                         break;
10791                         
10792                 case '^' :
10793                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10794                         break;
10795                         
10796                 case '|' :
10797                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10798                         break;
10799                         
10800                 case BITWISEAND:
10801                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10802                         break;
10803                         
10804                 case INLINEASM:
10805                         genInline (ic);
10806                         break;
10807                         
10808                 case RRC:
10809                         genRRC (ic);
10810                         break;
10811                         
10812                 case RLC:
10813                         genRLC (ic);
10814                         break;
10815                         
10816                 case GETHBIT:
10817                         genGetHbit (ic);
10818                         break;
10819                         
10820                 case LEFT_OP:
10821                         genLeftShift (ic);
10822                         break;
10823                         
10824                 case RIGHT_OP:
10825                         genRightShift (ic);
10826                         break;
10827                         
10828                 case GET_VALUE_AT_ADDRESS:
10829                         genPointerGet(ic);
10830                         break;
10831                         
10832                 case '=' :
10833                         if (POINTER_SET(ic))
10834                                 genPointerSet(ic);
10835                         else
10836                                 genAssign(ic);
10837                         break;
10838                         
10839                 case IFX:
10840                         genIfx (ic,NULL);
10841                         break;
10842                         
10843                 case ADDRESS_OF:
10844                         genAddrOf (ic);
10845                         break;
10846                         
10847                 case JUMPTABLE:
10848                         genJumpTab (ic);
10849                         break;
10850                         
10851                 case CAST:
10852                         genCast (ic);
10853                         break;
10854                         
10855                 case RECEIVE:
10856                         genReceive(ic);
10857                         break;
10858                         
10859                 case SEND:
10860                         addSet(&_G.sendSet,ic);
10861                         break;
10862                         
10863                 case DUMMY_READ_VOLATILE:
10864                         genDummyRead (ic);
10865                         break;
10866                         
10867                 default :
10868                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10869                         ic = ic;
10870                         break;
10871                 }
10872         }
10873
10874         
10875         /* now we are ready to call the
10876         peep hole optimizer */
10877         if (!options.nopeep) {
10878                 peepHole (&lineHead);
10879         }
10880         /* now do the actual printing */
10881         printLine (lineHead,codeOutFile);
10882         
10883 #ifdef PCODE_DEBUG
10884         DFPRINTF((stderr,"printing pBlock\n\n"));
10885         printpBlock(stdout,pb);
10886 #endif
10887         
10888         return;
10889 }
10890
10891 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10892  * (meaning: representing its own address) or not (referencing its contents).
10893  * This can only be decided based on the operand's type. */
10894 int
10895 aop_isLitLike (asmop *aop)
10896 {
10897   assert (aop);
10898   if (aop->type == AOP_LIT) return 1;
10899 if (aop->type == AOP_IMMD) return 1;
10900   if ((aop->type == AOP_PCODE) &&
10901                 ((aop->aopu.pcop->type == PO_LITERAL)))
10902   {
10903     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10904      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10905     return 1;
10906   }
10907   return 0;
10908 }
10909
10910 int
10911 op_isLitLike (operand *op)
10912 {
10913   assert (op);
10914   if (aop_isLitLike (AOP(op))) return 1;
10915   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10916   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10917   return 0;
10918 }