7cf251c42bc1ada681fbb381e1cc67a7167f9a01
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8     cont'd   -  Raphael Neider <rneider AT web.de> (2005)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
30       Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h" 
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "glue.h"
46
47 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
48 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
49 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
50
51 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
53 void genMult8X8_8 (operand *, operand *,operand *);
54 extern void printpBlock(FILE *of, pBlock *pb);
55
56 static int labelOffset=0;
57 extern int debug_verbose;
58 extern int pic14_hasInterrupt;
59 //static int optimized_for_speed = 0;
60
61 /* max_key keeps track of the largest label number used in 
62 a function. This is then used to adjust the label offset
63 for the next function.
64 */
65 static int max_key=0;
66 static int GpsuedoStkPtr=0;
67 static int pic14_inISR = 0;
68
69 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
70 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
71 const char *AopType(short type);
72
73 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
74
75 /* this is the down and dirty file with all kinds of 
76 kludgy & hacky stuff. This is what it is all about
77 CODE GENERATION for a specific MCU . some of the
78 routines may be reusable, will have to see */
79
80 static char *zero = "0x00";
81 static char *one  = "0x01";
82 static char *spname = "sp";
83
84 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
85 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
86 static char **fReturn = fReturnpic14;
87
88 //static char *accUse[] = {"a","b"};
89
90 //static short rbank = -1;
91
92 static struct {
93         short r0Pushed;
94         short r1Pushed;
95         short accInUse;
96         short inLine;
97         short debugLine;
98         short nRegsSaved;
99         set *sendSet;
100 } _G;
101
102 /* Resolved ifx structure. This structure stores information
103 about an iCode ifx that makes it easier to generate code.
104 */
105 typedef struct resolvedIfx {
106         symbol *lbl;     /* pointer to a label */
107         int condition;   /* true or false ifx */
108         int generated;   /* set true when the code associated with the ifx
109                           * is generated */
110 } resolvedIfx;
111
112 extern int pic14_ptrRegReq ;
113 extern int pic14_nRegs;
114 extern struct dbuf_s *codeOutBuf;
115 static void saverbank (int, iCode *,bool);
116
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
119
120 #if 0
121 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
124 0x07, 0x03, 0x01, 0x00};
125 #endif
126
127 static  pBlock *pb;
128
129 /*-----------------------------------------------------------------*/
130 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
131 /*                                 exponent of 2 is returned, otherwise -1 is      */
132 /*                                 returned.                                                                       */
133 /* note that this is similar to the function `powof2' in SDCCsymt  */
134 /* if(n == 2^y)                                                                                                    */
135 /*       return y;                                                                                                         */
136 /* return -1;                                                                                                      */
137 /*-----------------------------------------------------------------*/
138 static int my_powof2 (unsigned long num)
139 {
140         if(num) {
141                 if( (num & (num-1)) == 0) {
142                         int nshifts = -1;
143                         while(num) {
144                                 num>>=1;
145                                 nshifts++;
146                         }
147                         return nshifts;
148                 }
149         }
150         
151         return -1;
152 }
153
154 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
155 {
156         
157         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
158                 line_no,
159                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
160                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
161                 ((result) ? AOP_SIZE(result) : 0),
162                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
163                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
164                 ((left)   ? AOP_SIZE(left) : 0),
165                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
166                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
167                 ((right)  ? AOP_SIZE(right) : 0));
168         
169 }
170
171 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
172 {
173         
174         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
175                 line_no,
176                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
177                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
178                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
179                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
180                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
181                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
182         
183 }
184
185 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
186 {
187         va_list ap;
188         char lb[INITIAL_INLINEASM];  
189         unsigned char *lbp = (unsigned char *)lb;
190         
191         if(!debug_verbose && !options.debug)
192                 return;
193         
194         va_start(ap,fmt);   
195         
196         if (inst && *inst) {
197                 if (fmt && *fmt)
198                         sprintf(lb,"%s\t",inst);
199                 else
200                         sprintf(lb,"%s",inst);
201                 vsprintf(lb+(strlen(lb)),fmt,ap);
202         }  else
203                 vsprintf(lb,fmt,ap);
204         
205         while (isspace(*lbp)) lbp++;
206         
207         if (lbp && *lbp) 
208                 lineCurr = (lineCurr ?
209                 connectLine(lineCurr,newLineNode(lb)) :
210         (lineHead = newLineNode(lb)));
211         lineCurr->isInline = _G.inLine;
212         lineCurr->isDebug  = _G.debugLine;
213         
214         addpCode2pBlock(pb,newpCodeCharP(lb));
215         
216         va_end(ap);
217 }
218
219 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
220 {
221 #if defined (HAVE_VSNPRINTF)
222   vsnprintf (buf, size, fmt, ap);
223 #elif defined (HAVE_VSPRINTF)
224   vsprintf (buf, size, fmt, ap);
225   if (strlen (buf) >= size)
226   {
227     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
228   }
229 #elif defined (HAVE_SNPRINTF)
230   snprintf (buf, size, "vs(n)printf required");
231 #elif defined (HAVE_SRINTF)
232   sprintf (buf, "vs(n)printf required");
233   if (strlen (buf) >= size)
234   {
235     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
236   }
237 #else
238   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
239 #endif
240 }
241
242 void emitpComment (const char *fmt, ...)
243 {
244   va_list va;
245   char buffer[4096];
246   
247   va_start (va, fmt);
248   if (pb) {
249     Safe_vsnprintf (buffer, 4096, fmt, va);
250     //fprintf (stderr, "%s\n" ,buffer);
251     addpCode2pBlock (pb, newpCodeCharP (buffer));
252 #if 0
253   } else {
254     Safe_vsnprintf (buffer, 4096, fmt, va);
255     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
256 #endif
257   }
258   va_end (va);
259 }
260
261 void emitpLabel(int key)
262 {
263         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
264 }
265
266 /* gen.h defines a macro emitpcode that should be used to call emitpcode
267  * as this allows for easy debugging (ever asked the question: where was
268  * this instruction geenrated? Here is the answer... */
269 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
270 {
271         if(pcop)
272                 addpCode2pBlock(pb,newpCode(poc,pcop));
273         else {
274                 static int has_warned = 0;
275                 
276                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
277                 if (!has_warned) {
278                         has_warned = 1;
279                         fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
280                 }
281         }
282 }
283
284 void emitpcodeNULLop(PIC_OPCODE poc)
285 {
286         
287         addpCode2pBlock(pb,newpCode(poc,NULL));
288         
289 }
290
291
292 /*-----------------------------------------------------------------*/
293 /* pic14_emitcode - writes the code into a file : for now it is simple    */
294 /*-----------------------------------------------------------------*/
295 void pic14_emitcode (char *inst,char *fmt, ...)
296 {
297         va_list ap;
298         char lb[INITIAL_INLINEASM];  
299         char *lbp = lb;
300         
301         va_start(ap,fmt);   
302         
303         if (inst && *inst) {
304                 if (fmt && *fmt)
305                         sprintf(lb,"%s\t",inst);
306                 else
307                         sprintf(lb,"%s",inst);
308                 vsprintf(lb+(strlen(lb)),fmt,ap);
309         }  else
310                 vsprintf(lb,fmt,ap);
311         
312         while (isspace(*lbp)) lbp++;
313         
314         if (lbp && *lbp) 
315                 lineCurr = (lineCurr ?
316                 connectLine(lineCurr,newLineNode(lb)) :
317         (lineHead = newLineNode(lb)));
318         lineCurr->isInline = _G.inLine;
319         lineCurr->isDebug  = _G.debugLine;
320         lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
321         
322         if(debug_verbose)
323                 addpCode2pBlock(pb,newpCodeCharP(lb));
324         
325         va_end(ap);
326 }
327
328 /*-----------------------------------------------------------------*/
329 /* pic14_emitDebuggerSymbol - associate the current code location  */
330 /*       with a debugger symbol                                                                            */
331 /*-----------------------------------------------------------------*/
332 void
333 pic14_emitDebuggerSymbol (char * debugSym)
334 {
335         _G.debugLine = 1;
336         pic14_emitcode ("", ";%s ==.", debugSym);
337         _G.debugLine = 0;
338 }
339
340 #if 0
341 /*-----------------------------------------------------------------*/
342 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
343 /*-----------------------------------------------------------------*/
344 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
345 {
346         bool r0iu = FALSE , r1iu = FALSE;
347         bool r0ou = FALSE , r1ou = FALSE;
348         
349         /* the logic: if r0 & r1 used in the instruction
350         then we are in trouble otherwise */
351         
352         /* first check if r0 & r1 are used by this
353         instruction, in which case we are in trouble */
354         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
355                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
356         {
357                 goto endOfWorld;          
358         }
359         
360         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
361         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
362         
363         /* if no usage of r0 then return it */
364         if (!r0iu && !r0ou) {
365                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
366                 (*aopp)->type = AOP_R0;
367                 
368                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
369         }
370         
371         /* if no usage of r1 then return it */
372         if (!r1iu && !r1ou) {
373                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
374                 (*aopp)->type = AOP_R1;
375                 
376                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
377         }    
378         
379         /* now we know they both have usage */
380         /* if r0 not used in this instruction */
381         if (!r0iu) {
382                 /* push it if not already pushed */
383                 if (!_G.r0Pushed) {
384                         //pic14_emitcode ("push","%s",
385                         //                pic14_regWithIdx(R0_IDX)->dname);
386                         _G.r0Pushed++ ;
387                 }
388                 
389                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
390                 (*aopp)->type = AOP_R0;
391                 
392                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
393         }
394         
395         /* if r1 not used then */
396         
397         if (!r1iu) {
398                 /* push it if not already pushed */
399                 if (!_G.r1Pushed) {
400                         //pic14_emitcode ("push","%s",
401                         //                pic14_regWithIdx(R1_IDX)->dname);
402                         _G.r1Pushed++ ;
403                 }
404                 
405                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
406                 (*aopp)->type = AOP_R1;
407                 return pic14_regWithIdx(R1_IDX);
408         }
409         
410 endOfWorld :
411         /* I said end of world but not quite end of world yet */
412         /* if this is a result then we can push it on the stack*/
413         if (result) {
414                 (*aopp)->type = AOP_STK;        
415                 return NULL;
416         }
417         
418         /* other wise this is true end of the world */
419         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
420                 "getFreePtr should never reach here");
421         exit(0);
422 }
423 #endif
424
425 /*-----------------------------------------------------------------*/
426 /* newAsmop - creates a new asmOp                                                                  */
427 /*-----------------------------------------------------------------*/
428 asmop *newAsmop (short type)
429 {
430         asmop *aop;
431         
432         aop = Safe_calloc(1,sizeof(asmop));
433         aop->type = type;
434         return aop;
435 }
436
437 static void genSetDPTR(int n)
438 {
439         if (!n)
440         {
441                 pic14_emitcode(";", "Select standard DPTR");
442                 pic14_emitcode("mov", "dps, #0x00");
443         }
444         else
445         {
446                 pic14_emitcode(";", "Select alternate DPTR");
447                 pic14_emitcode("mov", "dps, #0x01");
448         }
449 }
450
451 /*-----------------------------------------------------------------*/
452 /* resolveIfx - converts an iCode ifx into a form more useful for  */
453 /*                              generating code                                                                    */
454 /*-----------------------------------------------------------------*/
455 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
456 {
457         if(!resIfx) 
458                 return;
459         
460         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
461         
462         resIfx->condition = 1;  /* assume that the ifx is true */
463         resIfx->generated = 0;  /* indicate that the ifx has not been used */
464         
465         if(!ifx) {
466                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
467                                                                                         /*
468                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
469                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
470                 */
471         } else {
472                 if(IC_TRUE(ifx)) {
473                         resIfx->lbl = IC_TRUE(ifx);
474                 } else {
475                         resIfx->lbl = IC_FALSE(ifx);
476                         resIfx->condition = 0;
477                 }
478                 /*
479                 if(IC_TRUE(ifx)) 
480                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
481                 if(IC_FALSE(ifx)) 
482                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
483                 */
484         }
485         
486         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
487         
488 }
489 /*-----------------------------------------------------------------*/
490 /* pointerCode - returns the code for a pointer type                       */
491 /*-----------------------------------------------------------------*/
492 #if 0
493 static int pointerCode (sym_link *etype)
494 {
495         
496         return PTR_TYPE(SPEC_OCLS(etype));
497         
498 }
499 #endif
500
501 /*-----------------------------------------------------------------*/
502 /* aopForSym - for a true symbol                                                                   */
503 /*-----------------------------------------------------------------*/
504 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
505 {
506         asmop *aop;
507         memmap *space= SPEC_OCLS(sym->etype);
508         
509         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
510         /* if already has one */
511         if (sym->aop)
512                 return sym->aop;
513         
514         //DEBUGpic14_emitcode(";","%d",__LINE__);
515         /* if it is in direct space */
516         if (IN_DIRSPACE(space)) {
517                 sym->aop = aop = newAsmop (AOP_DIR);
518                 aop->aopu.aop_dir = sym->rname ;
519                 aop->size = getSize(sym->type);
520                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
521                 return aop;
522         }
523         
524         /* special case for a function */
525         if (IS_FUNC(sym->type)) {   
526                 
527                 sym->aop = aop = newAsmop(AOP_PCODE);
528                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
529                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
530                 PCOI(aop->aopu.pcop)->_function = 1;
531                 PCOI(aop->aopu.pcop)->index = 0;
532                 aop->size = FPTRSIZE; 
533                 /*
534                 sym->aop = aop = newAsmop(AOP_IMMD);    
535                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
536                 strcpy(aop->aopu.aop_immd,sym->rname);
537                 aop->size = FPTRSIZE; 
538                 */
539                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
540                 return aop;
541         }
542         
543         if (IS_ARRAY(sym->type)) {
544                 sym->aop = aop = newAsmop(AOP_PCODE);
545                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
546                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
547                 PCOI(aop->aopu.pcop)->_function = 0;
548                 PCOI(aop->aopu.pcop)->index = 0;
549                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
550                 
551                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
552                 return aop;
553         }
554         
555         /* only remaining is far space */
556         /* in which case DPTR gets the address */
557         sym->aop = aop = newAsmop(AOP_PCODE);
558         
559         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
560         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
561         PCOI(aop->aopu.pcop)->index = 0;
562         
563         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
564                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
565         
566         allocDirReg (IC_LEFT(ic));
567         
568         aop->size = FPTRSIZE;
569         /*
570         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
571         sym->aop = aop = newAsmop(AOP_DPTR);
572         pic14_emitcode ("mov","dptr,#%s", sym->rname);
573         aop->size = getSize(sym->type);
574         
575           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
576         */
577         
578         /* if it is in code space */
579         if (IN_CODESPACE(space))
580                 aop->code = 1;
581         
582         return aop;       
583 }
584
585 /*-----------------------------------------------------------------*/
586 /* aopForRemat - rematerialzes an object                                                   */
587 /*-----------------------------------------------------------------*/
588 static asmop *aopForRemat (operand *op) // x symbol *sym)
589 {
590         symbol *sym = OP_SYMBOL(op);
591         iCode *ic = NULL;
592         asmop *aop = newAsmop(AOP_PCODE);
593         int val = 0;
594         int offset = 0;
595         
596         ic = sym->rematiCode;
597
598         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
599         if(IS_OP_POINTER(op)) {
600                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
601         }
602         for (;;) {
603                 if (ic->op == '+') {
604                         val += (int) operandLitValue(IC_RIGHT(ic));
605                 } else if (ic->op == '-') {
606                         val -= (int) operandLitValue(IC_RIGHT(ic));
607                 } else
608                         break;
609                 
610                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
611         }
612         
613         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
614         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
615         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
616         PCOI(aop->aopu.pcop)->index = val;
617         
618         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
619                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
620                 val, IS_PTR_CONST(operandType(op)));
621         
622         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
623         
624         allocDirReg (IC_LEFT(ic));
625         
626         return aop;              
627 }
628
629 int aopIdx (asmop *aop, int offset)
630 {
631         if(!aop)
632                 return -1;
633         
634         if(aop->type !=  AOP_REG)
635                 return -2;
636         
637         return aop->aopu.aop_reg[offset]->rIdx;
638         
639 }
640 /*-----------------------------------------------------------------*/
641 /* regsInCommon - two operands have some registers in common       */
642 /*-----------------------------------------------------------------*/
643 static bool regsInCommon (operand *op1, operand *op2)
644 {
645         symbol *sym1, *sym2;
646         int i;
647         
648         /* if they have registers in common */
649         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
650                 return FALSE ;
651         
652         sym1 = OP_SYMBOL(op1);
653         sym2 = OP_SYMBOL(op2);
654         
655         if (sym1->nRegs == 0 || sym2->nRegs == 0)
656                 return FALSE ;
657         
658         for (i = 0 ; i < sym1->nRegs ; i++) {
659                 int j;
660                 if (!sym1->regs[i])
661                         continue ;
662                 
663                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
664                         if (!sym2->regs[j])
665                                 continue ;
666                         
667                         if (sym2->regs[j] == sym1->regs[i])
668                                 return TRUE ;
669                 }
670         }
671         
672         return FALSE ;
673 }
674
675 /*-----------------------------------------------------------------*/
676 /* operandsEqu - equivalent                                                                        */
677 /*-----------------------------------------------------------------*/
678 static bool operandsEqu ( operand *op1, operand *op2)
679 {
680         symbol *sym1, *sym2;
681         
682         /* if they not symbols */
683         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
684                 return FALSE;
685         
686         sym1 = OP_SYMBOL(op1);
687         sym2 = OP_SYMBOL(op2);
688         
689         /* if both are itemps & one is spilt
690         and the other is not then false */
691         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
692                 sym1->isspilt != sym2->isspilt )
693                 return FALSE ;
694         
695         /* if they are the same */
696         if (sym1 == sym2)
697                 return TRUE ;
698         
699         if (sym1->rname[0] && sym2->rname[0]
700                 && strcmp (sym1->rname, sym2->rname) == 0)
701                 return TRUE;
702         
703         
704         /* if left is a tmp & right is not */
705         if (IS_ITEMP(op1)  && 
706                 !IS_ITEMP(op2) &&
707                 sym1->isspilt  &&
708                 (sym1->usl.spillLoc == sym2))
709                 return TRUE;
710         
711         if (IS_ITEMP(op2)  && 
712                 !IS_ITEMP(op1) &&
713                 sym2->isspilt  &&
714                 sym1->level > 0 &&
715                 (sym2->usl.spillLoc == sym1))
716                 return TRUE ;
717         
718         return FALSE ;
719 }
720
721 /*-----------------------------------------------------------------*/
722 /* pic14_sameRegs - two asmops have the same registers             */
723 /*-----------------------------------------------------------------*/
724 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
725 {
726         int i;
727         
728         if (aop1 == aop2)
729                 return TRUE ;
730         
731         if (aop1->type != AOP_REG ||
732                 aop2->type != AOP_REG )
733                 return FALSE ;
734         
735         if (aop1->size != aop2->size )
736                 return FALSE ;
737         
738         for (i = 0 ; i < aop1->size ; i++ )
739                 if (aop1->aopu.aop_reg[i] !=
740                         aop2->aopu.aop_reg[i] )
741                         return FALSE ;
742                 
743                 return TRUE ;
744 }
745
746 /*-----------------------------------------------------------------*/
747 /* aopOp - allocates an asmop for an operand  :                    */
748 /*-----------------------------------------------------------------*/
749 void aopOp (operand *op, iCode *ic, bool result)
750 {
751         asmop *aop;
752         symbol *sym;
753         int i;
754         
755         if (!op)
756                 return ;
757         
758         /* if this a literal */
759         if (IS_OP_LITERAL(op)) {
760                 op->aop = aop = newAsmop(AOP_LIT);
761                 aop->aopu.aop_lit = op->operand.valOperand;
762                 aop->size = getSize(operandType(op));
763                 return;
764         }
765         
766         {
767                 sym_link *type = operandType(op);
768                 if(IS_PTR_CONST(type))
769                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
770         }
771         
772         /* if already has a asmop then continue */
773         if (op->aop)
774                 return ;
775         
776         /* if the underlying symbol has a aop */
777         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
778                 DEBUGpic14_emitcode(";","%d",__LINE__);
779                 op->aop = OP_SYMBOL(op)->aop;
780                 return;
781         }
782         
783         /* if this is a true symbol */
784         if (IS_TRUE_SYMOP(op)) {          
785                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
786                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
787                 return ;
788         }
789         
790         /* this is a temporary : this has
791         only four choices :
792         a) register
793         b) spillocation
794         c) rematerialize 
795         d) conditional   
796         e) can be a return use only */
797         
798         sym = OP_SYMBOL(op);
799         
800         
801         /* if the type is a conditional */
802         if (sym->regType == REG_CND) {
803                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
804                 aop->size = 0;
805                 return;
806         }
807         
808         /* if it is spilt then two situations
809         a) is rematerialize 
810         b) has a spill location */
811         if (sym->isspilt || sym->nRegs == 0) {
812                 
813                 DEBUGpic14_emitcode(";","%d",__LINE__);
814                 /* rematerialize it NOW */
815                 if (sym->remat) {
816                         
817                         sym->aop = op->aop = aop = aopForRemat (op);
818                         aop->size = getSize(sym->type);
819                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
820                         return;
821                 }
822                 
823 #if 0
824                 /* WREG is not usable as an ordinary operand with PIC architecture,
825                  * one might introduce a scratch register that can be used to make
826                  * WREG accesible as an operand... disable WREG for now */
827                 if (sym->accuse) {
828                         int i;
829                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
830                         aop->size = getSize(sym->type);
831                         for ( i = 0 ; i < 2 ; i++ )
832                                 aop->aopu.aop_str[i] = accUse[i];
833                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
834                         return;  
835                 }
836 #endif
837                 
838                 if (sym->ruonly ) {
839                         if(sym->isptr) {        // && sym->uptr 
840                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
841                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
842                                 
843                                 //PCOI(aop->aopu.pcop)->_const = 0;
844                                 //PCOI(aop->aopu.pcop)->index = 0;
845                                 /*
846                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
847                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
848                                 */
849                                 //allocDirReg (IC_LEFT(ic));
850                                 
851                                 aop->size = getSize(sym->type);
852                                 DEBUGpic14_emitcode(";","%d",__LINE__);
853                                 return;
854                                 
855                         } else {
856                                 
857                                 unsigned i;
858                                 
859                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
860                                 aop->size = getSize(sym->type);
861                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
862                                         aop->aopu.aop_str[i] = fReturn[i];
863                                 
864                                 DEBUGpic14_emitcode(";","%d",__LINE__);
865                                 return;
866                         }
867                 }
868                 
869                 /* else spill location  */
870                 if (sym->usl.spillLoc)
871                 {
872                         asmop *oldAsmOp = NULL;
873
874                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
875                         {
876                                 /* force a new aop if sizes differ */
877                                 oldAsmOp = sym->usl.spillLoc->aop;
878                                 sym->usl.spillLoc->aop = NULL;
879                         }
880                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
881                                 __FUNCTION__,__LINE__,
882                                 sym->usl.spillLoc->rname,
883                                 sym->rname, sym->usl.spillLoc->offset);
884                 
885                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
886                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
887                         {
888                                 /* Don't reuse the new aop, go with the last one */
889                                 sym->usl.spillLoc->aop = oldAsmOp;
890                         }
891                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
892                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
893                                 getSize(sym->type), 
894                                 sym->usl.spillLoc->offset);
895                         aop->size = getSize(sym->type);
896                 
897                         return;
898                 }
899         }
900         
901         {
902                 sym_link *type = operandType(op);
903                 if(IS_PTR_CONST(type)) 
904                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
905         }
906         
907         /* must be in a register */
908         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
909         sym->aop = op->aop = aop = newAsmop(AOP_REG);
910         aop->size = sym->nRegs;
911         for ( i = 0 ; i < sym->nRegs ;i++)
912                 aop->aopu.aop_reg[i] = sym->regs[i];
913 }
914
915 /*-----------------------------------------------------------------*/
916 /* freeAsmop - free up the asmop given to an operand                       */
917 /*----------------------------------------------------------------*/
918 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
919 {       
920         asmop *aop ;
921         
922         if (!op)
923                 aop = aaop;
924         else 
925                 aop = op->aop;
926         
927         if (!aop)
928                 return ;
929         
930         if (aop->freed)
931                 goto dealloc; 
932         
933         aop->freed = 1;
934         
935         /* depending on the asmop type only three cases need work AOP_RO
936         , AOP_R1 && AOP_STK */
937 #if 0
938         switch (aop->type) {
939         case AOP_R0 :
940                 if (_G.r0Pushed ) {
941                         if (pop) {
942                                 pic14_emitcode ("pop","ar0");     
943                                 _G.r0Pushed--;
944                         }
945                 }
946                 bitVectUnSetBit(ic->rUsed,R0_IDX);
947                 break;
948                 
949         case AOP_R1 :
950                 if (_G.r1Pushed ) {
951                         if (pop) {
952                                 pic14_emitcode ("pop","ar1");
953                                 _G.r1Pushed--;
954                         }
955                 }
956                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
957                 break;
958                 
959         case AOP_STK :
960                 {
961                         int sz = aop->size;      
962                         int stk = aop->aopu.aop_stk + aop->size;
963                         bitVectUnSetBit(ic->rUsed,R0_IDX);
964                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
965                         
966                         getFreePtr(ic,&aop,FALSE);
967                         
968                         if (options.stack10bit)
969                         {
970                                 /* I'm not sure what to do here yet... */
971                                 /* #STUB */
972                                 fprintf(stderr, 
973                                         "*** Warning: probably generating bad code for "
974                                         "10 bit stack mode.\n");
975                         }
976                         
977                         if (stk) {
978                                 pic14_emitcode ("mov","a,_bp");
979                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
980                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
981                         } else {
982                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
983                         }
984                         
985                         while (sz--) {
986                                 pic14_emitcode("pop","acc");
987                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
988                                 if (!sz) break;
989                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
990                         }
991                         op->aop = aop;
992                         freeAsmop(op,NULL,ic,TRUE);
993                         if (_G.r0Pushed) {
994                                 pic14_emitcode("pop","ar0");
995                                 _G.r0Pushed--;
996                         }
997                         
998                         if (_G.r1Pushed) {
999                                 pic14_emitcode("pop","ar1");
1000                                 _G.r1Pushed--;
1001                         }         
1002                 }
1003         }
1004 #endif
1005         
1006 dealloc:
1007         /* all other cases just dealloc */
1008         if (op ) {
1009                 op->aop = NULL;
1010                 if (IS_SYMOP(op)) {
1011                         OP_SYMBOL(op)->aop = NULL;      
1012                         /* if the symbol has a spill */
1013                         if (SPIL_LOC(op))
1014                                 SPIL_LOC(op)->aop = NULL;
1015                 }
1016         }
1017 }
1018
1019 /*-----------------------------------------------------------------*/
1020 /* aopGet - for fetching value of the aop                                                  */
1021 /*-----------------------------------------------------------------*/
1022 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1023 {
1024         char *s = buffer ;
1025         char *rs;
1026         
1027         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1028         /* offset is greater than
1029         size then zero */
1030         assert(aop);
1031         if (offset > (aop->size - 1) &&
1032                 aop->type != AOP_LIT)
1033                 return zero;
1034         
1035         /* depending on type */
1036         switch (aop->type) {
1037                 
1038         case AOP_R0:
1039         case AOP_R1:
1040                 DEBUGpic14_emitcode(";","%d",__LINE__);
1041                 /* if we need to increment it */           
1042                 while (offset > aop->coff) {            
1043                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1044                         aop->coff++;
1045                 }
1046                 
1047                 while (offset < aop->coff) {
1048                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1049                         aop->coff--;
1050                 }
1051                 
1052                 aop->coff = offset ;
1053                 if (aop->paged) {
1054                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1055                         return (dname ? "acc" : "a");
1056                 }               
1057                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1058                 rs = Safe_calloc(1,strlen(s)+1);
1059                 strcpy(rs,s);   
1060                 return rs;
1061                 
1062         case AOP_DPTR:
1063         case AOP_DPTR2:
1064                 DEBUGpic14_emitcode(";","%d",__LINE__);
1065                 if (aop->type == AOP_DPTR2)
1066                 {
1067                         genSetDPTR(1);
1068                 }
1069                 
1070                 while (offset > aop->coff) {
1071                         pic14_emitcode ("inc","dptr");
1072                         aop->coff++;
1073                 }
1074                 
1075                 while (offset < aop->coff) {            
1076                         pic14_emitcode("lcall","__decdptr");
1077                         aop->coff--;
1078                 }
1079                 
1080                 aop->coff = offset;
1081                 if (aop->code) {
1082                         pic14_emitcode("clr","a");
1083                         pic14_emitcode("movc","a,@a+dptr");
1084                 }
1085                 else {
1086                         pic14_emitcode("movx","a,@dptr");
1087                 }
1088                 
1089                 if (aop->type == AOP_DPTR2)
1090                 {
1091                         genSetDPTR(0);
1092                 }
1093                 
1094                 return (dname ? "acc" : "a");
1095                 
1096                 
1097         case AOP_IMMD:
1098                 if (bit16) 
1099                         sprintf (s,"%s",aop->aopu.aop_immd);
1100                 else
1101                         if (offset) 
1102                                 sprintf(s,"(%s >> %d)",
1103                                 aop->aopu.aop_immd,
1104                                 offset*8);
1105                         else
1106                                 sprintf(s,"%s",
1107                                 aop->aopu.aop_immd);
1108                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1109                         rs = Safe_calloc(1,strlen(s)+1);
1110                         strcpy(rs,s);   
1111                         return rs;
1112                         
1113         case AOP_DIR:
1114                 if (offset) {
1115                         sprintf(s,"(%s + %d)",
1116                                 aop->aopu.aop_dir,
1117                                 offset);
1118                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1119                 } else
1120                         sprintf(s,"%s",aop->aopu.aop_dir);
1121                 rs = Safe_calloc(1,strlen(s)+1);
1122                 strcpy(rs,s);   
1123                 return rs;
1124                 
1125         case AOP_REG:
1126                 //if (dname) 
1127                 //        return aop->aopu.aop_reg[offset]->dname;
1128                 //else
1129                 return aop->aopu.aop_reg[offset]->name;
1130                 
1131         case AOP_CRY:
1132                 //pic14_emitcode(";","%d",__LINE__);
1133                 return aop->aopu.aop_dir;
1134                 
1135         case AOP_ACC:
1136                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1137                 return "AOP_accumulator_bug";
1138                 
1139         case AOP_LIT:
1140                 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1141                 rs = Safe_strdup(s);
1142                 return rs;
1143                 
1144         case AOP_STR:
1145                 aop->coff = offset ;
1146                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1147                         dname)
1148                         return "acc";
1149                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1150                 
1151                 return aop->aopu.aop_str[offset];
1152                 
1153         case AOP_PCODE:
1154                 {
1155                         pCodeOp *pcop = aop->aopu.pcop;
1156                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1157                         if(pcop->name) {
1158                                 if (pcop->type == PO_IMMEDIATE) {
1159                                         offset += PCOI(pcop)->index;
1160                                 }
1161                                 if (offset) {
1162                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1163                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1164                                 } else {
1165                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1166                                         sprintf(s,"%s", pcop->name);
1167                                 }
1168                         } else
1169                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1170                         
1171                 }
1172                 rs = Safe_calloc(1,strlen(s)+1);
1173                 strcpy(rs,s);   
1174                 return rs;
1175                 
1176   }
1177   
1178   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1179           "aopget got unsupported aop->type");
1180   exit(0);
1181 }
1182
1183
1184 /*-----------------------------------------------------------------*/
1185 /* popGetTempReg - create a new temporary pCodeOp                                  */
1186 /*-----------------------------------------------------------------*/
1187 pCodeOp *popGetTempReg(void)
1188 {
1189         
1190         pCodeOp *pcop;
1191         
1192         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1193         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1194                 PCOR(pcop)->r->wasUsed=1;
1195                 PCOR(pcop)->r->isFree=0;
1196         }
1197         
1198         return pcop;
1199 }
1200
1201 /*-----------------------------------------------------------------*/
1202 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1203 /*-----------------------------------------------------------------*/
1204 void popReleaseTempReg(pCodeOp *pcop)
1205 {
1206         
1207         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1208                 PCOR(pcop)->r->isFree = 1;
1209         
1210 }
1211 /*-----------------------------------------------------------------*/
1212 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1213 /*-----------------------------------------------------------------*/
1214 pCodeOp *popGetLabel(unsigned int key)
1215 {
1216         
1217         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1218         
1219         if(key>(unsigned int)max_key)
1220                 max_key = key;
1221         
1222         return newpCodeOpLabel(NULL,key+100+labelOffset);
1223 }
1224
1225 /*-------------------------------------------------------------------*/
1226 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1227 /*-------------------------------------------------------------------*/
1228 pCodeOp *popGetHighLabel(unsigned int key)
1229 {
1230         pCodeOp *pcop;
1231         pcop = popGetLabel(key);
1232         PCOLAB(pcop)->offset = 1;
1233         return pcop;
1234 }
1235
1236 /*-----------------------------------------------------------------*/
1237 /* popGetLit - asm operator to pcode operator conversion                           */
1238 /*-----------------------------------------------------------------*/
1239 pCodeOp *popGetLit(unsigned int lit)
1240 {
1241         
1242         return newpCodeOpLit((unsigned char)lit);
1243 }
1244
1245 /*-----------------------------------------------------------------*/
1246 /* popGetImmd - asm operator to pcode immediate conversion                 */
1247 /*-----------------------------------------------------------------*/
1248 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1249 {
1250         
1251         return newpCodeOpImmd(name, offset,index, 0, is_func);
1252 }
1253
1254 extern set *externs;
1255
1256 /*-----------------------------------------------------------------*/
1257 /* popGetWithString - asm operator to pcode operator conversion                    */
1258 /*-----------------------------------------------------------------*/
1259 pCodeOp *popGetWithString(char *str, int isExtern)
1260 {
1261         pCodeOp *pcop;
1262         
1263         
1264         if(!str) {
1265                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1266                 exit (1);
1267         }
1268         
1269         pcop = newpCodeOp(str,PO_STR);
1270         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1271
1272         return pcop;
1273 }
1274
1275 pCodeOp *popGetExternal (char *str)
1276 {
1277         pCodeOp *pcop = popGetWithString (str, 1);
1278         
1279         if (str) {
1280           symbol *sym;
1281           bool found = 0;
1282
1283           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1284           {
1285             if (!strcmp (str, sym->rname))
1286               found = 1;
1287           }
1288           
1289           if (!found)
1290           {
1291             sym = newSymbol(str, 0);
1292             strncpy(sym->rname, str, SDCC_NAME_MAX);
1293             addSet (&externs, sym);
1294           } // if
1295         }
1296         return pcop;
1297 }
1298
1299 /*-----------------------------------------------------------------*/
1300 /* popRegFromString -                                                                                      */
1301 /*-----------------------------------------------------------------*/
1302 pCodeOp *popRegFromString(char *str, int size, int offset)
1303 {
1304         
1305         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1306         pcop->type = PO_DIR;
1307         
1308         DEBUGpic14_emitcode(";","%d",__LINE__);
1309         
1310         if(!str)
1311                 str = "BAD_STRING";
1312         
1313         pcop->name = Safe_calloc(1,strlen(str)+1);
1314         strcpy(pcop->name,str);
1315         
1316         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1317         
1318         PCOR(pcop)->r = dirregWithName(pcop->name);
1319         if(PCOR(pcop)->r == NULL) {
1320                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1321                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1322                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1323         } else {
1324                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1325         }
1326         PCOR(pcop)->instance = offset;
1327         
1328         return pcop;
1329 }
1330
1331 /*-----------------------------------------------------------------*/
1332 /*-----------------------------------------------------------------*/
1333 pCodeOp *popRegFromIdx(int rIdx)
1334 {
1335         pCodeOp *pcop;
1336         
1337         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1338                 __FUNCTION__,__LINE__,rIdx);
1339         
1340         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1341         
1342         PCOR(pcop)->rIdx = rIdx;
1343         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1344         PCOR(pcop)->r->isFree = 0;
1345         PCOR(pcop)->r->wasUsed = 1;
1346         
1347         pcop->type = PCOR(pcop)->r->pc_type;
1348         
1349         
1350         return pcop;
1351 }
1352
1353 /*-----------------------------------------------------------------*/
1354 /* popGet - asm operator to pcode operator conversion                      */
1355 /*-----------------------------------------------------------------*/
1356 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1357 {
1358         //char *s = buffer ;
1359         //char *rs;
1360         
1361         pCodeOp *pcop;
1362         
1363         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1364         /* offset is greater than
1365         size then zero */
1366
1367         assert (aop);
1368
1369
1370         /* XXX: still needed for BIT operands (AOP_CRY) */
1371         if (offset > (aop->size - 1) &&
1372                 aop->type != AOP_LIT &&
1373                 aop->type != AOP_PCODE)
1374         {
1375                 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1376                 return NULL;  //zero;
1377         }
1378         
1379         /* depending on type */
1380         switch (aop->type) {
1381                 
1382         case AOP_R0:
1383         case AOP_R1:
1384         case AOP_DPTR:
1385         case AOP_DPTR2:
1386         case AOP_ACC:
1387                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1388                 return NULL;
1389                 
1390         case AOP_IMMD:
1391                 DEBUGpic14_emitcode(";","%d",__LINE__);
1392                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1393                 
1394         case AOP_DIR:
1395                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1396 #if 0
1397                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1398                 pcop->type = PO_DIR;
1399                 
1400                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1401                 strcpy(pcop->name,aop->aopu.aop_dir);   
1402                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1403                 if(PCOR(pcop)->r == NULL) {
1404                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1405                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1406                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1407                 } else {
1408                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1409                 }
1410                 PCOR(pcop)->instance = offset;
1411                 
1412                 return pcop;
1413 #endif
1414                 
1415         case AOP_REG:
1416                 {
1417                         int rIdx;
1418                         assert (offset < aop->size);
1419                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1420                         
1421                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1422                         PCOR(pcop)->rIdx = rIdx;
1423                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1424                         PCOR(pcop)->r->wasUsed=1;
1425                         PCOR(pcop)->r->isFree=0;
1426                         
1427                         PCOR(pcop)->instance = offset;
1428                         pcop->type = PCOR(pcop)->r->pc_type;
1429                         //rs = aop->aopu.aop_reg[offset]->name;
1430                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1431                         return pcop;
1432                 }
1433                 
1434         case AOP_CRY:
1435                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1436                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1437                 //if(PCOR(pcop)->r == NULL)
1438                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1439                 return pcop;
1440                 
1441         case AOP_LIT:
1442                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1443                 
1444         case AOP_STR:
1445                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1446                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1447                 /*
1448                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1449                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1450                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1451                 pcop->type = PCOR(pcop)->r->pc_type;
1452                 pcop->name = PCOR(pcop)->r->name;
1453                 
1454                   return pcop;
1455                 */
1456                 
1457         case AOP_PCODE:
1458                 pcop = NULL;
1459                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1460                         __LINE__, 
1461                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1462                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1463                 switch (aop->aopu.pcop->type)
1464                 {
1465                 case PO_IMMEDIATE:
1466                   pcop = pCodeOpCopy (aop->aopu.pcop);
1467                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1468                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1469                   PCOI(pcop)->index += offset;
1470                   //PCOI(pcop)->offset = 0;
1471                   break;
1472                 case PO_DIR:
1473                   pcop = pCodeOpCopy (aop->aopu.pcop);
1474                   PCOR(pcop)->instance = offset;
1475                   break;
1476                 default:
1477                   assert ( !"unhandled pCode type" );
1478                   break;
1479                 } // switch
1480                 return pcop;
1481         }
1482         
1483         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1484                 "popGet got unsupported aop->type");
1485         exit(0);
1486 }
1487
1488 /*-----------------------------------------------------------------*/
1489 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1490 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1491 /*-----------------------------------------------------------------*/
1492 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1493 {
1494   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1495   {
1496     pCodeOp *pcop = aop->aopu.pcop;
1497     assert (offset <= GPTRSIZE);
1498
1499     /* special case: index >= 2 should return GPOINTER-style values */
1500     if (offset == 2)
1501     {
1502       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1503       return pcop;
1504     }
1505     
1506     pcop = pCodeOpCopy (pcop);
1507     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1508      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1509     PCOI(pcop)->offset += offset;
1510     PCOI(pcop)->index += index;
1511     //fprintf (stderr, "is PO_IMMEDIATE: %s+o%d+i%d (new o%d,i%d)\n", pcop->name,PCOI(pcop)->offset,PCOI(pcop)->index, offset, index);
1512     return pcop;
1513   } else {
1514     return popGet (aop, offset + index);
1515   }
1516 }
1517
1518 /*-----------------------------------------------------------------*/
1519 /* aopPut - puts a string for a aop                                                        */
1520 /*-----------------------------------------------------------------*/
1521 void aopPut (asmop *aop, char *s, int offset)
1522 {
1523         char *d = buffer ;
1524         symbol *lbl ;
1525         
1526         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1527         
1528         if (aop->size && offset > ( aop->size - 1)) {
1529                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1530                         "aopPut got offset > aop->size");
1531                 exit(0);
1532         }
1533         
1534         /* will assign value to value */
1535         /* depending on where it is ofcourse */
1536         switch (aop->type) {
1537         case AOP_DIR:
1538                 if (offset) {
1539                         sprintf(d,"(%s + %d)",
1540                                 aop->aopu.aop_dir,offset);
1541                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1542                         
1543                 } else
1544                         sprintf(d,"%s",aop->aopu.aop_dir);
1545                 
1546                 if (strcmp(d,s)) {
1547                         DEBUGpic14_emitcode(";","%d",__LINE__);
1548                         if(strcmp(s,"W"))
1549                                 pic14_emitcode("movf","%s,w",s);
1550                         pic14_emitcode("movwf","%s",d);
1551                         
1552                         if(strcmp(s,"W")) {
1553                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1554                                 if(offset >= aop->size) {
1555                                         emitpcode(POC_CLRF,popGet(aop,offset));
1556                                         break;
1557                                 } else {
1558                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1559                                 }
1560                         }
1561                         emitpcode(POC_MOVWF,popGet(aop,offset));
1562                 
1563                 }
1564                 break;
1565                 
1566         case AOP_REG:
1567                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1568                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1569                         /*
1570                         if (*s == '@'             ||
1571                         strcmp(s,"r0") == 0 ||
1572                         strcmp(s,"r1") == 0 ||
1573                         strcmp(s,"r2") == 0 ||
1574                         strcmp(s,"r3") == 0 ||
1575                         strcmp(s,"r4") == 0 ||
1576                         strcmp(s,"r5") == 0 ||
1577                         strcmp(s,"r6") == 0 || 
1578                         strcmp(s,"r7") == 0 )
1579                         pic14_emitcode("mov","%s,%s  ; %d",
1580                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1581                         else
1582                         */
1583                         
1584                         if(strcmp(s,"W")==0 )
1585                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1586                         
1587                         pic14_emitcode("movwf","%s",
1588                                 aop->aopu.aop_reg[offset]->name);
1589                         
1590                         if(strcmp(s,zero)==0) {
1591                                 emitpcode(POC_CLRF,popGet(aop,offset));
1592                                 
1593                         } else if(strcmp(s,"W")==0) {
1594                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1595                                 pcop->type = PO_GPR_REGISTER;
1596                                 
1597                                 PCOR(pcop)->rIdx = -1;
1598                                 PCOR(pcop)->r = NULL;
1599                                 
1600                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1601                                 pcop->name = Safe_strdup(s);
1602                                 emitpcode(POC_MOVFW,pcop);
1603                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1604                         } else if(strcmp(s,one)==0) {
1605                                 emitpcode(POC_CLRF,popGet(aop,offset));
1606                                 emitpcode(POC_INCF,popGet(aop,offset));
1607                         } else {
1608                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1609                         }
1610                 }
1611                 break;
1612                 
1613         case AOP_DPTR:
1614         case AOP_DPTR2:
1615                 
1616                 if (aop->type == AOP_DPTR2)
1617                 {
1618                         genSetDPTR(1);
1619                 }
1620                 
1621                 if (aop->code) {
1622                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1623                                 "aopPut writting to code space");
1624                         exit(0);
1625                 }
1626                 
1627                 while (offset > aop->coff) {
1628                         aop->coff++;
1629                         pic14_emitcode ("inc","dptr");
1630                 }
1631                 
1632                 while (offset < aop->coff) {
1633                         aop->coff-- ;
1634                         pic14_emitcode("lcall","__decdptr");
1635                 }
1636                 
1637                 aop->coff = offset;
1638                 
1639                 /* if not in accumulater */
1640                 MOVA(s);
1641                 
1642                 pic14_emitcode ("movx","@dptr,a");
1643                 
1644                 if (aop->type == AOP_DPTR2)
1645                 {
1646                         genSetDPTR(0);
1647                 }
1648                 break;
1649                 
1650         case AOP_R0:
1651         case AOP_R1:
1652                 while (offset > aop->coff) {
1653                         aop->coff++;
1654                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1655                 }
1656                 while (offset < aop->coff) {
1657                         aop->coff-- ;
1658                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1659                 }
1660                 aop->coff = offset;
1661                 
1662                 if (aop->paged) {
1663                         MOVA(s);                         
1664                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1665                         
1666                 } else
1667                         if (*s == '@') {
1668                                 MOVA(s);
1669                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1670                         } else
1671                                 if (strcmp(s,"r0") == 0 ||
1672                                         strcmp(s,"r1") == 0 ||
1673                                         strcmp(s,"r2") == 0 ||
1674                                         strcmp(s,"r3") == 0 ||
1675                                         strcmp(s,"r4") == 0 ||
1676                                         strcmp(s,"r5") == 0 ||
1677                                         strcmp(s,"r6") == 0 || 
1678                                         strcmp(s,"r7") == 0 ) {
1679                                         char buffer[10];
1680                                         sprintf(buffer,"a%s",s);
1681                                         pic14_emitcode("mov","@%s,%s",
1682                                                 aop->aopu.aop_ptr->name,buffer);
1683                                 } else
1684                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1685                                 
1686                                 break;
1687                                 
1688         case AOP_STK:
1689                 if (strcmp(s,"a") == 0)
1690                         pic14_emitcode("push","acc");
1691                 else
1692                         pic14_emitcode("push","%s",s);
1693                 
1694                 break;
1695                 
1696         case AOP_CRY:
1697                 /* if bit variable */
1698                 if (!aop->aopu.aop_dir) {
1699                         pic14_emitcode("clr","a");
1700                         pic14_emitcode("rlc","a");
1701                 } else {
1702                         if (s == zero) 
1703                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1704                         else
1705                                 if (s == one)
1706                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1707                                 else
1708                                         if (!strcmp(s,"c"))
1709                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1710                                         else {
1711                                                 lbl = newiTempLabel(NULL);
1712                                                 
1713                                                 if (strcmp(s,"a")) {
1714                                                         MOVA(s);
1715                                                 }
1716                                                 pic14_emitcode("clr","c");
1717                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1718                                                 pic14_emitcode("cpl","c");
1719                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1720                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1721                                         }
1722                 }
1723                 break;
1724                 
1725         case AOP_STR:
1726                 aop->coff = offset;
1727                 if (strcmp(aop->aopu.aop_str[offset],s))
1728                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1729                 break;
1730                 
1731         case AOP_ACC:
1732                 aop->coff = offset;
1733                 if (!offset && (strcmp(s,"acc") == 0))
1734                         break;
1735                 
1736                 if (strcmp(aop->aopu.aop_str[offset],s))
1737                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1738                 break;
1739                 
1740         default :
1741                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1742                         "aopPut got unsupported aop->type");
1743                 exit(0);
1744         }
1745         
1746 }
1747
1748 /*-----------------------------------------------------------------*/
1749 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1750 /*-----------------------------------------------------------------*/
1751 static void mov2w_op (operand *op, int offset)
1752 {
1753         assert (op);
1754         FENTRY;
1755
1756         /* for PO_IMMEDIATEs: use address or value? */
1757         if (op_isLitLike (op))
1758         {
1759                 /* access address of op */
1760                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1761                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1762                 {
1763                         if (offset == GPTRSIZE-1)
1764                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1765                         else
1766                                 emitpcode (POC_MOVLW, popGetLit (0));
1767                 }
1768                 else
1769                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1770         } else {
1771                 /* access value stored in op */
1772                 mov2w (AOP(op), offset);
1773         }
1774 }
1775
1776
1777 /*-----------------------------------------------------------------*/
1778 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1779 /*-----------------------------------------------------------------*/
1780 void mov2w (asmop *aop, int offset)
1781 {
1782         
1783         if(!aop)
1784                 return;
1785         
1786         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1787         
1788         if ( aop_isLitLike (aop) )
1789                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1790         else
1791                 emitpcode(POC_MOVFW,popGet(aop,offset));
1792         
1793 }
1794
1795 static void movwf (asmop *op, int offset)
1796 {
1797         emitpcode (POC_MOVWF, popGet(op, offset));
1798 }
1799
1800 static pCodeOp *get_argument_pcop (int idx)
1801 {
1802         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1803         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1804 }
1805
1806 static pCodeOp *get_return_val_pcop (int offset)
1807 {
1808         assert (offset > 0 && "the most significant byte is returned via WREG");
1809         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1810 }
1811
1812 static void pass_argument (operand *op, int offset, int idx)
1813 {
1814         if (op)
1815                 mov2w_op (op, offset);
1816         if (idx != 0)
1817                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1818 }
1819
1820 static void get_returnvalue (operand *op, int offset, int idx)
1821 {
1822         if (idx != 0)
1823                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1824         movwf(AOP(op), offset);
1825 }
1826
1827 static void call_libraryfunc (char *name)
1828 {
1829   /* library code might reside in different page... */
1830   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1831   /* call the library function */
1832   emitpcode (POC_CALL, popGetExternal (name));
1833   /* might return from different page... */
1834   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1835 }
1836 #if 0
1837 /*-----------------------------------------------------------------*/
1838 /* reAdjustPreg - points a register back to where it should        */
1839 /*-----------------------------------------------------------------*/
1840 static void reAdjustPreg (asmop *aop)
1841 {
1842         int size ;
1843         
1844         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1845         aop->coff = 0;
1846         if ((size = aop->size) <= 1)
1847                 return ;
1848         size-- ;
1849         switch (aop->type) {
1850         case AOP_R0 :
1851         case AOP_R1 :
1852                 while (size--)
1853                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1854                 break;                  
1855         case AOP_DPTR :
1856         case AOP_DPTR2:
1857                 if (aop->type == AOP_DPTR2)
1858                 {
1859                         genSetDPTR(1);
1860                 } 
1861                 while (size--)
1862                 {
1863                         pic14_emitcode("lcall","__decdptr");
1864                 }
1865                 
1866                 if (aop->type == AOP_DPTR2)
1867                 {
1868                         genSetDPTR(0);
1869                 }
1870                 break;
1871                 
1872         }
1873         
1874 }
1875 #endif
1876
1877
1878 #if 0
1879 /*-----------------------------------------------------------------*/
1880 /* opIsGptr: returns non-zero if the passed operand is             */
1881 /* a generic pointer type.                                         */
1882 /*-----------------------------------------------------------------*/ 
1883 static int opIsGptr(operand *op)
1884 {
1885         sym_link *type = operandType(op);
1886         
1887         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1888         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1889         {
1890                 return 1;
1891         }
1892         return 0;          
1893 }
1894 #endif
1895
1896 /*-----------------------------------------------------------------*/
1897 /* pic14_getDataSize - get the operand data size                   */
1898 /*-----------------------------------------------------------------*/
1899 int pic14_getDataSize(operand *op)
1900 {
1901         int size;
1902         
1903         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1904         
1905 #if 0
1906         size = getSize(OP_SYM_ETYPE(op));
1907         return size;
1908         //return AOP_SIZE(op);
1909         
1910         // tsd- in the pic port, the genptr size is 1, so this code here
1911         // fails. ( in the 8051 port, the size was 4).
1912 #else
1913         size = AOP_SIZE(op);
1914         if (IS_GENPTR(OP_SYM_TYPE(op)))
1915         {
1916                 sym_link *type = operandType(op);
1917                 if (IS_GENPTR(type))
1918                 {
1919                         /* generic pointer; arithmetic operations
1920                         * should ignore the high byte (pointer type).
1921                         */
1922                         size--;
1923                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1924                 }
1925         }
1926         return size;
1927 #endif
1928 }
1929
1930 /*-----------------------------------------------------------------*/
1931 /* pic14_outAcc - output Acc                                       */
1932 /*-----------------------------------------------------------------*/
1933 void pic14_outAcc(operand *result)
1934 {
1935         int size,offset;
1936         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1937         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1938         
1939         
1940         size = pic14_getDataSize(result);
1941         if(size){
1942                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1943                 size--;
1944                 offset = 1;
1945                 /* unsigned or positive */
1946                 while(size--)
1947                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1948         }
1949         
1950 }
1951
1952 /*-----------------------------------------------------------------*/
1953 /* pic14_outBitC - output a bit C                                  */
1954 /*-----------------------------------------------------------------*/
1955 void pic14_outBitC(operand *result)
1956 {
1957         
1958         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1959         /* if the result is bit */
1960         if (AOP_TYPE(result) == AOP_CRY) 
1961                 aopPut(AOP(result),"c",0);
1962         else {
1963                 pic14_emitcode("clr","a  ; %d", __LINE__);
1964                 pic14_emitcode("rlc","a");
1965                 pic14_outAcc(result);
1966         }
1967 }
1968
1969 /*-----------------------------------------------------------------*/
1970 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1971 /*-----------------------------------------------------------------*/
1972 void pic14_toBoolean(operand *oper)
1973 {
1974         int size = AOP_SIZE(oper);
1975         int offset = 0;
1976         
1977         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1978
1979         assert (size > 0);
1980
1981         if (size == 1) {
1982                 /* MOVFW does not load the flags... */
1983                 if (AOP_TYPE(oper) == AOP_ACC) {
1984                         emitpcode(POC_IORLW, popGetLit(0));
1985                         offset = 1;
1986                 } else {
1987                         emitpcode(POC_MOVLW, popGetLit(0));
1988                         offset = 0;
1989                 }
1990         } else {
1991                 if ( AOP_TYPE(oper) != AOP_ACC) {
1992                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1993                         offset = 1;
1994                 }
1995         }
1996         
1997         while (offset < size) {
1998                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1999         }
2000         /* Z is set iff (oper == 0) */
2001 }
2002
2003
2004 /*-----------------------------------------------------------------*/
2005 /* genNot - generate code for ! operation                          */
2006 /*-----------------------------------------------------------------*/
2007 static void genNot (iCode *ic)
2008 {
2009         //symbol *tlbl;
2010         int size;
2011
2012         FENTRY;
2013         
2014         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2015         /* assign asmOps to operand & result */
2016         aopOp (IC_LEFT(ic),ic,FALSE);
2017         aopOp (IC_RESULT(ic),ic,TRUE);
2018         
2019         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2020         /* if in bit space then a special case */
2021         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2022                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2023                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2024                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2025                 } else {
2026                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2027                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2028                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2029                 }
2030                 goto release;
2031         }
2032         
2033         size = AOP_SIZE(IC_LEFT(ic));
2034         mov2w (AOP(IC_LEFT(ic)),0);
2035         while (--size > 0)
2036         {
2037           if (op_isLitLike (IC_LEFT(ic)))
2038             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2039           else
2040             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2041         }
2042         emitpcode(POC_MOVLW, popGetLit (0));
2043         emitSKPNZ;
2044         emitpcode(POC_MOVLW, popGetLit (1));
2045         movwf(AOP(IC_RESULT(ic)), 0);
2046
2047         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2048         {
2049           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2050         }
2051         goto release;
2052         
2053 release:        
2054         /* release the aops */
2055         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2056         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2057 }
2058
2059
2060 /*-----------------------------------------------------------------*/
2061 /* genCpl - generate code for complement                                                   */
2062 /*-----------------------------------------------------------------*/
2063 static void genCpl (iCode *ic)
2064 {
2065         operand *left, *result;
2066         int size, offset=0;  
2067         
2068         FENTRY;
2069         
2070         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2071         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2072         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2073         
2074         /* if both are in bit space then 
2075         a special case */
2076         if (AOP_TYPE(result) == AOP_CRY &&
2077                 AOP_TYPE(left) == AOP_CRY ) { 
2078                 
2079                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2080                 pic14_emitcode("cpl","c"); 
2081                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2082                 goto release; 
2083         } 
2084         
2085         size = AOP_SIZE(result);
2086         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2087         while (size--) {
2088                 
2089                 if(AOP_TYPE(left) == AOP_ACC) 
2090                         emitpcode(POC_XORLW, popGetLit(0xff));
2091                 else
2092                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2093                 
2094                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2095                 offset++;
2096         }
2097         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2098         
2099         
2100 release:
2101         /* release the aops */
2102         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2103         freeAsmop(result,NULL,ic,TRUE);
2104 }
2105
2106 /*-----------------------------------------------------------------*/
2107 /* genUminusFloat - unary minus for floating points                        */
2108 /*-----------------------------------------------------------------*/
2109 static void genUminusFloat(operand *op,operand *result)
2110 {
2111         int size ,offset =0 ;
2112         char *l;
2113         
2114         FENTRY;
2115
2116         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2117         /* for this we just need to flip the 
2118         first it then copy the rest in place */
2119         size = AOP_SIZE(op) - 1;
2120         l = aopGet(AOP(op),3,FALSE,FALSE);
2121         
2122         MOVA(l);          
2123         
2124         pic14_emitcode("cpl","acc.7");
2125         aopPut(AOP(result),"a",3);      
2126         
2127         while(size--) {
2128                 aopPut(AOP(result),
2129                         aopGet(AOP(op),offset,FALSE,FALSE),
2130                         offset);
2131                 offset++;
2132         }                
2133 }
2134
2135 /*-----------------------------------------------------------------*/
2136 /* genUminus - unary minus code generation                                                 */
2137 /*-----------------------------------------------------------------*/
2138 static void genUminus (iCode *ic)
2139 {
2140         int size, i;
2141         sym_link *optype, *rtype;
2142         
2143         FENTRY;
2144         
2145         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2146         /* assign asmops */
2147         aopOp(IC_LEFT(ic),ic,FALSE);
2148         aopOp(IC_RESULT(ic),ic,TRUE);
2149         
2150         /* if both in bit space then special
2151         case */
2152         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2153                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2154                 
2155                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2156                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2157                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2158                 
2159                 goto release; 
2160         } 
2161         
2162         optype = operandType(IC_LEFT(ic));
2163         rtype = operandType(IC_RESULT(ic));
2164         
2165         /* if float then do float stuff */
2166         if (IS_FLOAT(optype)) {
2167                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2168                 goto release;
2169         }
2170         
2171         /* otherwise subtract from zero by taking the 2's complement */
2172         size = AOP_SIZE(IC_LEFT(ic));
2173         
2174         for(i=0; i<size; i++) {
2175                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2176                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2177                 else {
2178                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2179                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2180                 }
2181         }
2182         
2183         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2184         for(i=1; i<size; i++) {
2185                 emitSKPNZ;
2186                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2187         }
2188         
2189 release:
2190         /* release the aops */
2191         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2192         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2193 }
2194
2195 /*-----------------------------------------------------------------*/
2196 /* saveRegisters - will look for a call and save the registers     */
2197 /*-----------------------------------------------------------------*/
2198 static void saveRegisters(iCode *lic) 
2199 {
2200         int i;
2201         iCode *ic;
2202         bitVect *rsave;
2203         sym_link *dtype;
2204         
2205         FENTRY;
2206
2207         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2208         /* look for call */
2209         for (ic = lic ; ic ; ic = ic->next) 
2210                 if (ic->op == CALL || ic->op == PCALL)
2211                         break;
2212                 
2213                 if (!ic) {
2214                         fprintf(stderr,"found parameter push with no function call\n");
2215                         return ;
2216                 }
2217                 
2218                 /* if the registers have been saved already then
2219                 do nothing */
2220                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2221                         return ;
2222                 
2223                         /* find the registers in use at this time 
2224                 and push them away to safety */
2225                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2226                         ic->rUsed);
2227                 
2228                 ic->regsSaved = 1;
2229                 if (options.useXstack) {
2230                         if (bitVectBitValue(rsave,R0_IDX))
2231                                 pic14_emitcode("mov","b,r0");
2232                         pic14_emitcode("mov","r0,%s",spname);
2233                         for (i = 0 ; i < pic14_nRegs ; i++) {
2234                                 if (bitVectBitValue(rsave,i)) {
2235                                         if (i == R0_IDX)
2236                                                 pic14_emitcode("mov","a,b");
2237                                         else
2238                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2239                                         pic14_emitcode("movx","@r0,a");
2240                                         pic14_emitcode("inc","r0");
2241                                 }
2242                         }
2243                         pic14_emitcode("mov","%s,r0",spname);
2244                         if (bitVectBitValue(rsave,R0_IDX))
2245                                 pic14_emitcode("mov","r0,b");     
2246                 }// else
2247                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2248                 //        if (bitVectBitValue(rsave,i))
2249                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2250                 //}
2251                 
2252                 dtype = operandType(IC_LEFT(ic));
2253                 if (currFunc && dtype && 
2254                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2255                         IFFUNC_ISISR(currFunc->type) &&
2256                         !ic->bankSaved) 
2257                         
2258                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2259                 
2260 }
2261 /*-----------------------------------------------------------------*/
2262 /* unsaveRegisters - pop the pushed registers                                      */
2263 /*-----------------------------------------------------------------*/
2264 static void unsaveRegisters (iCode *ic)
2265 {
2266         int i;
2267         bitVect *rsave;
2268         
2269         FENTRY;
2270
2271         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2272         /* find the registers in use at this time 
2273         and push them away to safety */
2274         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2275                 ic->rUsed);
2276         
2277         if (options.useXstack) {
2278                 pic14_emitcode("mov","r0,%s",spname); 
2279                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2280                         if (bitVectBitValue(rsave,i)) {
2281                                 pic14_emitcode("dec","r0");
2282                                 pic14_emitcode("movx","a,@r0");
2283                                 if (i == R0_IDX)
2284                                         pic14_emitcode("mov","b,a");
2285                                 else
2286                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2287                         }       
2288                         
2289                 }
2290                 pic14_emitcode("mov","%s,r0",spname);
2291                 if (bitVectBitValue(rsave,R0_IDX))
2292                         pic14_emitcode("mov","r0,b");
2293         } //else
2294         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2295         //      if (bitVectBitValue(rsave,i))
2296         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2297         //}
2298         
2299 }  
2300
2301
2302 /*-----------------------------------------------------------------*/
2303 /* pushSide -                            */
2304 /*-----------------------------------------------------------------*/
2305 static void pushSide(operand * oper, int size)
2306 {
2307 #if 0
2308         int offset = 0;
2309         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2310         while (size--) {
2311                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2312                 if (AOP_TYPE(oper) != AOP_REG &&
2313                         AOP_TYPE(oper) != AOP_DIR &&
2314                         strcmp(l,"a") ) {
2315                         pic14_emitcode("mov","a,%s",l);
2316                         pic14_emitcode("push","acc");
2317                 } else
2318                         pic14_emitcode("push","%s",l);
2319         }
2320 #endif
2321 }
2322
2323 /*-----------------------------------------------------------------*/
2324 /* assignResultValue -                           */
2325 /*-----------------------------------------------------------------*/
2326 static void assignResultValue(operand * oper)
2327 {
2328         int size = AOP_SIZE(oper);
2329         int offset = 0;
2330         
2331         FENTRY;
2332
2333         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2334         
2335         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2336         
2337         /* assign MSB first (passed via WREG) */
2338         while (size--) {
2339                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2340                 GpsuedoStkPtr++;
2341         }
2342 }
2343
2344
2345 /*-----------------------------------------------------------------*/
2346 /* genIpush - genrate code for pushing this gets a little complex  */
2347 /*-----------------------------------------------------------------*/
2348 static void genIpush (iCode *ic)
2349 {
2350         FENTRY;
2351         
2352         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2353 #if 0
2354         int size, offset = 0 ;
2355         char *l;
2356         
2357         
2358         /* if this is not a parm push : ie. it is spill push 
2359         and spill push is always done on the local stack */
2360         if (!ic->parmPush) {
2361                 
2362                 /* and the item is spilt then do nothing */
2363                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2364                         return ;
2365                 
2366                 aopOp(IC_LEFT(ic),ic,FALSE);
2367                 size = AOP_SIZE(IC_LEFT(ic));
2368                 /* push it on the stack */
2369                 while(size--) {
2370                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2371                         if (*l == '#') {
2372                                 MOVA(l);
2373                                 l = "acc";
2374                         }
2375                         pic14_emitcode("push","%s",l);
2376                 }
2377                 return ;                
2378         }
2379         
2380         /* this is a paramter push: in this case we call
2381         the routine to find the call and save those
2382         registers that need to be saved */   
2383         saveRegisters(ic);
2384         
2385         /* then do the push */
2386         aopOp(IC_LEFT(ic),ic,FALSE);
2387         
2388         
2389         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2390         size = AOP_SIZE(IC_LEFT(ic));
2391         
2392         while (size--) {
2393                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2394                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2395                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2396                         strcmp(l,"a") ) {
2397                         pic14_emitcode("mov","a,%s",l);
2398                         pic14_emitcode("push","acc");
2399                 } else
2400                         pic14_emitcode("push","%s",l);
2401         }         
2402         
2403         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2404 #endif
2405 }
2406
2407 /*-----------------------------------------------------------------*/
2408 /* genIpop - recover the registers: can happen only for spilling   */
2409 /*-----------------------------------------------------------------*/
2410 static void genIpop (iCode *ic)
2411 {
2412         FENTRY;
2413
2414         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2415         assert (!"genIpop -- unimplemented");
2416 #if 0
2417         int size,offset ;
2418         
2419         
2420         /* if the temp was not pushed then */
2421         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2422                 return ;
2423         
2424         aopOp(IC_LEFT(ic),ic,FALSE);
2425         size = AOP_SIZE(IC_LEFT(ic));
2426         offset = (size-1);
2427         while (size--) 
2428                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2429                 FALSE,TRUE));
2430         
2431         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2432 #endif
2433 }
2434
2435 /*-----------------------------------------------------------------*/
2436 /* unsaverbank - restores the resgister bank from stack                    */
2437 /*-----------------------------------------------------------------*/
2438 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2439 {
2440         FENTRY;
2441
2442         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2443 #if 0
2444         int i;
2445         asmop *aop ;
2446         regs *r = NULL;
2447         
2448         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2449         if (popPsw) {
2450                 if (options.useXstack) {
2451                         aop = newAsmop(0);
2452                         r = getFreePtr(ic,&aop,FALSE);
2453                         
2454                         
2455                         pic14_emitcode("mov","%s,_spx",r->name);
2456                         pic14_emitcode("movx","a,@%s",r->name);
2457                         pic14_emitcode("mov","psw,a");
2458                         pic14_emitcode("dec","%s",r->name);
2459                         
2460                 }else
2461                         pic14_emitcode ("pop","psw");
2462         }
2463         
2464         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2465                 if (options.useXstack) {           
2466                         pic14_emitcode("movx","a,@%s",r->name);
2467                         //pic14_emitcode("mov","(%s+%d),a",
2468                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2469                         pic14_emitcode("dec","%s",r->name);
2470                         
2471                 } else 
2472                         pic14_emitcode("pop",""); //"(%s+%d)",
2473                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2474         }
2475         
2476         if (options.useXstack) {
2477                 
2478                 pic14_emitcode("mov","_spx,%s",r->name);
2479                 freeAsmop(NULL,aop,ic,TRUE);
2480                 
2481         }
2482 #endif 
2483 }
2484
2485 /*-----------------------------------------------------------------*/
2486 /* saverbank - saves an entire register bank on the stack                  */
2487 /*-----------------------------------------------------------------*/
2488 static void saverbank (int bank, iCode *ic, bool pushPsw)
2489 {
2490         FENTRY;
2491
2492         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2493 #if 0
2494         int i;
2495         asmop *aop ;
2496         regs *r = NULL;
2497         
2498         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2499         if (options.useXstack) {
2500                 
2501                 aop = newAsmop(0);
2502                 r = getFreePtr(ic,&aop,FALSE);  
2503                 pic14_emitcode("mov","%s,_spx",r->name);
2504                 
2505         }
2506         
2507         for (i = 0 ; i < pic14_nRegs ;i++) {
2508                 if (options.useXstack) {
2509                         pic14_emitcode("inc","%s",r->name);
2510                         //pic14_emitcode("mov","a,(%s+%d)",
2511                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2512                         pic14_emitcode("movx","@%s,a",r->name);                 
2513                 } else 
2514                         pic14_emitcode("push","");// "(%s+%d)",
2515                 //regspic14[i].base,8*bank+regspic14[i].offset);
2516         }
2517         
2518         if (pushPsw) {
2519                 if (options.useXstack) {
2520                         pic14_emitcode("mov","a,psw");
2521                         pic14_emitcode("movx","@%s,a",r->name); 
2522                         pic14_emitcode("inc","%s",r->name);
2523                         pic14_emitcode("mov","_spx,%s",r->name);                 
2524                         freeAsmop (NULL,aop,ic,TRUE);
2525                         
2526                 } else
2527                         pic14_emitcode("push","psw");
2528                 
2529                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2530         }
2531         ic->bankSaved = 1;
2532 #endif
2533 }
2534
2535 /*-----------------------------------------------------------------*/
2536 /* genCall - generates a call statement                                                    */
2537 /*-----------------------------------------------------------------*/
2538 static void genCall (iCode *ic)
2539 {
2540         sym_link *dtype;         
2541         symbol *sym;
2542         char *name;
2543         int isExtern;
2544         
2545         FENTRY;
2546
2547         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2548         
2549         /* if caller saves & we have not saved then */
2550         if (!ic->regsSaved)
2551                 saveRegisters(ic);
2552         
2553                 /* if we are calling a function that is not using
2554                 the same register bank then we need to save the
2555         destination registers on the stack */
2556         dtype = operandType(IC_LEFT(ic));
2557         if (currFunc && dtype && 
2558                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2559                 IFFUNC_ISISR(currFunc->type) &&
2560                 !ic->bankSaved) 
2561                 
2562                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2563         
2564         /* if send set is not empty the assign */
2565         if (_G.sendSet) {
2566                 iCode *sic;
2567                 /* For the Pic port, there is no data stack.
2568                 * So parameters passed to functions are stored
2569                 * in registers. (The pCode optimizer will get
2570                 * rid of most of these :).
2571                 */
2572                 int psuedoStkPtr=-1;
2573                 int firstTimeThruLoop = 1;
2574                 
2575                 _G.sendSet = reverseSet(_G.sendSet);
2576                 
2577                 /* First figure how many parameters are getting passed */
2578                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2579                 sic = setNextItem(_G.sendSet)) {
2580                         
2581                         aopOp(IC_LEFT(sic),sic,FALSE);
2582                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2583                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2584                 }
2585                 
2586                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2587                 sic = setNextItem(_G.sendSet)) {
2588                         int size, offset = 0;
2589                         
2590                         aopOp(IC_LEFT(sic),sic,FALSE);
2591                         size = AOP_SIZE(IC_LEFT(sic));
2592                         
2593                         while (size--) {
2594                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2595                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2596                                 
2597                                 if(!firstTimeThruLoop) {
2598                                         /* If this is not the first time we've been through the loop
2599                                         * then we need to save the parameter in a temporary
2600                                         * register. The last byte of the last parameter is
2601                                         * passed in W. */
2602                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2603                                         
2604                                 }
2605                                 firstTimeThruLoop=0;
2606                                 
2607                                 mov2w_op (IC_LEFT(sic),  offset);
2608                                 offset++;
2609                         }
2610                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2611                 }
2612                 _G.sendSet = NULL;
2613         }
2614         /* make the call */
2615         sym = OP_SYMBOL(IC_LEFT(ic));
2616         name = sym->rname[0] ? sym->rname : sym->name;
2617         isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2618         if (isExtern) {
2619                 /* Extern functions and ISRs maybe on a different page;
2620                  * must call pagesel */
2621                 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2622         }
2623         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2624         if (isExtern) {
2625                 /* May have returned from a different page;
2626                  * must use pagesel to restore PCLATH before next
2627                  * goto or call instruction */
2628                 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2629         }
2630         GpsuedoStkPtr=0;
2631         /* if we need assign a result value */
2632         if ((IS_ITEMP(IC_RESULT(ic)) && 
2633                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2634                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2635                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2636                 
2637                 _G.accInUse++;
2638                 aopOp(IC_RESULT(ic),ic,FALSE);
2639                 _G.accInUse--;
2640                 
2641                 assignResultValue(IC_RESULT(ic));
2642                 
2643                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2644                         AopType(AOP_TYPE(IC_RESULT(ic))));
2645                 
2646                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2647         }
2648         
2649         /* if register bank was saved then pop them */
2650         if (ic->bankSaved)
2651                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2652         
2653         /* if we hade saved some registers then unsave them */
2654         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2655                 unsaveRegisters (ic);
2656         
2657         
2658 }
2659
2660 /*-----------------------------------------------------------------*/
2661 /* genPcall - generates a call by pointer statement                        */
2662 /*-----------------------------------------------------------------*/
2663 static void genPcall (iCode *ic)
2664 {
2665         sym_link *dtype;
2666         symbol *albl = newiTempLabel(NULL);
2667         symbol *blbl = newiTempLabel(NULL);
2668         PIC_OPCODE poc;
2669         pCodeOp *pcop;
2670         operand *left;
2671         
2672         FENTRY;
2673
2674         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2675         /* if caller saves & we have not saved then */
2676         if (!ic->regsSaved)
2677                 saveRegisters(ic);
2678         
2679                 /* if we are calling a function that is not using
2680                 the same register bank then we need to save the
2681         destination registers on the stack */
2682         dtype = operandType(IC_LEFT(ic));
2683         if (currFunc && dtype && 
2684                 IFFUNC_ISISR(currFunc->type) &&
2685                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2686                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2687         
2688         left = IC_LEFT(ic);
2689         aopOp(left,ic,FALSE);
2690         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2691         
2692         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2693         
2694         pushSide(IC_LEFT(ic), FPTRSIZE);
2695         
2696         /* if send set is not empty, assign parameters */
2697         if (_G.sendSet) {
2698                 
2699                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2700                 /* no way to pass args - W always gets used to make the call */
2701         }
2702         /* first idea - factor out a common helper function and call it.
2703         But don't know how to get it generated only once in its own block
2704         
2705         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2706                 char *rname;
2707                 char *buffer;
2708                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2709                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2710                 buffer = Safe_calloc(1,strlen(rname)+16);
2711                 sprintf(buffer, "%s_goto_helper", rname);
2712                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2713                 free(buffer);
2714         }
2715         */
2716         emitpcode(POC_CALL,popGetLabel(albl->key));
2717         pcop = popGetLabel(blbl->key);
2718         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2719         emitpcode(POC_GOTO,pcop);
2720         emitpLabel(albl->key);
2721         
2722         emitpcode(poc,popGetAddr(AOP(left),1,0));
2723         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2724         emitpcode(poc,popGetAddr(AOP(left),0,0));
2725         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2726         
2727         emitpLabel(blbl->key);
2728         
2729         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2730         
2731         /* if we need to assign a result value */
2732         if ((IS_ITEMP(IC_RESULT(ic)) &&
2733                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2734                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2735                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2736                 
2737                 _G.accInUse++;
2738                 aopOp(IC_RESULT(ic),ic,FALSE);
2739                 _G.accInUse--;
2740
2741                 GpsuedoStkPtr = 0;
2742                 
2743                 assignResultValue(IC_RESULT(ic));
2744                 
2745                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2746         }
2747         
2748         /* if register bank was saved then unsave them */
2749         if (currFunc && dtype && 
2750                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2751                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2752         
2753                 /* if we hade saved some registers then
2754         unsave them */
2755         if (ic->regsSaved)
2756                 unsaveRegisters (ic);
2757         
2758 }
2759
2760 /*-----------------------------------------------------------------*/
2761 /* resultRemat - result  is rematerializable                                       */
2762 /*-----------------------------------------------------------------*/
2763 static int resultRemat (iCode *ic)
2764 {
2765         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2766         FENTRY;
2767
2768         if (SKIP_IC(ic) || ic->op == IFX)
2769                 return 0;
2770         
2771         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2772                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2773                 if (sym->remat && !POINTER_SET(ic)) 
2774                         return 1;
2775         }
2776         
2777         return 0;
2778 }
2779
2780 #if defined(__BORLANDC__) || defined(_MSC_VER)
2781 #define STRCASECMP stricmp
2782 #else
2783 #define STRCASECMP strcasecmp
2784 #endif
2785
2786 #if 0
2787 /*-----------------------------------------------------------------*/
2788 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2789 /*-----------------------------------------------------------------*/
2790 static bool inExcludeList(char *s)
2791 {
2792         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2793         int i =0;
2794         
2795         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2796         if (options.excludeRegs[i] &&
2797                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2798                 return FALSE ;
2799         
2800         for ( i = 0 ; options.excludeRegs[i]; i++) {
2801                 if (options.excludeRegs[i] &&
2802                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2803                         return TRUE;
2804         }
2805         return FALSE ;
2806 }
2807 #endif
2808
2809 /*-----------------------------------------------------------------*/
2810 /* genFunction - generated code for function entry                                 */
2811 /*-----------------------------------------------------------------*/
2812 static void genFunction (iCode *ic)
2813 {
2814         symbol *sym;
2815         sym_link *ftype;
2816         
2817         FENTRY;
2818
2819         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2820         
2821         labelOffset += (max_key+4);
2822         max_key=0;
2823         GpsuedoStkPtr=0;
2824         _G.nRegsSaved = 0;
2825         /* create the function header */
2826         pic14_emitcode(";","-----------------------------------------");
2827         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2828         pic14_emitcode(";","-----------------------------------------");
2829         
2830         /* prevent this symbol from being emitted as 'extern' */
2831         pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2832
2833         pic14_emitcode("","%s:",sym->rname);
2834         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2835         
2836         ftype = operandType(IC_LEFT(ic));
2837         
2838         /* if critical function then turn interrupts off */
2839         if (IFFUNC_ISCRITICAL(ftype))
2840                 pic14_emitcode("clr","ea");
2841         
2842                 /* here we need to generate the equates for the
2843         register bank if required */
2844 #if 0
2845         if (FUNC_REGBANK(ftype) != rbank) {
2846                 int i ;
2847                 
2848                 rbank = FUNC_REGBANK(ftype);
2849                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2850                         if (strcmp(regspic14[i].base,"0") == 0)
2851                                 pic14_emitcode("","%s = 0x%02x",
2852                                 regspic14[i].dname,
2853                                 8*rbank+regspic14[i].offset);
2854                         else
2855                                 pic14_emitcode ("","%s = %s + 0x%02x",
2856                                 regspic14[i].dname,
2857                                 regspic14[i].base,
2858                                 8*rbank+regspic14[i].offset);
2859                 }
2860         }
2861 #endif
2862         
2863         /* if this is an interrupt service routine */
2864         pic14_inISR = 0;
2865         if (IFFUNC_ISISR(sym->type)) {
2866                 pic14_inISR = 1;
2867         /*  already done in pic14createInterruptVect() - delete me
2868         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2869         emitpcodeNULLop(POC_NOP);
2870         emitpcodeNULLop(POC_NOP);
2871         emitpcodeNULLop(POC_NOP);
2872                 */
2873                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2874                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2875                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2876                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2877                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2878                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2879                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2880                 
2881                 pBlockConvert2ISR(pb);
2882                 pic14_hasInterrupt = 1;
2883 #if 0  
2884                 if (!inExcludeList("acc"))              
2885                         pic14_emitcode ("push","acc");  
2886                 if (!inExcludeList("b"))
2887                         pic14_emitcode ("push","b");
2888                 if (!inExcludeList("dpl"))
2889                         pic14_emitcode ("push","dpl");
2890                 if (!inExcludeList("dph"))
2891                         pic14_emitcode ("push","dph");
2892                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2893                 {
2894                         pic14_emitcode ("push", "dpx");
2895                         /* Make sure we're using standard DPTR */
2896                         pic14_emitcode ("push", "dps");
2897                         pic14_emitcode ("mov", "dps, #0x00");
2898                         if (options.stack10bit)
2899                         { 
2900                                 /* This ISR could conceivably use DPTR2. Better save it. */
2901                                 pic14_emitcode ("push", "dpl1");
2902                                 pic14_emitcode ("push", "dph1");
2903                                 pic14_emitcode ("push", "dpx1");
2904                         }
2905                 }
2906                 /* if this isr has no bank i.e. is going to
2907                 run with bank 0 , then we need to save more
2908                 registers :-) */
2909                 if (!FUNC_REGBANK(sym->type)) {
2910                         
2911                 /* if this function does not call any other
2912                 function then we can be economical and
2913                         save only those registers that are used */
2914                         if (! IFFUNC_HASFCALL(sym->type)) {
2915                                 int i;
2916                                 
2917                                 /* if any registers used */
2918                                 if (sym->regsUsed) {
2919                                         /* save the registers used */
2920                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2921                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2922                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2923                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2924                                         }
2925                                 }
2926                                 
2927                         } else {
2928                         /* this function has    a function call cannot
2929                         determines register usage so we will have the
2930                                 entire bank */
2931                                 saverbank(0,ic,FALSE);
2932                         }       
2933                 }
2934 #endif
2935         } else {
2936         /* if callee-save to be used for this function
2937                 then save the registers being used in this function */
2938                 if (IFFUNC_CALLEESAVES(sym->type)) {
2939                         int i;
2940                         
2941                         /* if any registers used */
2942                         if (sym->regsUsed) {
2943                                 /* save the registers used */
2944                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2945                                         if (bitVectBitValue(sym->regsUsed,i) ||
2946                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2947                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2948                                                 _G.nRegsSaved++;
2949                                         }
2950                                 }
2951                         }
2952                 }
2953         }
2954         
2955         /* set the register bank to the desired value */
2956         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2957                 pic14_emitcode("push","psw");
2958                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
2959         }
2960         
2961         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2962                 
2963                 if (options.useXstack) {
2964                         pic14_emitcode("mov","r0,%s",spname);
2965                         pic14_emitcode("mov","a,_bp");
2966                         pic14_emitcode("movx","@r0,a");
2967                         pic14_emitcode("inc","%s",spname);
2968                 }
2969                 else
2970                 {
2971                         /* set up the stack */
2972                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
2973                 }
2974                 pic14_emitcode ("mov","_bp,%s",spname);
2975         }
2976         
2977         /* adjust the stack for the function */
2978         if (sym->stack) {
2979                 
2980                 int i = sym->stack;
2981                 if (i > 256 ) 
2982                         werror(W_STACK_OVERFLOW,sym->name);
2983                 
2984                 if (i > 3 && sym->recvSize < 4) {                
2985                         
2986                         pic14_emitcode ("mov","a,sp");
2987                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2988                         pic14_emitcode ("mov","sp,a");
2989                         
2990                 }
2991                 else
2992                         while(i--)
2993                                 pic14_emitcode("inc","sp");
2994         }
2995         
2996         if (sym->xstack) {
2997                 
2998                 pic14_emitcode ("mov","a,_spx");
2999                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3000                 pic14_emitcode ("mov","_spx,a");
3001         }
3002         
3003 }
3004
3005 /*-----------------------------------------------------------------*/
3006 /* genEndFunction - generates epilogue for functions                       */
3007 /*-----------------------------------------------------------------*/
3008 static void genEndFunction (iCode *ic)
3009 {
3010         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3011         
3012         FENTRY;
3013
3014         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3015         
3016         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3017         {
3018                 pic14_emitcode ("mov","%s,_bp",spname);
3019         }
3020         
3021         /* if use external stack but some variables were
3022         added to the local stack then decrement the
3023         local stack */
3024         if (options.useXstack && sym->stack) {    
3025                 pic14_emitcode("mov","a,sp");
3026                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3027                 pic14_emitcode("mov","sp,a");
3028         }
3029         
3030         
3031         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3032                 if (options.useXstack) {
3033                         pic14_emitcode("mov","r0,%s",spname);
3034                         pic14_emitcode("movx","a,@r0");
3035                         pic14_emitcode("mov","_bp,a");
3036                         pic14_emitcode("dec","%s",spname);
3037                 }
3038                 else
3039                 {
3040                         pic14_emitcode ("pop","_bp");
3041                 }
3042         }
3043         
3044         /* restore the register bank    */        
3045         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3046                 pic14_emitcode ("pop","psw");
3047         
3048         if (IFFUNC_ISISR(sym->type)) {
3049                 
3050                 /* now we need to restore the registers */
3051                 /* if this isr has no bank i.e. is going to
3052                 run with bank 0 , then we need to save more
3053 registers :-) */
3054                 if (!FUNC_REGBANK(sym->type)) {
3055                         
3056                 /* if this function does not call any other
3057                 function then we can be economical and
3058                         save only those registers that are used */
3059                         if (! IFFUNC_HASFCALL(sym->type)) {
3060                                 int i;
3061                                 
3062                                 /* if any registers used */
3063                                 if (sym->regsUsed) {
3064                                         /* save the registers used */
3065                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3066                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3067                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3068                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3069                                         }
3070                                 }
3071                                 
3072                         } else {
3073                         /* this function has    a function call cannot
3074                         determines register usage so we will have the
3075                                 entire bank */
3076                                 unsaverbank(0,ic,FALSE);
3077                         }       
3078                 }
3079 #if 0
3080                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3081                 {
3082                         if (options.stack10bit)
3083                         {
3084                                 pic14_emitcode ("pop", "dpx1");
3085                                 pic14_emitcode ("pop", "dph1");
3086                                 pic14_emitcode ("pop", "dpl1");
3087                         } 
3088                         pic14_emitcode ("pop", "dps");
3089                         pic14_emitcode ("pop", "dpx");
3090                 }
3091                 if (!inExcludeList("dph"))
3092                         pic14_emitcode ("pop","dph");
3093                 if (!inExcludeList("dpl"))
3094                         pic14_emitcode ("pop","dpl");
3095                 if (!inExcludeList("b"))
3096                         pic14_emitcode ("pop","b");
3097                 if (!inExcludeList("acc"))
3098                         pic14_emitcode ("pop","acc");
3099                 
3100                 if (IFFUNC_ISCRITICAL(sym->type))
3101                         pic14_emitcode("setb","ea");
3102 #endif
3103                 
3104                 /* if debug then send end of function */
3105                 /*      if (options.debug && currFunc) { */
3106                 if (currFunc) {
3107                         debugFile->writeEndFunction (currFunc, ic, 1);
3108                 }
3109                 
3110                 pic14_emitcode ("reti","");
3111                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3112                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3113                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3114                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3115                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3116                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3117                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3118                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3119                 emitpcodeNULLop(POC_RETFIE);
3120         }
3121         else {
3122                 if (IFFUNC_ISCRITICAL(sym->type))
3123                         pic14_emitcode("setb","ea");
3124                 
3125                 if (IFFUNC_CALLEESAVES(sym->type)) {
3126                         int i;
3127                         
3128                         /* if any registers used */
3129                         if (sym->regsUsed) {
3130                                 /* save the registers used */
3131                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3132                                         if (bitVectBitValue(sym->regsUsed,i) ||
3133                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3134                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3135                                 }
3136                         }
3137                         
3138                 }
3139                 
3140                 /* if debug then send end of function */
3141                 if (currFunc) {
3142                         debugFile->writeEndFunction (currFunc, ic, 1);
3143                 }
3144                 
3145                 pic14_emitcode ("return","");
3146                 emitpcodeNULLop(POC_RETURN);
3147                 
3148                 /* Mark the end of a function */
3149                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3150         }
3151         
3152 }
3153
3154 /*-----------------------------------------------------------------*/
3155 /* genRet - generate code for return statement                                     */
3156 /*-----------------------------------------------------------------*/
3157 static void genRet (iCode *ic)
3158 {
3159         int size,offset = 0;
3160         
3161         FENTRY;
3162
3163         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3164         /* if we have no return value then
3165         just generate the "ret" */
3166         if (!IC_LEFT(ic)) 
3167                 goto jumpret;           
3168         
3169                 /* we have something to return then
3170         move the return value into place */
3171         aopOp(IC_LEFT(ic),ic,FALSE);
3172         size = AOP_SIZE(IC_LEFT(ic));
3173
3174         for (offset = 0; offset < size; offset++)
3175         {
3176                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3177         }
3178         
3179         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3180         
3181 jumpret:
3182         /* generate a jump to the return label
3183         if the next is not the return statement */
3184         if (!(ic->next && ic->next->op == LABEL &&
3185                 IC_LABEL(ic->next) == returnLabel)) {
3186                 
3187                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3188         }
3189         
3190 }
3191
3192 /*-----------------------------------------------------------------*/
3193 /* genLabel - generates a label                                                                    */
3194 /*-----------------------------------------------------------------*/
3195 static void genLabel (iCode *ic)
3196 {
3197         FENTRY;
3198
3199         /* special case never generate */
3200         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3201         if (IC_LABEL(ic) == entryLabel)
3202                 return ;
3203         
3204         emitpLabel(IC_LABEL(ic)->key);
3205         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3206 }
3207
3208 /*-----------------------------------------------------------------*/
3209 /* genGoto - generates a goto                                                                      */
3210 /*-----------------------------------------------------------------*/
3211 //tsd
3212 static void genGoto (iCode *ic)
3213 {
3214         FENTRY;
3215
3216         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3217         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3218 }
3219
3220
3221 /*-----------------------------------------------------------------*/
3222 /* genMultbits :- multiplication of bits                                                   */
3223 /*-----------------------------------------------------------------*/
3224 static void genMultbits (operand *left, 
3225                                                  operand *right, 
3226                                                  operand *result)
3227 {
3228         FENTRY;
3229         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3230         
3231         if(!pic14_sameRegs(AOP(result),AOP(right)))
3232                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3233         
3234         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3235         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3236         emitpcode(POC_BCF,  popGet(AOP(result),0));
3237         
3238 }
3239
3240
3241 /*-----------------------------------------------------------------*/
3242 /* genMultOneByte : 8 bit multiplication & division                        */
3243 /*-----------------------------------------------------------------*/
3244 static void genMultOneByte (operand *left,
3245                                                         operand *right,
3246                                                         operand *result)
3247 {
3248         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3249         
3250         // symbol *lbl ;
3251         int size,offset,i;
3252         
3253         
3254         FENTRY;
3255         
3256         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3257         DEBUGpic14_AopType(__LINE__,left,right,result);
3258         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3259         
3260         /* (if two literals, the value is computed before) */
3261         /* if one literal, literal on the right */
3262         if (AOP_TYPE(left) == AOP_LIT){
3263                 operand *t = right;
3264                 right = left;
3265                 left = t;
3266         }
3267
3268         assert (AOP_SIZE(left) == AOP_SIZE(right));
3269         
3270         size = min(AOP_SIZE(result),AOP_SIZE(left));
3271         offset = Gstack_base_addr - (2*size - 1);
3272
3273         /* pass right operand as argument */
3274         for (i=0; i < size; i++)
3275         {
3276                 mov2w (AOP(right), i);
3277                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3278         } // for
3279         
3280         /* pass left operand as argument */
3281         for (i=0; i < size; i++)
3282         {
3283                 mov2w (AOP(left), i);
3284                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3285         } // for
3286         assert (offset == Gstack_base_addr);
3287         
3288         /* call library routine */
3289         assert (size > 0 && size <= 4);
3290         call_libraryfunc (func[size]);
3291         
3292         /* assign result */
3293         movwf (AOP(result), size-1);
3294         for (i=0; i < size - 1; i++)
3295         {
3296                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3297                 movwf (AOP(result), size - 2 - i);
3298         } // for
3299
3300         /* now (zero-/sign) extend the result to its size */
3301         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3302 }
3303
3304 /*-----------------------------------------------------------------*/
3305 /* genMult - generates code for multiplication                                     */
3306 /*-----------------------------------------------------------------*/
3307 static void genMult (iCode *ic)
3308 {
3309         operand *left = IC_LEFT(ic);
3310         operand *right = IC_RIGHT(ic);
3311         operand *result= IC_RESULT(ic); 
3312         
3313         FENTRY;
3314
3315         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3316         /* assign the amsops */
3317         aopOp (left,ic,FALSE);
3318         aopOp (right,ic,FALSE);
3319         aopOp (result,ic,TRUE);
3320         
3321         DEBUGpic14_AopType(__LINE__,left,right,result);
3322         
3323         /* special cases first */
3324         /* both are bits */
3325         if (AOP_TYPE(left) == AOP_CRY &&
3326                 AOP_TYPE(right)== AOP_CRY) {
3327                 genMultbits(left,right,result);
3328                 goto release ;
3329         }
3330         
3331         /* if both are of size == 1 */
3332         if (AOP_SIZE(left) == 1 &&
3333                 AOP_SIZE(right) == 1 ) {
3334                 genMultOneByte(left,right,result);
3335                 goto release ;
3336         }
3337         
3338         /* should have been converted to function call */
3339         assert(0) ;
3340         
3341 release :
3342         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3343         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3344         freeAsmop(result,NULL,ic,TRUE); 
3345 }
3346
3347 /*-----------------------------------------------------------------*/
3348 /* genDivbits :- division of bits                                                                  */
3349 /*-----------------------------------------------------------------*/
3350 static void genDivbits (operand *left, 
3351                                                 operand *right, 
3352                                                 operand *result)
3353 {
3354         
3355         char *l;
3356         
3357         FENTRY;
3358
3359         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3360         /* the result must be bit */      
3361         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3362         l = aopGet(AOP(left),0,FALSE,FALSE);
3363         
3364         MOVA(l);          
3365         
3366         pic14_emitcode("div","ab");
3367         pic14_emitcode("rrc","a");
3368         aopPut(AOP(result),"c",0);
3369 }
3370
3371 /*-----------------------------------------------------------------*/
3372 /* genDivOneByte : 8 bit division                                                                  */
3373 /*-----------------------------------------------------------------*/
3374 static void genDivOneByte (operand *left,
3375                                                    operand *right,
3376                                                    operand *result)
3377 {
3378         int size;
3379         int sign;
3380         
3381         FENTRY;
3382         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3383         
3384         assert (AOP_SIZE(right) == 1);
3385         assert (AOP_SIZE(left) == 1);
3386
3387         size = min(AOP_SIZE(result),AOP_SIZE(left));
3388         sign = !(SPEC_USIGN(operandType(left))
3389                 && SPEC_USIGN(operandType(right)));
3390
3391         if (AOP_TYPE(right) == AOP_LIT)
3392         {
3393                 /* XXX: might add specialized code */
3394         }
3395
3396         if (!sign)
3397         {
3398                 /* unsigned division */
3399         #if 1
3400                 mov2w(AOP(right),0);
3401                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3402                 mov2w(AOP(left),0);
3403                 call_libraryfunc("__divuchar");
3404                 movwf(AOP(result),0);
3405         #else
3406                 pCodeOp *temp;
3407                 symbol *lbl;
3408
3409                 temp = popGetTempReg();
3410                 lbl = newiTempLabel(NULL);
3411                 
3412                 /* XXX: improve this naive approach:
3413                    [result] = [a] / [b]
3414                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3415
3416                    In PIC assembler:
3417                    movf  left,W
3418                    movwf temp           // temp <-- left
3419                    movf  right,W        // W <-- right
3420                    clrf  result
3421                    label1:
3422                    incf  result
3423                    subwf temp,F         // temp <-- temp - W
3424                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3425                    goto  label1
3426                    decf result          // we just subtract once too often
3427                  */
3428
3429                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3430                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3431                 
3432                 mov2w(AOP(left),0);
3433                 emitpcode(POC_MOVWF, temp);
3434                 mov2w(AOP(right),0);
3435                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3436
3437                 emitpLabel(lbl->key);
3438                 emitpcode(POC_INCF, popGet(AOP(result),0));
3439                 emitpcode(POC_SUBWF, temp);
3440                 emitSKPNC;
3441                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3442                 emitpcode(POC_DECF, popGet(AOP(result),0));
3443         #endif
3444         }
3445         else
3446         {
3447                 /* signed division */
3448                 mov2w(AOP(right),0);
3449                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3450                 mov2w(AOP(left),0);
3451                 call_libraryfunc("__divschar");
3452                 movwf(AOP(result),0);
3453         }
3454
3455         /* now performed the signed/unsigned division -- extend result */
3456         addSign(result, 1, sign);
3457 }
3458
3459 /*-----------------------------------------------------------------*/
3460 /* genDiv - generates code for division                            */
3461 /*-----------------------------------------------------------------*/
3462 static void genDiv (iCode *ic)
3463 {
3464         operand *left = IC_LEFT(ic);
3465         operand *right = IC_RIGHT(ic);
3466         operand *result= IC_RESULT(ic); 
3467         
3468         FENTRY;
3469         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3470         /* assign the amsops */
3471         aopOp (left,ic,FALSE);
3472         aopOp (right,ic,FALSE);
3473         aopOp (result,ic,TRUE);
3474         
3475         /* special cases first */
3476         /* both are bits */
3477         if (AOP_TYPE(left) == AOP_CRY &&
3478                 AOP_TYPE(right)== AOP_CRY) {
3479                 genDivbits(left,right,result);
3480                 goto release ;
3481         }
3482         
3483         /* if both are of size == 1 */
3484         if (AOP_SIZE(left) == 1 &&
3485                 AOP_SIZE(right) == 1 ) {
3486                 genDivOneByte(left,right,result);
3487                 goto release ;
3488         }
3489         
3490         /* should have been converted to function call */
3491         assert(0);
3492 release :
3493         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3494         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3495         freeAsmop(result,NULL,ic,TRUE); 
3496 }
3497
3498 /*-----------------------------------------------------------------*/
3499 /* genModOneByte : 8 bit modulus                                                                   */
3500 /*-----------------------------------------------------------------*/
3501 static void genModOneByte (operand *left,
3502                                                    operand *right,
3503                                                    operand *result)
3504 {
3505         int size;
3506         int sign;
3507         
3508         FENTRY;
3509         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3510         
3511         assert (AOP_SIZE(right) == 1);
3512         assert (AOP_SIZE(left) == 1);
3513
3514         size = min(AOP_SIZE(result),AOP_SIZE(left));
3515         sign = !(SPEC_USIGN(operandType(left))
3516                 && SPEC_USIGN(operandType(right)));
3517
3518         if (AOP_TYPE(right) == AOP_LIT)
3519         {
3520                 /* XXX: might add specialized code */
3521         }
3522
3523         if (!sign)
3524         {
3525                 /* unsigned division */
3526         #if 1
3527                 mov2w(AOP(right),0);
3528                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3529                 mov2w(AOP(left),0);
3530                 call_libraryfunc("__moduchar");
3531                 movwf(AOP(result),0);
3532         #else
3533                 pCodeOp *temp;
3534                 symbol *lbl;
3535
3536                 lbl = newiTempLabel(NULL);
3537                 
3538                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3539
3540                 /* XXX: improve this naive approach:
3541                    [result] = [a] % [b]
3542                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3543
3544                    In PIC assembler:
3545                    movf  left,W
3546                    movwf result         // result <-- left
3547                    movf  right,W        // W <-- right
3548                    label1:
3549                    subwf result,F       // result <-- result - W
3550                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3551                    goto  label1
3552                    addwf result, F      // we just subtract once too often
3553                  */
3554
3555                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3556                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3557                 
3558                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3559                 {
3560                         mov2w(AOP(left),0);
3561                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3562                 }
3563                 mov2w(AOP(right),0);
3564
3565                 emitpLabel(lbl->key);
3566                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3567                 emitSKPNC;
3568                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3569                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3570         #endif
3571         }
3572         else
3573         {
3574                 /* signed division */
3575                 mov2w(AOP(right),0);
3576                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3577                 mov2w(AOP(left),0);
3578                 call_libraryfunc("__modschar");
3579                 movwf(AOP(result),0);
3580         }
3581
3582         /* now we performed the signed/unsigned modulus -- extend result */
3583         addSign(result, 1, sign);
3584 }
3585
3586 /*-----------------------------------------------------------------*/
3587 /* genMod - generates code for division                                                    */
3588 /*-----------------------------------------------------------------*/
3589 static void genMod (iCode *ic)
3590 {
3591         operand *left = IC_LEFT(ic);
3592         operand *right = IC_RIGHT(ic);
3593         operand *result= IC_RESULT(ic);  
3594         
3595         FENTRY;
3596         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3597         /* assign the amsops */
3598         aopOp (left,ic,FALSE);
3599         aopOp (right,ic,FALSE);
3600         aopOp (result,ic,TRUE);
3601         
3602         /* if both are of size == 1 */
3603         if (AOP_SIZE(left) == 1 &&
3604                 AOP_SIZE(right) == 1 ) {
3605                 genModOneByte(left,right,result);
3606                 goto release ;
3607         }
3608         
3609         /* should have been converted to function call */
3610         assert(0);
3611         
3612 release :
3613         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3614         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3615         freeAsmop(result,NULL,ic,TRUE); 
3616 }
3617
3618 /*-----------------------------------------------------------------*/
3619 /* genIfxJump :- will create a jump depending on the ifx                   */
3620 /*-----------------------------------------------------------------*/
3621 /*
3622 note: May need to add parameter to indicate when a variable is in bit space.
3623 */
3624 static void genIfxJump (iCode *ic, char *jval)
3625 {
3626         
3627         FENTRY;
3628         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3629         /* if true label then we jump if condition
3630         supplied is true */
3631         if ( IC_TRUE(ic) ) {
3632                 
3633                 if(strcmp(jval,"a") == 0)
3634                         emitSKPZ;
3635                 else if (strcmp(jval,"c") == 0)
3636                         emitSKPC;
3637                 else {
3638                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3639                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3640                 }
3641                 
3642                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3643                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3644                 
3645         }
3646         else {
3647                 /* false label is present */
3648                 if(strcmp(jval,"a") == 0)
3649                         emitSKPNZ;
3650                 else if (strcmp(jval,"c") == 0)
3651                         emitSKPNC;
3652                 else {
3653                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3654                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3655                 }
3656                 
3657                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3658                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3659                 
3660         }
3661         
3662         
3663         /* mark the icode as generated */
3664         ic->generated = 1;
3665 }
3666
3667 #if 0
3668 /*-----------------------------------------------------------------*/
3669 /* genSkip                                                                                                                 */
3670 /*-----------------------------------------------------------------*/
3671 static void genSkip(iCode *ifx,int status_bit)
3672 {
3673         FENTRY;
3674         if(!ifx)
3675                 return;
3676         
3677         if ( IC_TRUE(ifx) ) {
3678                 switch(status_bit) {
3679                 case 'z':
3680                         emitSKPNZ;
3681                         break;
3682                         
3683                 case 'c':
3684                         emitSKPNC;
3685                         break;
3686                         
3687                 case 'd':
3688                         emitSKPDC;
3689                         break;
3690                         
3691                 }
3692                 
3693                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3694                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3695                 
3696         } else {
3697                 
3698                 switch(status_bit) {
3699                         
3700                 case 'z':
3701                         emitSKPZ;
3702                         break;
3703                         
3704                 case 'c':
3705                         emitSKPC;
3706                         break;
3707                         
3708                 case 'd':
3709                         emitSKPDC;
3710                         break;
3711                 }
3712                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3713                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3714                 
3715         }
3716         
3717 }
3718 #endif
3719
3720 /*-----------------------------------------------------------------*/
3721 /* genSkipc                                                                                                        */
3722 /*-----------------------------------------------------------------*/
3723 static void genSkipc(resolvedIfx *rifx)
3724 {
3725         FENTRY;
3726         if(!rifx)
3727                 return;
3728         
3729         if(rifx->condition)
3730                 emitSKPNC;
3731         else
3732                 emitSKPC;
3733         
3734         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3735         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3736         rifx->generated = 1;
3737 }
3738
3739 #if 0
3740 /*-----------------------------------------------------------------*/
3741 /* genSkipz2                                                                                                       */
3742 /*-----------------------------------------------------------------*/
3743 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3744 {
3745         FENTRY;
3746         if(!rifx)
3747                 return;
3748         
3749         if( (rifx->condition ^ invert_condition) & 1)
3750                 emitSKPZ;
3751         else
3752                 emitSKPNZ;
3753         
3754         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3755         rifx->generated = 1;
3756 }
3757 #endif
3758
3759 #if 0
3760 /*-----------------------------------------------------------------*/
3761 /* genSkipz                                                        */
3762 /*-----------------------------------------------------------------*/
3763 static void genSkipz(iCode *ifx, int condition)
3764 {
3765         FENTRY;
3766         assert (ifx != NULL);
3767         
3768         if(condition)
3769                 emitSKPNZ;
3770         else
3771                 emitSKPZ;
3772         
3773         if ( IC_TRUE(ifx) )
3774                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3775         else
3776                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3777         
3778         if ( IC_TRUE(ifx) )
3779                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3780         else
3781                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3782         
3783 }
3784 #endif
3785
3786 #if 0
3787 /*-----------------------------------------------------------------*/
3788 /* genSkipCond                                                     */
3789 /*-----------------------------------------------------------------*/
3790 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3791 {
3792         FENTRY;
3793         if(!rifx)
3794                 return;
3795         
3796         if(rifx->condition)
3797                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3798         else
3799                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3800         
3801         
3802         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3803         rifx->generated = 1;
3804 }
3805 #endif
3806
3807 #if 0
3808 /*-----------------------------------------------------------------*/
3809 /* genChkZeroes :- greater or less than comparison                 */
3810 /*     For each byte in a literal that is zero, inclusive or the   */
3811 /*     the corresponding byte in the operand with W                */
3812 /*     returns true if any of the bytes are zero                   */
3813 /*-----------------------------------------------------------------*/
3814 static int genChkZeroes(operand *op, int lit,  int size)
3815 {
3816         
3817         int i;
3818         int flag =1;
3819         
3820         while(size--) {
3821                 i = (lit >> (size*8)) & 0xff;
3822                 
3823                 if(i==0) {
3824                         if(flag) 
3825                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3826                         else
3827                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3828                         flag = 0;
3829                 }
3830         }
3831         
3832         return (flag==0);
3833 }
3834 #endif
3835
3836
3837 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3838 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3839 #define DEBUGpc           emitpComment
3840
3841 /*-----------------------------------------------------------------*/
3842 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3843 /*                  aop (if it's NOT a literal) or from lit (if    */
3844 /*                  aop is a literal)                              */
3845 /*-----------------------------------------------------------------*/
3846 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3847   if (aop->type == AOP_LIT) {
3848     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3849   } else {
3850     emitpcode (POC_MOVFW, popGet (aop, offset));
3851   }
3852 }
3853
3854 /* genCmp performs a left < right comparison, stores
3855  * the outcome in result (if != NULL) and generates
3856  * control flow code for the ifx (if != NULL).
3857  *
3858  * This version leaves in sequences like
3859  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3860  * which should be optmized by the peephole
3861  * optimizer - RN 2005-01-01 */
3862 static void genCmp (operand *left,operand *right,
3863                     operand *result, iCode *ifx, int sign)
3864 {
3865   resolvedIfx rIfx;
3866   int size;
3867   int offs;
3868   symbol *templbl;
3869   operand *dummy;
3870   unsigned long lit;
3871   unsigned long mask;
3872   int performedLt;
3873   int invert_result = 0;
3874
3875   FENTRY;
3876   
3877   assert (AOP_SIZE(left) == AOP_SIZE(right));
3878   assert (left && right);
3879
3880   size = AOP_SIZE(right) - 1;
3881   mask = (0x100UL << (size*8)) - 1;
3882   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3883   performedLt = 1;
3884   templbl = NULL;
3885   lit = 0;
3886   
3887   resolveIfx (&rIfx, ifx);
3888
3889   /**********************************************************************
3890    * handle bits - bit compares are promoted to int compares seemingly! *
3891    **********************************************************************/
3892 #if 0
3893   // THIS IS COMPLETELY UNTESTED!
3894   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3895     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3896     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3897     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3898
3899     emitSETC;
3900     // 1 < {0,1} is false --> clear C by skipping the next instruction
3901     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3902     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3903     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3904     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3905     emitCLRC; // only skipped for left=0 && right=1
3906
3907     goto correct_result_in_carry;
3908   } // if
3909 #endif
3910
3911   /*************************************************
3912    * make sure that left is register (or the like) *
3913    *************************************************/
3914   if (!isAOP_REGlike(left)) {
3915     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3916     assert (isAOP_LIT(left));
3917     assert (isAOP_REGlike(right));
3918     // swap left and right
3919     // left < right <==> right > left <==> (right >= left + 1)
3920     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3921
3922     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3923       // MAXVALUE < right? always false
3924       if (performedLt) emitCLRC; else emitSETC;
3925       goto correct_result_in_carry;
3926     } // if
3927
3928     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3929     // that's why we handled it above.
3930     lit++;
3931
3932     dummy = left;
3933     left = right;
3934     right = dummy;
3935
3936     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3937   } else if (isAOP_LIT(right)) {
3938     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3939   } // if
3940
3941   assert (isAOP_REGlike(left)); // left must be register or the like
3942   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3943
3944   /*************************************************
3945    * special cases go here                         *
3946    *************************************************/
3947
3948   if (isAOP_LIT(right)) {
3949     if (!sign) {
3950       // unsigned comparison to a literal
3951       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3952       if (lit == 0) {
3953         // unsigned left < 0? always false
3954         if (performedLt) emitCLRC; else emitSETC;
3955         goto correct_result_in_carry;
3956       }
3957     } else {
3958       // signed comparison to a literal
3959       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3960       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3961         // signed left < 0x80000000? always false
3962         if (performedLt) emitCLRC; else emitSETC;
3963         goto correct_result_in_carry;
3964       } else if (lit == 0) {
3965         // compare left < 0; set CARRY if SIGNBIT(left) is set
3966         if (performedLt) emitSETC; else emitCLRC;
3967         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3968         if (performedLt) emitCLRC; else emitSETC;
3969         goto correct_result_in_carry;
3970       }
3971     } // if (!sign)
3972   } // right is literal
3973
3974   /*************************************************
3975    * perform a general case comparison             *
3976    * make sure we get CARRY==1 <==> left >= right  *
3977    *************************************************/
3978   // compare most significant bytes
3979   //DEBUGpc ("comparing bytes at offset %d", size);
3980   if (!sign) {
3981     // unsigned comparison
3982     pic14_mov2w_regOrLit (AOP(right), lit, size);
3983     emitpcode (POC_SUBFW, popGet (AOP(left), size));
3984   } else {
3985     // signed comparison
3986     // (add 2^n to both operands then perform an unsigned comparison)
3987     if (isAOP_LIT(right)) {
3988       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3989       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3990
3991       if (litbyte == 0x80) {
3992         // left >= 0x80 -- always true, but more bytes to come
3993         mov2w (AOP(left), size);
3994         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3995         emitSETC;
3996       } else {
3997         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3998         mov2w (AOP(left), size);
3999         emitpcode (POC_ADDLW, popGetLit (0x80));
4000         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4001       } // if
4002     } else {
4003       pCodeOp *pctemp = popGetTempReg();
4004       mov2w (AOP(left), size);
4005       emitpcode (POC_ADDLW, popGetLit (0x80));
4006       emitpcode (POC_MOVWF, pctemp);
4007       mov2w (AOP(right), size);
4008       emitpcode (POC_ADDLW, popGetLit (0x80));
4009       emitpcode (POC_SUBFW, pctemp);
4010       popReleaseTempReg(pctemp);
4011     }
4012   } // if (!sign)
4013
4014   // compare remaining bytes (treat as unsigned case from above)
4015   templbl = newiTempLabel ( NULL );
4016   offs = size;
4017   while (offs--) {
4018     //DEBUGpc ("comparing bytes at offset %d", offs);
4019     emitSKPZ;
4020     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4021     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4022     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4023   } // while (offs)
4024   emitpLabel (templbl->key);
4025   goto result_in_carry;
4026
4027 result_in_carry:
4028   
4029   /****************************************************
4030    * now CARRY contains the result of the comparison: *
4031    * SUBWF sets CARRY iff                             *
4032    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4033    * (F=left, W=right)                                *
4034    ****************************************************/
4035
4036   if (performedLt) {
4037     invert_result = 1;
4038     // value will be used in the following genSkipc()
4039     rIfx.condition ^= 1;
4040   } // if
4041
4042 correct_result_in_carry:
4043
4044   // assign result to variable (if neccessary)
4045   if (result && AOP_TYPE(result) != AOP_CRY) {
4046     //DEBUGpc ("assign result");
4047     size = AOP_SIZE(result);
4048     while (size--) {
4049       emitpcode (POC_CLRF, popGet (AOP(result), size));
4050     } // while
4051     if (invert_result) {
4052       emitSKPC;
4053       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4054     } else {
4055       emitpcode (POC_RLF, popGet (AOP(result), 0));
4056     }
4057   } // if (result)
4058
4059   // perform conditional jump
4060   if (ifx) {
4061     //DEBUGpc ("generate control flow");
4062     genSkipc (&rIfx);
4063     ifx->generated = 1;
4064   } // if
4065 }
4066
4067
4068 #if 0
4069 /* OLD VERSION -- BUGGY, DO NOT USE */
4070
4071 /*-----------------------------------------------------------------*/
4072 /* genCmp :- greater or less than comparison                       */
4073 /*-----------------------------------------------------------------*/
4074 static void genCmp (operand *left,operand *right,
4075                                         operand *result, iCode *ifx, int sign)
4076 {
4077         int size; //, offset = 0 ;
4078         unsigned long lit = 0L,i = 0;
4079         resolvedIfx rFalseIfx;
4080         //  resolvedIfx rTrueIfx;
4081         symbol *truelbl;
4082
4083         FENTRY;
4084         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4085         /*
4086         if(ifx) {
4087         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4088         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4089         }
4090         */
4091         
4092         resolveIfx(&rFalseIfx,ifx);
4093         truelbl  = newiTempLabel(NULL);
4094         size = max(AOP_SIZE(left),AOP_SIZE(right));
4095         
4096         DEBUGpic14_AopType(__LINE__,left,right,result);
4097         
4098 #define _swapp
4099         
4100         /* if literal is on the right then swap with left */
4101         if ((AOP_TYPE(right) == AOP_LIT)) {
4102                 operand *tmp = right ;
4103                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4104                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4105 #ifdef _swapp
4106                 
4107                 lit = (lit - 1) & mask;
4108                 right = left;
4109                 left = tmp;
4110                 rFalseIfx.condition ^= 1;
4111 #endif
4112                 
4113         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4114                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4115         }
4116         
4117         
4118         //if(IC_TRUE(ifx) == NULL)
4119         /* if left & right are bit variables */
4120         if (AOP_TYPE(left) == AOP_CRY &&
4121                 AOP_TYPE(right) == AOP_CRY ) {
4122                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4123                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4124         } else {
4125         /* subtract right from left if at the
4126         end the carry flag is set then we know that
4127                 left is greater than right */
4128                 
4129                 symbol *lbl  = newiTempLabel(NULL);
4130                 
4131 #ifndef _swapp
4132                 if(AOP_TYPE(right) == AOP_LIT) {
4133                         
4134                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4135                         
4136                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4137                         
4138                         /* special cases */
4139                         
4140                         if(lit == 0) {
4141                                 
4142                                 if(sign != 0) 
4143                                         genSkipCond(&rFalseIfx,left,size-1,7);
4144                                 else 
4145                                         /* no need to compare to 0...*/
4146                                         /* NOTE: this is a de-generate compare that most certainly 
4147                                         *       creates some dead code. */
4148                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4149                                 
4150                                 if(ifx) ifx->generated = 1;
4151                                 return;
4152                                 
4153                         }
4154                         size--;
4155                         
4156                         if(size == 0) {
4157                                 //i = (lit >> (size*8)) & 0xff;
4158                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4159                                 
4160                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4161                                 
4162                                 i = ((0-lit) & 0xff);
4163                                 if(sign) {
4164                                         if( i == 0x81) { 
4165                                         /* lit is 0x7f, all signed chars are less than
4166                                                 * this except for 0x7f itself */
4167                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4168                                                 genSkipz2(&rFalseIfx,0);
4169                                         } else {
4170                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4171                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4172                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4173                                         }
4174                                         
4175                                 } else {
4176                                         if(lit == 1) {
4177                                                 genSkipz2(&rFalseIfx,1);
4178                                         } else {
4179                                                 emitpcode(POC_ADDLW, popGetLit(i));
4180                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4181                                         }
4182                                 }
4183                                 
4184                                 if(ifx) ifx->generated = 1;
4185                                 return;
4186                         }
4187                         
4188                         /* chars are out of the way. now do ints and longs */
4189                         
4190                         
4191                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4192                         
4193                         /* special cases */
4194                         
4195                         if(sign) {
4196                                 
4197                                 if(lit == 0) {
4198                                         genSkipCond(&rFalseIfx,left,size,7);
4199                                         if(ifx) ifx->generated = 1;
4200                                         return;
4201                                 }
4202                                 
4203                                 if(lit <0x100) {
4204                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4205                                         
4206                                         //rFalseIfx.condition ^= 1;
4207                                         //genSkipCond(&rFalseIfx,left,size,7);
4208                                         //rFalseIfx.condition ^= 1;
4209                                         
4210                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4211                                         if(rFalseIfx.condition)
4212                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4213                                         else
4214                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4215                                         
4216                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4217                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4218                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4219                                         
4220                                         while(size > 1)
4221                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4222                                         
4223                                         if(rFalseIfx.condition) {
4224                                                 emitSKPZ;
4225                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4226                                                 
4227                                         } else {
4228                                                 emitSKPNZ;
4229                                         }
4230                                         
4231                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4232                                         emitpLabel(truelbl->key);
4233                                         if(ifx) ifx->generated = 1;
4234                                         return;
4235                                         
4236                                 }
4237                                 
4238                                 if(size == 1) {
4239                                         
4240                                         if( (lit & 0xff) == 0) {
4241                                                 /* lower byte is zero */
4242                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4243                                                 i = ((lit >> 8) & 0xff) ^0x80;
4244                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4245                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4246                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4247                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4248                                                 
4249                                                 
4250                                                 if(ifx) ifx->generated = 1;
4251                                                 return;
4252                                                 
4253                                         }
4254                                 } else {
4255                                         /* Special cases for signed longs */
4256                                         if( (lit & 0xffffff) == 0) {
4257                                                 /* lower byte is zero */
4258                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4259                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4260                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4261                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4262                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4263                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4264                                                 
4265                                                 
4266                                                 if(ifx) ifx->generated = 1;
4267                                                 return;
4268                                                 
4269                                         }
4270                                         
4271                                 }
4272                                 
4273                                 
4274                                 if(lit & (0x80 << (size*8))) {
4275                                         /* lit is negative */
4276                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4277                                         
4278                                         //genSkipCond(&rFalseIfx,left,size,7);
4279                                         
4280                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4281                                         
4282                                         if(rFalseIfx.condition)
4283                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4284                                         else
4285                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4286                                         
4287                                         
4288                                 } else {
4289                                         /* lit is positive */
4290                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4291                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4292                                         if(rFalseIfx.condition)
4293                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4294                                         else
4295                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4296                                         
4297                                 }
4298                                 
4299                                 /* There are no more special cases, so perform a general compare */
4300                                 
4301                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4302                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4303                                 
4304                                 while(size--) {
4305                                         
4306                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4307                                         emitSKPNZ;
4308                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4309                                 }
4310                                 //rFalseIfx.condition ^= 1;
4311                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4312                                 
4313                                 emitpLabel(truelbl->key);
4314                                 
4315                                 if(ifx) ifx->generated = 1;
4316                                 return;
4317                                 
4318                                 
4319                         }
4320
4321
4322                         /* sign is out of the way. So now do an unsigned compare */
4323                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4324
4325
4326                         /* General case - compare to an unsigned literal on the right.*/
4327
4328                         i = (lit >> (size*8)) & 0xff;
4329                         emitpcode(POC_MOVLW, popGetLit(i));
4330                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4331                         while(size--) {
4332                                 i = (lit >> (size*8)) & 0xff;
4333                                 
4334                                 if(i) {
4335                                         emitpcode(POC_MOVLW, popGetLit(i));
4336                                         emitSKPNZ;
4337                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4338                                 } else {
4339                                 /* this byte of the lit is zero, 
4340                                         *if it's not the last then OR in the variable */
4341                                         if(size)
4342                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4343                                 }
4344                         }
4345
4346
4347                 emitpLabel(lbl->key);
4348                 //if(emitFinalCheck)
4349                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4350                 if(sign)
4351                         emitpLabel(truelbl->key);
4352
4353                 if(ifx) ifx->generated = 1;
4354                 return;
4355
4356
4357                 }
4358 #endif  // _swapp
4359
4360                 if(AOP_TYPE(left) == AOP_LIT) {
4361                         //symbol *lbl = newiTempLabel(NULL);
4362                         
4363                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4364                         
4365                         
4366                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4367                         
4368                         /* Special cases */
4369                         if((lit == 0) && (sign == 0)){
4370                                 
4371                                 size--;
4372                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4373                                 while(size) 
4374                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4375                                 
4376                                 genSkipz2(&rFalseIfx,0);
4377                                 if(ifx) ifx->generated = 1;
4378                                 return;
4379                         }
4380                         
4381                         if(size==1) {
4382                                 /* Special cases */
4383                                 lit &= 0xff;
4384                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4385                                         /* degenerate compare can never be true */
4386                                         if(rFalseIfx.condition == 0)
4387                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4388                                         
4389                                         if(ifx) ifx->generated = 1;
4390                                         return;
4391                                 }
4392                                 
4393                                 if(sign) {
4394                                         /* signed comparisons to a literal byte */
4395                                         
4396                                         int lp1 = (lit+1) & 0xff;
4397                                         
4398                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4399                                         switch (lp1) {
4400                                         case 0:
4401                                                 rFalseIfx.condition ^= 1;
4402                                                 genSkipCond(&rFalseIfx,right,0,7);
4403                                                 break;
4404                                         case 0x7f:
4405                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4406                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4407                                                 genSkipz2(&rFalseIfx,1);
4408                                                 break;
4409                                         default:
4410                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4411                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4412                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4413                                                 rFalseIfx.condition ^= 1;
4414                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4415                                                 break;
4416                                         }
4417                                         if(ifx) ifx->generated = 1;
4418                                 } else {
4419                                         /* unsigned comparisons to a literal byte */
4420                                         
4421                                         switch(lit & 0xff ) {
4422                                         case 0:
4423                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4424                                                 genSkipz2(&rFalseIfx,0);
4425                                                 if(ifx) ifx->generated = 1;
4426                                                 break;
4427                                         case 0x7f:
4428                                                 genSkipCond(&rFalseIfx,right,0,7);
4429                                                 if(ifx) ifx->generated = 1;
4430                                                 break;
4431                                                 
4432                                         default:
4433                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4434                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4435                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4436                                                 rFalseIfx.condition ^= 1;
4437                                                 if (AOP_TYPE(result) == AOP_CRY) {
4438                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4439                                                         if(ifx) ifx->generated = 1;
4440                                                 } else {
4441                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4442                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4443                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4444                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4445                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4446                                                 }       
4447                                                 break;
4448                                         }
4449                                 }
4450                                 
4451                                 //goto check_carry;
4452                                 return;
4453                                 
4454                         } else {
4455                                 
4456                                 /* Size is greater than 1 */
4457                                 
4458                                 if(sign) {
4459                                         int lp1 = lit+1;
4460                                         
4461                                         size--;
4462                                         
4463                                         if(lp1 == 0) {
4464                                                 /* this means lit = 0xffffffff, or -1 */
4465                                                 
4466                                                 
4467                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4468                                                 rFalseIfx.condition ^= 1;
4469                                                 genSkipCond(&rFalseIfx,right,size,7);
4470                                                 if(ifx) ifx->generated = 1;
4471                                                 return;
4472                                         }
4473                                         
4474                                         if(lit == 0) {
4475                                                 int s = size;
4476                                                 
4477                                                 if(rFalseIfx.condition) {
4478                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4479                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4480                                                 }
4481                                                 
4482                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4483                                                 while(size--)
4484                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4485                                                 
4486                                                 
4487                                                 emitSKPZ;
4488                                                 if(rFalseIfx.condition) {
4489                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4490                                                         emitpLabel(truelbl->key);
4491                                                 }else {
4492                                                         rFalseIfx.condition ^= 1;
4493                                                         genSkipCond(&rFalseIfx,right,s,7);
4494                                                 }
4495                                                 
4496                                                 if(ifx) ifx->generated = 1;
4497                                                 return;
4498                                         }
4499                                         
4500                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4501                                                 /* lower byte of signed word is zero */
4502                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4503                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4504                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4505                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4506                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4507                                                 rFalseIfx.condition ^= 1;
4508                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4509                                                 
4510                                                 
4511                                                 if(ifx) ifx->generated = 1;
4512                                                 return;
4513                                         }
4514                                         
4515                                         if(lit & (0x80 << (size*8))) {
4516                                                 /* Lit is less than zero */
4517                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4518                                                 //rFalseIfx.condition ^= 1;
4519                                                 //genSkipCond(&rFalseIfx,left,size,7);
4520                                                 //rFalseIfx.condition ^= 1;
4521                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4522                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4523                                                 
4524                                                 if(rFalseIfx.condition)
4525                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4526                                                 else
4527                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4528                                                 
4529                                                 
4530                                         } else {
4531                                                 /* Lit is greater than or equal to zero */
4532                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4533                                                 //rFalseIfx.condition ^= 1;
4534                                                 //genSkipCond(&rFalseIfx,right,size,7);
4535                                                 //rFalseIfx.condition ^= 1;
4536                                                 
4537                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4538                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4539                                                 
4540                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4541                                                 if(rFalseIfx.condition)
4542                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4543                                                 else
4544                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4545                                                 
4546                                         }
4547                                         
4548                                         
4549                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4550                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4551                                         
4552                                         while(size--) {
4553                                                 
4554                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4555                                                 emitSKPNZ;
4556                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4557                                         }
4558                                         rFalseIfx.condition ^= 1;
4559                                         //rFalseIfx.condition = 1;
4560                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4561                                         
4562                                         emitpLabel(truelbl->key);
4563                                         
4564                                         if(ifx) ifx->generated = 1;
4565                                         return;
4566                                         // end of if (sign)
4567                                 } else {
4568                                         
4569                                         /* compare word or long to an unsigned literal on the right.*/
4570                                         
4571                                         
4572                                         size--;
4573                                         if(lit < 0xff) {
4574                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4575                                                 switch (lit) {
4576                                                 case 0:
4577                                                         break; /* handled above */
4578                                                 /*
4579                                                 case 0xff:
4580                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4581                                                         while(size--)
4582                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4583                                                         genSkipz2(&rFalseIfx,0);
4584                                                         break;
4585                                                 */
4586                                                 default:
4587                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4588                                                         while(--size)
4589                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4590                                                         
4591                                                         emitSKPZ;
4592                                                         if(rFalseIfx.condition)
4593                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4594                                                         else
4595                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4596                                                         
4597                                                         
4598                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4599                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4600                                                         
4601                                                         rFalseIfx.condition ^= 1;
4602                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4603                                                 }
4604                                                 
4605                                                 emitpLabel(truelbl->key);
4606                                                 
4607                                                 if(ifx) ifx->generated = 1;
4608                                                 return;
4609                                         }
4610                                         
4611                                         
4612                                         lit++;
4613                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4614                                         i = (lit >> (size*8)) & 0xff;
4615                                         
4616                                         emitpcode(POC_MOVLW, popGetLit(i));
4617                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4618                                         
4619                                         while(size--) {
4620                                                 i = (lit >> (size*8)) & 0xff;
4621                                                 
4622                                                 if(i) {
4623                                                         emitpcode(POC_MOVLW, popGetLit(i));
4624                                                         emitSKPNZ;
4625                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4626                                                 } else {
4627                                                 /* this byte of the lit is zero, 
4628                                                         *if it's not the last then OR in the variable */
4629                                                         if(size)
4630                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4631                                                 }
4632                                         }
4633                                         
4634                                         
4635                                         emitpLabel(lbl->key);
4636                                         
4637                                         rFalseIfx.condition ^= 1;
4638                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4639                                 }
4640                                 
4641                                 if(sign)
4642                                         emitpLabel(truelbl->key);
4643                                 if(ifx) ifx->generated = 1;
4644                                 return;
4645                         }
4646                 }
4647                 /* Compare two variables */
4648                 
4649                 DEBUGpic14_emitcode(";sign","%d",sign);
4650                 
4651                 size--;
4652                 if(sign) {
4653                         /* Sigh. thus sucks... */
4654                         if(size) {
4655                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4656                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4657                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4658                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4659                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4660                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4661                         } else {
4662                                 /* Signed char comparison */
4663                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4664                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4665                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4666                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4667                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4668                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4669                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4670                                 
4671                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4672                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4673                                 
4674                                 if(ifx) ifx->generated = 1;
4675                                 return;
4676                         }
4677                         
4678                 } else {
4679                         
4680                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4681                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4682                 }
4683                 
4684                 
4685                 /* The rest of the bytes of a multi-byte compare */
4686                 while (size) {
4687                         
4688                         emitSKPZ;
4689                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4690                         size--;
4691                         
4692                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4693                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4694                         
4695                         
4696                 }
4697                 
4698                 emitpLabel(lbl->key);
4699                 
4700                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4701                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4702                         (AOP_TYPE(result) == AOP_REG)) {
4703                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4704                         emitpcode(POC_RLF, popGet(AOP(result),0));
4705                 } else {
4706                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4707                 }       
4708                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4709                 if(ifx) ifx->generated = 1;
4710                 
4711                 return;
4712                 
4713         }
4714         
4715         // check_carry:
4716         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4717                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4718                 pic14_outBitC(result);
4719         } else {
4720                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4721                 /* if the result is used in the next
4722                 ifx conditional branch then generate
4723                 code a little differently */
4724                 if (ifx )
4725                         genIfxJump (ifx,"c");
4726                 else
4727                         pic14_outBitC(result);
4728                 /* leave the result in acc */
4729         }
4730         
4731 }
4732 #endif
4733
4734 /*-----------------------------------------------------------------*/
4735 /* genCmpGt :- greater than comparison                             */
4736 /*-----------------------------------------------------------------*/
4737 static void genCmpGt (iCode *ic, iCode *ifx)
4738 {
4739         operand *left, *right, *result;
4740         sym_link *letype , *retype;
4741         int sign ;
4742         
4743         FENTRY;
4744         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4745         left = IC_LEFT(ic);
4746         right= IC_RIGHT(ic);
4747         result = IC_RESULT(ic);
4748         
4749         letype = getSpec(operandType(left));
4750         retype =getSpec(operandType(right));
4751         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4752         /* assign the amsops */
4753         aopOp (left,ic,FALSE);
4754         aopOp (right,ic,FALSE);
4755         aopOp (result,ic,TRUE);
4756         
4757         genCmp(right, left, result, ifx, sign);
4758         
4759         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4760         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4761         freeAsmop(result,NULL,ic,TRUE); 
4762 }
4763
4764 /*-----------------------------------------------------------------*/
4765 /* genCmpLt - less than comparisons                                */
4766 /*-----------------------------------------------------------------*/
4767 static void genCmpLt (iCode *ic, iCode *ifx)
4768 {
4769         operand *left, *right, *result;
4770         sym_link *letype , *retype;
4771         int sign ;
4772         
4773         FENTRY;
4774         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4775         left = IC_LEFT(ic);
4776         right= IC_RIGHT(ic);
4777         result = IC_RESULT(ic);
4778         
4779         letype = getSpec(operandType(left));
4780         retype =getSpec(operandType(right));
4781         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4782         
4783         /* assign the amsops */
4784         aopOp (left,ic,FALSE);
4785         aopOp (right,ic,FALSE);
4786         aopOp (result,ic,TRUE);
4787         
4788         genCmp(left, right, result, ifx, sign);
4789         
4790         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4791         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4792         freeAsmop(result,NULL,ic,TRUE); 
4793 }
4794
4795 #if 0
4796 /*-----------------------------------------------------------------*/
4797 /* genc16bit2lit - compare a 16 bit value to a literal             */
4798 /*-----------------------------------------------------------------*/
4799 static void genc16bit2lit(operand *op, int lit, int offset)
4800 {
4801         int i;
4802         
4803         FENTRY;
4804         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4805         if( (lit&0xff) == 0) 
4806                 i=1;
4807         else
4808                 i=0;
4809         
4810         switch( BYTEofLONG(lit,i)) { 
4811         case 0:
4812                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4813                 break;
4814         case 1:
4815                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4816                 break;
4817         case 0xff:
4818                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4819                 break;
4820         default:
4821                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4822                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4823         }
4824         
4825         i ^= 1;
4826         
4827         switch( BYTEofLONG(lit,i)) { 
4828         case 0:
4829                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4830                 break;
4831         case 1:
4832                 emitSKPNZ;
4833                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4834                 break;
4835         case 0xff:
4836                 emitSKPNZ;
4837                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4838                 break;
4839         default:
4840                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4841                 emitSKPNZ;
4842                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4843                 
4844         }
4845         
4846 }
4847 #endif
4848
4849 #if 0
4850 /*-----------------------------------------------------------------*/
4851 /* gencjneshort - compare and jump if not equal                    */
4852 /*-----------------------------------------------------------------*/
4853 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4854 {
4855         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4856         int offset = 0;
4857         //resolvedIfx rIfx;
4858         symbol *lbl;
4859         
4860         //unsigned long lit = 0L;
4861         FENTRY;
4862         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4863           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4864           return;
4865         }
4866         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4867         DEBUGpic14_AopType(__LINE__,left,right,result);
4868         
4869         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4870         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4871         if (AOP_SIZE(result)) {
4872           for (offset = 0; offset < AOP_SIZE(result); offset++)
4873             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4874         }
4875         
4876         assert (AOP_SIZE(left) == AOP_SIZE(right));
4877         //resolveIfx(&rIfx,ifx);
4878         lbl = newiTempLabel (NULL);
4879         while (size--)
4880         {
4881           mov2w (AOP(right),size);
4882           emitpcode (POC_XORFW, popGet (AOP(left), size));
4883           if (size)
4884           {
4885             emitSKPZ;
4886             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4887           }
4888         } // while
4889         emitpLabel (lbl->key);
4890         if (AOP_SIZE(result)) {
4891           emitSKPNZ;
4892           emitpcode (POC_INCF, popGet (AOP(result), 0));
4893         } else {
4894           assert (ifx);
4895           genSkipz (ifx, NULL != IC_TRUE(ifx));
4896           ifx->generated = 1;
4897         }
4898         return;
4899 #if 0   
4900         if(result)
4901         {
4902                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4903                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4904                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4905                 for (offset=0; offset < AOP_SIZE(result); offset++)
4906                 {
4907                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4908                 } // for offset
4909         }
4910         
4911         
4912         /* if the left side is a literal or 
4913         if the right is in a pointer register and left 
4914         is not */
4915         if ((AOP_TYPE(left) == AOP_LIT) || 
4916                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4917                 operand *t = right;
4918                 right = left;
4919                 left = t;
4920         }
4921         if(AOP_TYPE(right) == AOP_LIT)
4922                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4923         
4924         /* if the right side is a literal then anything goes */
4925         if (AOP_TYPE(right) == AOP_LIT &&
4926                 AOP_TYPE(left) != AOP_DIR ) {
4927                 switch(size) {
4928                 case 2:
4929                         genc16bit2lit(left, lit, 0);
4930                         emitSKPNZ;
4931                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4932                         break;
4933                 default:
4934                         offset = 0;
4935                         while (size--) {
4936                                 if(lit & 0xff) {
4937                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4938                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4939                                 } else {
4940                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4941                                 }
4942                                 
4943                                 emitSKPNZ;
4944                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4945                                 offset++;
4946                                 lit >>= 8;
4947                         }
4948                         break;
4949                 }
4950         }
4951         
4952         /* if the right side is in a register or in direct space or
4953         if the left is a pointer register & right is not */    
4954         else if (AOP_TYPE(right) == AOP_REG ||
4955                 AOP_TYPE(right) == AOP_DIR || 
4956                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4957                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4958                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4959                 int lbl_key = lbl->key;
4960                 
4961                 if(!result) {
4962                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4963                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4964                                 __FUNCTION__,__LINE__);
4965                         return;
4966                 }
4967                 
4968                 /*     switch(size) { */
4969                 /*     case 2: */
4970                 /*       genc16bit2lit(left, lit, 0); */
4971                 /*       emitSKPNZ; */
4972                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4973                 /*       break; */
4974                 /*     default: */
4975                 offset = 0;
4976                 while (size--) {
4977                         int emit_skip=1;
4978                         if((AOP_TYPE(left) == AOP_DIR) && 
4979                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4980                                 
4981                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4982                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4983                                 
4984                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4985                                 
4986                                 switch (lit & 0xff) {
4987                                 case 0:
4988                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4989                                         break;
4990                                 case 1:
4991                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4992                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4993                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4994                                         emit_skip=0;
4995                                         break;
4996                                 case 0xff:
4997                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4998                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4999                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5000                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5001                                         emit_skip=0;
5002                                         break;
5003                                 default:
5004                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5005                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5006                                 }
5007                                 lit >>= 8;
5008                                 
5009                         } else {
5010                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5011                         }
5012                         if(emit_skip) {
5013                                 if(AOP_TYPE(result) == AOP_CRY) {
5014                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5015                                         if(rIfx.condition)
5016                                                 emitSKPNZ;
5017                                         else
5018                                                 emitSKPZ;
5019                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5020                                 } else {
5021                                         /* fix me. probably need to check result size too */
5022                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5023                                         if(rIfx.condition)
5024                                                 emitSKPZ;
5025                                         else
5026                                                 emitSKPNZ;
5027                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5028                                 }
5029                                 if(ifx)
5030                                         ifx->generated=1;
5031                         }
5032                         emit_skip++;
5033                         offset++;
5034                 }
5035                 /*       break; */
5036                 /*     } */
5037         } else if(AOP_TYPE(right) == AOP_REG &&
5038                 AOP_TYPE(left) != AOP_DIR){
5039
5040                 offset = 0;
5041                 while(size--) {
5042                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5043                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5044                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5045                         if(rIfx.condition)
5046                                 emitSKPNZ;
5047                         else
5048                                 emitSKPZ;
5049                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5050                         offset++;
5051                 }
5052                 
5053         }else{
5054                 /* right is a pointer reg need both a & b */
5055                 offset = 0;
5056                 while(size--) {
5057                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5058                         if(strcmp(l,"b"))
5059                                 pic14_emitcode("mov","b,%s",l);
5060                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5061                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5062                         offset++;
5063                 }
5064         }
5065         
5066         emitpcode(POC_INCF,popGet(AOP(result),0));
5067         if(!rIfx.condition)
5068                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5069         
5070         emitpLabel(lbl->key);
5071         
5072         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5073         
5074         if(ifx)
5075                 ifx->generated = 1;
5076 #endif
5077 }
5078 #endif
5079
5080 #if 0
5081 /*-----------------------------------------------------------------*/
5082 /* gencjne - compare and jump if not equal                         */
5083 /*-----------------------------------------------------------------*/
5084 static void gencjne(operand *left, operand *right, iCode *ifx)
5085 {
5086         symbol *tlbl  = newiTempLabel(NULL);
5087         
5088         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5089         gencjneshort(left, right, lbl);
5090         
5091         pic14_emitcode("mov","a,%s",one);
5092         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5093         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5094         pic14_emitcode("clr","a");
5095         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5096         
5097         emitpLabel(lbl->key);
5098         emitpLabel(tlbl->key);
5099         
5100 }
5101 #endif
5102
5103 /*-----------------------------------------------------------------*/
5104 /* genCmpEq - generates code for equal to                          */
5105 /*-----------------------------------------------------------------*/
5106 static void genCmpEq (iCode *ic, iCode *ifx)
5107 {
5108   operand *left, *right, *result;
5109   int size;
5110   symbol *false_label;
5111
5112   FENTRY;
5113   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5114
5115   if(ifx)
5116     DEBUGpic14_emitcode ("; ifx is non-null","");
5117   else
5118     DEBUGpic14_emitcode ("; ifx is null","");
5119
5120   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5121   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5122   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5123
5124   DEBUGpic14_AopType(__LINE__,left,right,result);
5125
5126   /* if literal, move literal to right */ 
5127   if (op_isLitLike (IC_LEFT(ic))) {
5128     operand *tmp = right ;
5129     right = left;
5130     left = tmp;
5131   }
5132
5133   false_label = NULL;
5134   if (ifx && !IC_TRUE(ifx))
5135   {
5136     assert (IC_FALSE(ifx));
5137     false_label = IC_FALSE(ifx);
5138   }
5139
5140   size = min(AOP_SIZE(left),AOP_SIZE(right));
5141   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5142   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5143
5144   /* assume left != right */
5145   {
5146     int i;
5147     for (i=0; i < AOP_SIZE(result); i++)
5148     {
5149       emitpcode(POC_CLRF, popGet(AOP(result),i));
5150     }
5151   }
5152
5153   if (AOP_TYPE(right) == AOP_LIT)
5154   {
5155     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5156     int i;
5157     size = AOP_SIZE(left);
5158     assert(!op_isLitLike(left));
5159
5160     switch (lit)
5161     {
5162       case 0:
5163         mov2w(AOP(left), 0);
5164         for (i=1; i < size; i++)
5165           emitpcode(POC_IORFW,popGet(AOP(left),i));
5166         /* now Z is set iff `left == right' */
5167         emitSKPZ;
5168         if (!false_label) false_label = newiTempLabel(NULL);
5169         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5170         break;
5171
5172       default:
5173         for (i=0; i < size; i++)
5174         {
5175           mov2w(AOP(left),i);
5176           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5177           /* now Z is cleared if `left != right' */
5178           emitSKPZ;
5179           if (!false_label) false_label = newiTempLabel(NULL);
5180           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5181         } // for i
5182         break;
5183     } // switch (lit)
5184   }
5185   else
5186   {
5187     /* right is no literal */
5188     int i;
5189
5190     for (i=0; i < size; i++)
5191     {
5192       mov2w(AOP(right),i);
5193       emitpcode(POC_XORFW,popGet(AOP(left),i));
5194       /* now Z is cleared if `left != right' */
5195       emitSKPZ;
5196       if (!false_label) false_label = newiTempLabel(NULL);
5197       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5198     } // for i
5199   }
5200
5201   /* if we reach here, left == right */
5202
5203   if (AOP_SIZE(result) > 0)
5204   {
5205     emitpcode(POC_INCF, popGet(AOP(result),0));
5206   }
5207
5208   if (ifx && IC_TRUE(ifx))
5209   {
5210     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5211   }
5212
5213   if (false_label && (!ifx || IC_TRUE(ifx)))
5214     emitpLabel(false_label->key);
5215
5216   if (ifx) ifx->generated = 1;
5217
5218   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5219   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5220   freeAsmop(result,NULL,ic,TRUE);
5221 }
5222
5223 /*-----------------------------------------------------------------*/
5224 /* ifxForOp - returns the icode containing the ifx for operand     */
5225 /*-----------------------------------------------------------------*/
5226 static iCode *ifxForOp ( operand *op, iCode *ic )
5227 {
5228         FENTRY;
5229         /* if true symbol then needs to be assigned */
5230         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5231         if (IS_TRUE_SYMOP(op))
5232                 return NULL ;
5233         
5234         /* if this has register type condition and
5235         the next instruction is ifx with the same operand
5236         and live to of the operand is upto the ifx only then */
5237         if (ic->next &&
5238                 ic->next->op == IFX &&
5239                 IC_COND(ic->next)->key == op->key &&
5240                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5241                 return ic->next;
5242         
5243         if (ic->next &&
5244                 ic->next->op == IFX &&
5245                 IC_COND(ic->next)->key == op->key) {
5246                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5247                 return ic->next;
5248         }
5249         
5250         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5251         if (ic->next &&
5252                 ic->next->op == IFX)
5253                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5254         
5255         if (ic->next &&
5256                 ic->next->op == IFX &&
5257                 IC_COND(ic->next)->key == op->key) {
5258                 DEBUGpic14_emitcode ("; "," key is okay");
5259                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5260                         OP_SYMBOL(op)->liveTo,
5261                         ic->next->seq);
5262         }
5263         
5264         
5265         return NULL;
5266 }
5267 /*-----------------------------------------------------------------*/
5268 /* genAndOp - for && operation                                     */
5269 /*-----------------------------------------------------------------*/
5270 static void genAndOp (iCode *ic)
5271 {
5272         operand *left,*right, *result;
5273         /*     symbol *tlbl; */
5274         
5275         FENTRY;
5276         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5277         /* note here that && operations that are in an
5278         if statement are taken away by backPatchLabels
5279         only those used in arthmetic operations remain */
5280         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5281         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5282         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5283         
5284         DEBUGpic14_AopType(__LINE__,left,right,result);
5285         
5286         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5287         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5288         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5289         
5290         /* if both are bit variables */
5291         /*     if (AOP_TYPE(left) == AOP_CRY && */
5292         /*         AOP_TYPE(right) == AOP_CRY ) { */
5293         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5294         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5295         /*         pic14_outBitC(result); */
5296         /*     } else { */
5297         /*         tlbl = newiTempLabel(NULL); */
5298         /*         pic14_toBoolean(left);     */
5299         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5300         /*         pic14_toBoolean(right); */
5301         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5302         /*         pic14_outBitAcc(result); */
5303         /*     } */
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 /*-----------------------------------------------------------------*/
5312 /* genOrOp - for || operation                                      */
5313 /*-----------------------------------------------------------------*/
5314 /*
5315 tsd pic port -
5316 modified this code, but it doesn't appear to ever get called
5317 */
5318
5319 static void genOrOp (iCode *ic)
5320 {
5321         operand *left,*right, *result;
5322         symbol *tlbl;
5323         int i;
5324         
5325         /* note here that || operations that are in an
5326         if statement are taken away by backPatchLabels
5327         only those used in arthmetic operations remain */
5328         FENTRY;
5329         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5330         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5331         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5332         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5333         
5334         DEBUGpic14_AopType(__LINE__,left,right,result);
5335
5336         for (i=0; i < AOP_SIZE(result); i++)
5337         {
5338                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5339         } // for i
5340
5341         tlbl = newiTempLabel(NULL);
5342         pic14_toBoolean(left);
5343         emitSKPZ;
5344         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5345         pic14_toBoolean(right);
5346         emitpLabel(tlbl->key);
5347         /* here Z is clear IFF `left || right' */
5348         emitSKPZ;
5349         emitpcode(POC_INCF, popGet(AOP(result), 0));
5350         
5351         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5352         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5353         freeAsmop(result,NULL,ic,TRUE);            
5354 }
5355
5356 /*-----------------------------------------------------------------*/
5357 /* isLiteralBit - test if lit == 2^n                               */
5358 /*-----------------------------------------------------------------*/
5359 static int isLiteralBit(unsigned long lit)
5360 {
5361         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5362                 0x100L,0x200L,0x400L,0x800L,
5363                 0x1000L,0x2000L,0x4000L,0x8000L,
5364                 0x10000L,0x20000L,0x40000L,0x80000L,
5365                 0x100000L,0x200000L,0x400000L,0x800000L,
5366                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5367                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5368         int idx;
5369         
5370         FENTRY;
5371         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5372         for(idx = 0; idx < 32; idx++)
5373                 if(lit == pw[idx])
5374                         return idx+1;
5375                 return 0;
5376 }
5377
5378 /*-----------------------------------------------------------------*/
5379 /* continueIfTrue -                                                */
5380 /*-----------------------------------------------------------------*/
5381 static void continueIfTrue (iCode *ic)
5382 {
5383         FENTRY;
5384         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5385         if(IC_TRUE(ic))
5386         {
5387                 // Why +100?!?
5388                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5389                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5390         }
5391         ic->generated = 1;
5392 }
5393
5394 /*-----------------------------------------------------------------*/
5395 /* jmpIfTrue -                                                     */
5396 /*-----------------------------------------------------------------*/
5397 static void jumpIfTrue (iCode *ic)
5398 {
5399         FENTRY;
5400         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5401         if(!IC_TRUE(ic))
5402         {
5403                 // Why +100?!?
5404                 emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
5405                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5406         }
5407         ic->generated = 1;
5408 }
5409
5410 /*-----------------------------------------------------------------*/
5411 /* jmpTrueOrFalse -                                                */
5412 /*-----------------------------------------------------------------*/
5413 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5414 {
5415         FENTRY;
5416         // ugly but optimized by peephole
5417         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5418         if(IC_TRUE(ic)){
5419                 symbol *nlbl = newiTempLabel(NULL);
5420                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5421                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5422                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5423                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5424         }
5425         else{
5426                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5427                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5428         }
5429         ic->generated = 1;
5430 }
5431
5432 /*-----------------------------------------------------------------*/
5433 /* genAnd  - code for and                                          */
5434 /*-----------------------------------------------------------------*/
5435 static void genAnd (iCode *ic, iCode *ifx)
5436 {
5437         operand *left, *right, *result;
5438         int size, offset=0;  
5439         unsigned long lit = 0L;
5440         int bytelit = 0;
5441         resolvedIfx rIfx;
5442         
5443         FENTRY;
5444         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5445         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5446         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5447         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5448         
5449         resolveIfx(&rIfx,ifx);
5450         
5451         /* if left is a literal & right is not then exchange them */
5452         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5453                 AOP_NEEDSACC(left)) {
5454                 operand *tmp = right ;
5455                 right = left;
5456                 left = tmp;
5457         }
5458         
5459         /* if result = right then exchange them */
5460         if(pic14_sameRegs(AOP(result),AOP(right))){
5461                 operand *tmp = right ;
5462                 right = left;
5463                 left = tmp;
5464         }
5465         
5466         /* if right is bit then exchange them */
5467         if (AOP_TYPE(right) == AOP_CRY &&
5468                 AOP_TYPE(left) != AOP_CRY){
5469                 operand *tmp = right ;
5470                 right = left;
5471                 left = tmp;
5472         }
5473         if(AOP_TYPE(right) == AOP_LIT)
5474                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5475         
5476         size = AOP_SIZE(result);
5477         
5478         DEBUGpic14_AopType(__LINE__,left,right,result);
5479         
5480         // if(bit & yy)
5481         // result = bit & yy;
5482         if (AOP_TYPE(left) == AOP_CRY){
5483                 // c = bit & literal;
5484                 if(AOP_TYPE(right) == AOP_LIT){
5485                         if(lit & 1) {
5486                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5487                                         // no change
5488                                         goto release;
5489                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5490                         } else {
5491                                 // bit(result) = 0;
5492                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5493                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5494                                         goto release;
5495                                 }
5496                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5497                                         jumpIfTrue(ifx);
5498                                         goto release;
5499                                 }
5500                                 pic14_emitcode("clr","c");
5501                         }
5502                 } else {
5503                         if (AOP_TYPE(right) == AOP_CRY){
5504                                 // c = bit & bit;
5505                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5506                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5507                         } else {
5508                                 // c = bit & val;
5509                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5510                                 // c = lsb
5511                                 pic14_emitcode("rrc","a");
5512                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5513                         }
5514                 }
5515                 // bit = c
5516                 // val = c
5517                 if(size)
5518                         pic14_outBitC(result);
5519                 // if(bit & ...)
5520                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5521                         genIfxJump(ifx, "c");           
5522                 goto release ;
5523         }
5524         
5525         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5526         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5527         if((AOP_TYPE(right) == AOP_LIT) &&
5528                 (AOP_TYPE(result) == AOP_CRY) &&
5529                 (AOP_TYPE(left) != AOP_CRY)){
5530                 int posbit = isLiteralBit(lit);
5531                 /* left &  2^n */
5532                 if(posbit){
5533                         posbit--;
5534                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5535                         // bit = left & 2^n
5536                         if(size)
5537                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5538                         // if(left &  2^n)
5539                         else{
5540                                 if(ifx){
5541                                         int offset = 0;
5542                                         while (posbit > 7) {
5543                                                 posbit -= 8;
5544                                                 offset++;
5545                                         }
5546                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5547                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5548                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5549                                         
5550                                         ifx->generated = 1;
5551                                 }
5552                                 goto release;
5553                         }
5554                 } else {
5555                         symbol *tlbl = newiTempLabel(NULL);
5556                         int sizel = AOP_SIZE(left);
5557                         if(size)
5558                                 pic14_emitcode("setb","c");
5559                         while(sizel--){
5560                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5561                                         mov2w( AOP(left), offset);
5562                                         // byte ==  2^n ?
5563                                         if((posbit = isLiteralBit(bytelit)) != 0) {
5564                                                 emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
5565                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
5566                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5567                                         }
5568                                         else{
5569                                                 emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
5570                                                 if (rIfx.condition) emitSKPZ;
5571                                                 else emitSKPNZ;
5572                                                 
5573                                                 if(bytelit != 0x0FFL)
5574                                                 {
5575                                                         pic14_emitcode("anl","a,%s",
5576                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5577                                                 }
5578                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5579                                         }
5580
5581                                         emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
5582                                         ifx->generated = 1;
5583                                                 
5584                                 }
5585                                 offset++;
5586                         }
5587                         // bit = left & literal
5588                         if(size){
5589                                 pic14_emitcode("clr","c");
5590                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5591                         }
5592                         // if(left & literal)
5593                         else{
5594                                 if(ifx)
5595                                         jmpTrueOrFalse(ifx, tlbl);
5596                                 goto release ;
5597                         }
5598                 }
5599                 pic14_outBitC(result);
5600                 goto release ;
5601         }
5602         
5603         /* if left is same as result */
5604         if(pic14_sameRegs(AOP(result),AOP(left))){
5605                 int know_W = -1;
5606                 for(;size--; offset++,lit>>=8) {
5607                         if(AOP_TYPE(right) == AOP_LIT){
5608                                 switch(lit & 0xff) {
5609                                 case 0x00:
5610                                         /*  and'ing with 0 has clears the result */
5611                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5612                                         break;
5613                                 case 0xff:
5614                                         /* and'ing with 0xff is a nop when the result and left are the same */
5615                                         break;
5616                                         
5617                                 default:
5618                                         {
5619                                                 int p = my_powof2( (~lit) & 0xff );
5620                                                 if(p>=0) {
5621                                                         /* only one bit is set in the literal, so use a bcf instruction */
5622                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5623                                                         
5624                                                 } else {
5625                                                         if(know_W != (int)(lit&0xff))
5626                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5627                                                         know_W = lit &0xff;
5628                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5629                                                 }
5630                                         }    
5631                                 }
5632                         } else {
5633                                 if (AOP_TYPE(left) == AOP_ACC) {
5634                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5635                                 } else {        
5636                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5637                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5638                                         
5639                                 }
5640                         }
5641                 }
5642                 
5643         } else {
5644                 // left & result in different registers
5645                 if(AOP_TYPE(result) == AOP_CRY){
5646                         // result = bit
5647                         // if(size), result in bit
5648                         // if(!size && ifx), conditional oper: if(left & right)
5649                         symbol *tlbl = newiTempLabel(NULL);
5650                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5651                         if(size)
5652                                 pic14_emitcode("setb","c");
5653                         while(sizer--){
5654                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5655                                 pic14_emitcode("anl","a,%s",
5656                                         aopGet(AOP(left),offset,FALSE,FALSE));
5657                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5658                                 offset++;
5659                         }
5660                         if(size){
5661                                 CLRC;
5662                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5663                                 pic14_outBitC(result);
5664                         } else if(ifx)
5665                                 jmpTrueOrFalse(ifx, tlbl);
5666                 } else {
5667                         for(;(size--);offset++) {
5668                                 // normal case
5669                                 // result = left & right
5670                                 if(AOP_TYPE(right) == AOP_LIT){
5671                                         int t = (lit >> (offset*8)) & 0x0FFL;
5672                                         switch(t) { 
5673                                         case 0x00:
5674                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5675                                                 break;
5676                                         case 0xff:
5677                                                 if(AOP_TYPE(left) != AOP_ACC) {
5678                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5679                                                 }
5680                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5681                                                 break;
5682                                         default:
5683                                                 if(AOP_TYPE(left) == AOP_ACC) {
5684                                                         emitpcode(POC_ANDLW, popGetLit(t));
5685                                                 } else {
5686                                                         emitpcode(POC_MOVLW, popGetLit(t));
5687                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5688                                                 }
5689                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5690                                         }
5691                                         continue;
5692                                 }
5693                                 
5694                                 if (AOP_TYPE(left) == AOP_ACC) {
5695                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5696                                 } else {
5697                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5698                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5699                                 }
5700                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5701                         }
5702                 }
5703         }
5704         
5705 release :
5706         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5707         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5708         freeAsmop(result,NULL,ic,TRUE);     
5709 }
5710
5711 /*-----------------------------------------------------------------*/
5712 /* genOr  - code for or                                            */
5713 /*-----------------------------------------------------------------*/
5714 static void genOr (iCode *ic, iCode *ifx)
5715 {
5716         operand *left, *right, *result;
5717         int size, offset=0;
5718         unsigned long lit = 0L;
5719         
5720         FENTRY;
5721         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5722         
5723         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5724         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5725         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5726         
5727         DEBUGpic14_AopType(__LINE__,left,right,result);
5728         
5729         /* if left is a literal & right is not then exchange them */
5730         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5731                 AOP_NEEDSACC(left)) {
5732                 operand *tmp = right ;
5733                 right = left;
5734                 left = tmp;
5735         }
5736         
5737         /* if result = right then exchange them */
5738         if(pic14_sameRegs(AOP(result),AOP(right))){
5739                 operand *tmp = right ;
5740                 right = left;
5741                 left = tmp;
5742         }
5743         
5744         /* if right is bit then exchange them */
5745         if (AOP_TYPE(right) == AOP_CRY &&
5746                 AOP_TYPE(left) != AOP_CRY){
5747                 operand *tmp = right ;
5748                 right = left;
5749                 left = tmp;
5750         }
5751         
5752         DEBUGpic14_AopType(__LINE__,left,right,result);
5753         
5754         if(AOP_TYPE(right) == AOP_LIT)
5755                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5756         
5757         size = AOP_SIZE(result);
5758         
5759         // if(bit | yy)
5760         // xx = bit | yy;
5761         if (AOP_TYPE(left) == AOP_CRY){
5762                 if(AOP_TYPE(right) == AOP_LIT){
5763                         // c = bit & literal;
5764                         if(lit){
5765                                 // lit != 0 => result = 1
5766                                 if(AOP_TYPE(result) == AOP_CRY){
5767                                         if(size)
5768                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5769                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5770                                         //   AOP(result)->aopu.aop_dir,
5771                                         //   AOP(result)->aopu.aop_dir);
5772                                         else if(ifx)
5773                                                 continueIfTrue(ifx);
5774                                         goto release;
5775                                 }
5776                         } else {
5777                                 // lit == 0 => result = left
5778                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5779                                         goto release;
5780                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5781                         }
5782                 } else {
5783                         if (AOP_TYPE(right) == AOP_CRY){
5784                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5785                                         // c = bit | bit;
5786                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5787                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5788                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5789                                         
5790                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5791                                                 AOP(result)->aopu.aop_dir,
5792                                                 AOP(result)->aopu.aop_dir);
5793                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5794                                                 AOP(right)->aopu.aop_dir,
5795                                                 AOP(right)->aopu.aop_dir);
5796                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5797                                                 AOP(result)->aopu.aop_dir,
5798                                                 AOP(result)->aopu.aop_dir);
5799                                 } else {
5800                                         if( AOP_TYPE(result) == AOP_ACC) {
5801                                                 emitpcode(POC_MOVLW, popGetLit(0));
5802                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5803                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5804                                                 emitpcode(POC_MOVLW, popGetLit(1));
5805                                                 
5806                                         } else {
5807                                                 
5808                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5809                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5810                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5811                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5812                                                 
5813                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5814                                                         AOP(result)->aopu.aop_dir,
5815                                                         AOP(result)->aopu.aop_dir);
5816                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5817                                                         AOP(right)->aopu.aop_dir,
5818                                                         AOP(right)->aopu.aop_dir);
5819                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5820                                                         AOP(left)->aopu.aop_dir,
5821                                                         AOP(left)->aopu.aop_dir);
5822                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5823                                                         AOP(result)->aopu.aop_dir,
5824                                                         AOP(result)->aopu.aop_dir);
5825                                         }
5826                                 }
5827                         } else {
5828                                 // c = bit | val;
5829                                 symbol *tlbl = newiTempLabel(NULL);
5830                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5831                                 
5832                                 
5833                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5834                                 if( AOP_TYPE(right) == AOP_ACC) {
5835                                         emitpcode(POC_IORLW, popGetLit(0));
5836                                         emitSKPNZ;
5837                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5838                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5839                                 }
5840                                 
5841                                 
5842                                 
5843                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5844                                         pic14_emitcode(";XXX setb","c");
5845                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5846                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5847                                 pic14_toBoolean(right);
5848                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5849                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5850                                         jmpTrueOrFalse(ifx, tlbl);
5851                                         goto release;
5852                                 } else {
5853                                         CLRC;
5854                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5855                                 }
5856                         }
5857                 }
5858                 // bit = c
5859                 // val = c
5860                 if(size)
5861                         pic14_outBitC(result);
5862                 // if(bit | ...)
5863                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5864                         genIfxJump(ifx, "c");           
5865                 goto release ;
5866         }
5867
5868         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5869         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5870         if((AOP_TYPE(right) == AOP_LIT) &&
5871           (AOP_TYPE(result) == AOP_CRY) &&
5872           (AOP_TYPE(left) != AOP_CRY)){
5873                 if(lit){
5874                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5875                         // result = 1
5876                         if(size)
5877                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5878                         else 
5879                                 continueIfTrue(ifx);
5880                         goto release;
5881                 } else {
5882                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5883                         // lit = 0, result = boolean(left)
5884                         if(size)
5885                                 pic14_emitcode(";XXX setb","c");
5886                         pic14_toBoolean(right);
5887                         if(size){
5888                                 symbol *tlbl = newiTempLabel(NULL);
5889                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5890                                 CLRC;
5891                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5892                         } else {
5893                                 genIfxJump (ifx,"a");
5894                                 goto release;
5895                         }
5896                 }
5897                 pic14_outBitC(result);
5898                 goto release ;
5899         }
5900
5901         /* if left is same as result */
5902         if(pic14_sameRegs(AOP(result),AOP(left))){
5903                 int know_W = -1;
5904                 for(;size--; offset++,lit>>=8) {
5905                         if(AOP_TYPE(right) == AOP_LIT){
5906                                 if((lit & 0xff) == 0)
5907                                         /*  or'ing with 0 has no effect */
5908                                         continue;
5909                                 else {
5910                                         int p = my_powof2(lit & 0xff);
5911                                         if(p>=0) {
5912                                                 /* only one bit is set in the literal, so use a bsf instruction */
5913                                                 emitpcode(POC_BSF,
5914                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5915                                         } else {
5916                                                 if(know_W != (int)(lit & 0xff))
5917                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5918                                                 know_W = lit & 0xff;
5919                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5920                                         }
5921                                         
5922                                 }
5923                         } else {
5924                                 if (AOP_TYPE(left) == AOP_ACC) {
5925                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5926                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5927                                 } else {        
5928                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5929                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5930                                         
5931                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5932                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5933                                         
5934                                 }
5935                         }
5936                 }
5937         } else {
5938                 // left & result in different registers
5939                 if(AOP_TYPE(result) == AOP_CRY){
5940                         // result = bit
5941                         // if(size), result in bit
5942                         // if(!size && ifx), conditional oper: if(left | right)
5943                         symbol *tlbl = newiTempLabel(NULL);
5944                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5945                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5946                         
5947                         
5948                         if(size)
5949                                 pic14_emitcode(";XXX setb","c");
5950                         while(sizer--){
5951                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5952                                 pic14_emitcode(";XXX orl","a,%s",
5953                                         aopGet(AOP(left),offset,FALSE,FALSE));
5954                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5955                                 offset++;
5956                         }
5957                         if(size){
5958                                 CLRC;
5959                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5960                                 pic14_outBitC(result);
5961                         } else if(ifx)
5962                                 jmpTrueOrFalse(ifx, tlbl);
5963                 } else for(;(size--);offset++){
5964                         // normal case
5965                         // result = left | right
5966                         if(AOP_TYPE(right) == AOP_LIT){
5967                                 int t = (lit >> (offset*8)) & 0x0FFL;
5968                                 switch(t) { 
5969                                 case 0x00:
5970                                         if (AOP_TYPE(left) != AOP_ACC) {
5971                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5972                                         }
5973                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5974                                         
5975                                         break;
5976                                 default:
5977                                         if (AOP_TYPE(left) == AOP_ACC) {
5978                                                 emitpcode(POC_IORLW,  popGetLit(t));
5979                                         } else {
5980                                                 emitpcode(POC_MOVLW,  popGetLit(t));
5981                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5982                                         }
5983                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
5984                                 }
5985                                 continue;
5986                         }
5987                         
5988                         // faster than result <- left, anl result,right
5989                         // and better if result is SFR
5990                         if (AOP_TYPE(left) == AOP_ACC) {
5991                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5992                         } else {
5993                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5994                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5995                         }
5996                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5997                 }
5998         }
5999
6000 release :
6001         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6002         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6003         freeAsmop(result,NULL,ic,TRUE);     
6004 }
6005
6006 /*-----------------------------------------------------------------*/
6007 /* genXor - code for xclusive or                                   */
6008 /*-----------------------------------------------------------------*/
6009 static void genXor (iCode *ic, iCode *ifx)
6010 {
6011         operand *left, *right, *result;
6012         int size, offset=0;
6013         unsigned long lit = 0L;
6014         
6015         FENTRY;
6016         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6017         
6018         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6019         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6020         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6021         
6022         /* if left is a literal & right is not ||
6023         if left needs acc & right does not */
6024         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6025                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6026                 operand *tmp = right ;
6027                 right = left;
6028                 left = tmp;
6029         }
6030         
6031         /* if result = right then exchange them */
6032         if(pic14_sameRegs(AOP(result),AOP(right))){
6033                 operand *tmp = right ;
6034                 right = left;
6035                 left = tmp;
6036         }
6037         
6038         /* if right is bit then exchange them */
6039         if (AOP_TYPE(right) == AOP_CRY &&
6040                 AOP_TYPE(left) != AOP_CRY){
6041                 operand *tmp = right ;
6042                 right = left;
6043                 left = tmp;
6044         }
6045         if(AOP_TYPE(right) == AOP_LIT)
6046                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6047         
6048         size = AOP_SIZE(result);
6049         
6050         // if(bit ^ yy)
6051         // xx = bit ^ yy;
6052         if (AOP_TYPE(left) == AOP_CRY){
6053                 if(AOP_TYPE(right) == AOP_LIT){
6054                         // c = bit & literal;
6055                         if(lit>>1){
6056                                 // lit>>1  != 0 => result = 1
6057                                 if(AOP_TYPE(result) == AOP_CRY){
6058                                         if(size)
6059                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6060                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6061                                         else if(ifx)
6062                                                 continueIfTrue(ifx);
6063                                         goto release;
6064                                 }
6065                                 pic14_emitcode("setb","c");
6066                         } else{
6067                                 // lit == (0 or 1)
6068                                 if(lit == 0){
6069                                         // lit == 0, result = left
6070                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6071                                                 goto release;
6072                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6073                                 } else{
6074                                         // lit == 1, result = not(left)
6075                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6076                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6077                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6078                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6079                                                 goto release;
6080                                         } else {
6081                                                 assert ( !"incomplete genXor" );
6082                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6083                                                 pic14_emitcode("cpl","c");
6084                                         }
6085                                 }
6086                         }
6087                         
6088                 } else {
6089                         // right != literal
6090                         symbol *tlbl = newiTempLabel(NULL);
6091                         if (AOP_TYPE(right) == AOP_CRY){
6092                                 // c = bit ^ bit;
6093                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6094                         }
6095                         else{
6096                                 int sizer = AOP_SIZE(right);
6097                                 // c = bit ^ val
6098                                 // if val>>1 != 0, result = 1
6099                                 pic14_emitcode("setb","c");
6100                                 while(sizer){
6101                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6102                                         if(sizer == 1)
6103                                                 // test the msb of the lsb
6104                                                 pic14_emitcode("anl","a,#0xfe");
6105                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6106                                         sizer--;
6107                                 }
6108                                 // val = (0,1)
6109                                 pic14_emitcode("rrc","a");
6110                         }
6111                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6112                         pic14_emitcode("cpl","c");
6113                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6114                 }
6115                 // bit = c
6116                 // val = c
6117                 if(size)
6118                         pic14_outBitC(result);
6119                 // if(bit | ...)
6120                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6121                         genIfxJump(ifx, "c");           
6122                 goto release ;
6123         }
6124         
6125         if(pic14_sameRegs(AOP(result),AOP(left))){
6126                 /* if left is same as result */
6127                 for(;size--; offset++) {
6128                         if(AOP_TYPE(right) == AOP_LIT){
6129                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6130                                 if(t == 0x00L)
6131                                         continue;
6132                                 else
6133                                         if (IS_AOP_PREG(left)) {
6134                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6135                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6136                                                 aopPut(AOP(result),"a",offset);
6137                                         } else {
6138                                                 emitpcode(POC_MOVLW, popGetLit(t));
6139                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6140                                                 pic14_emitcode("xrl","%s,%s",
6141                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6142                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6143                                         }
6144                         } else {
6145                                 if (AOP_TYPE(left) == AOP_ACC)
6146                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6147                                 else {
6148                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6149                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6150                                         /*
6151                                         if (IS_AOP_PREG(left)) {
6152                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6153                                         aopPut(AOP(result),"a",offset);
6154                                         } else
6155                                         pic14_emitcode("xrl","%s,a",
6156                                         aopGet(AOP(left),offset,FALSE,TRUE));
6157                                         */
6158                                 }
6159                         }
6160                 }
6161         } else {
6162                 // left & result in different registers
6163                 if(AOP_TYPE(result) == AOP_CRY){
6164                         // result = bit
6165                         // if(size), result in bit
6166                         // if(!size && ifx), conditional oper: if(left ^ right)
6167                         symbol *tlbl = newiTempLabel(NULL);
6168                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6169                         if(size)
6170                                 pic14_emitcode("setb","c");
6171                         while(sizer--){
6172                                 if((AOP_TYPE(right) == AOP_LIT) &&
6173                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6174                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6175                                 } else {
6176                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6177                                         pic14_emitcode("xrl","a,%s",
6178                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6179                                 }
6180                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6181                                 offset++;
6182                         }
6183                         if(size){
6184                                 CLRC;
6185                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6186                                 pic14_outBitC(result);
6187                         } else if(ifx)
6188                                 jmpTrueOrFalse(ifx, tlbl);
6189                 } else for(;(size--);offset++){
6190                         // normal case
6191                         // result = left & right
6192                         if(AOP_TYPE(right) == AOP_LIT){
6193                                 int t = (lit >> (offset*8)) & 0x0FFL;
6194                                 switch(t) { 
6195                                 case 0x00:
6196                                         if (AOP_TYPE(left) != AOP_ACC) {
6197                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6198                                         }
6199                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6200                                         pic14_emitcode("movf","%s,w",
6201                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6202                                         pic14_emitcode("movwf","%s",
6203                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6204                                         break;
6205                                 case 0xff:
6206                                         if (AOP_TYPE(left) == AOP_ACC) {
6207                                                 emitpcode(POC_XORLW, popGetLit(t));
6208                                         } else {
6209                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6210                                         }
6211                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6212                                         break;
6213                                 default:
6214                                         if (AOP_TYPE(left) == AOP_ACC) {
6215                                                 emitpcode(POC_XORLW, popGetLit(t));
6216                                         } else {
6217                                                 emitpcode(POC_MOVLW, popGetLit(t));
6218                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6219                                         }
6220                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6221                                         pic14_emitcode("movlw","0x%x",t);
6222                                         pic14_emitcode("xorwf","%s,w",
6223                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6224                                         pic14_emitcode("movwf","%s",
6225                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6226                                         
6227                                 }
6228                                 continue;
6229                         }
6230                         
6231                         // faster than result <- left, anl result,right
6232                         // and better if result is SFR
6233                         if (AOP_TYPE(left) == AOP_ACC) {
6234                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6235                         } else {
6236                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6237                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6238                         }
6239                         if ( AOP_TYPE(result) != AOP_ACC){
6240                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6241                         }
6242                 }
6243         }
6244         
6245 release :
6246         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6247         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6248         freeAsmop(result,NULL,ic,TRUE);     
6249 }
6250
6251 /*-----------------------------------------------------------------*/
6252 /* genInline - write the inline code out                           */
6253 /*-----------------------------------------------------------------*/
6254 static void genInline (iCode *ic)
6255 {
6256   char *buffer, *bp, *bp1;
6257
6258   FENTRY;
6259   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6260
6261   _G.inLine += (!options.asmpeep);
6262
6263   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6264   strcpy(buffer,IC_INLINE(ic));
6265
6266   /* emit each line as a code */
6267   while (*bp) {
6268     if (*bp == '\n') {
6269       *bp++ = '\0';
6270       
6271       if(*bp1)
6272         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6273       bp1 = bp;
6274     } else {
6275       if (*bp == ':') {
6276         bp++;
6277         *bp = '\0';
6278         bp++;
6279
6280         /* print label, use this special format with NULL directive
6281          * to denote that the argument should not be indented with tab */
6282         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6283
6284         bp1 = bp;
6285       } else
6286         bp++;
6287     }
6288   }
6289   if ((bp1 != bp) && *bp1)
6290     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6291
6292   Safe_free(buffer);
6293
6294   _G.inLine -= (!options.asmpeep);
6295 }
6296
6297 /*-----------------------------------------------------------------*/
6298 /* genRRC - rotate right with carry                                */
6299 /*-----------------------------------------------------------------*/
6300 static void genRRC (iCode *ic)
6301 {
6302         operand *left , *result ;
6303         int size, offset = 0, same;
6304         
6305         FENTRY;
6306         /* rotate right with carry */
6307         left = IC_LEFT(ic);
6308         result=IC_RESULT(ic);
6309         aopOp (left,ic,FALSE);
6310         aopOp (result,ic,FALSE);
6311         
6312         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6313         
6314         same = pic14_sameRegs(AOP(result),AOP(left));
6315         
6316         size = AOP_SIZE(result);    
6317         
6318         /* get the lsb and put it into the carry */
6319         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6320         
6321         offset = 0 ;
6322         
6323         while(size--) {
6324                 
6325                 if(same) {
6326                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6327                 } else {
6328                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6329                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6330                 }
6331                 
6332                 offset++;
6333         }
6334         
6335         freeAsmop(left,NULL,ic,TRUE);
6336         freeAsmop(result,NULL,ic,TRUE);
6337 }
6338
6339 /*-----------------------------------------------------------------*/
6340 /* genRLC - generate code for rotate left with carry               */
6341 /*-----------------------------------------------------------------*/
6342 static void genRLC (iCode *ic)
6343 {    
6344         operand *left , *result ;
6345         int size, offset = 0;
6346         int same;
6347         
6348         FENTRY;
6349         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6350         /* rotate right with carry */
6351         left = IC_LEFT(ic);
6352         result=IC_RESULT(ic);
6353         aopOp (left,ic,FALSE);
6354         aopOp (result,ic,FALSE);
6355         
6356         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6357         
6358         same = pic14_sameRegs(AOP(result),AOP(left));
6359         
6360         /* move it to the result */
6361         size = AOP_SIZE(result);    
6362         
6363         /* get the msb and put it into the carry */
6364         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6365         
6366         offset = 0 ;
6367         
6368         while(size--) {
6369                 
6370                 if(same) {
6371                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6372                 } else {
6373                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6374                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6375                 }
6376                 
6377                 offset++;
6378         }
6379         
6380         
6381         freeAsmop(left,NULL,ic,TRUE);
6382         freeAsmop(result,NULL,ic,TRUE);
6383 }
6384
6385 /*-----------------------------------------------------------------*/
6386 /* genGetHbit - generates code get highest order bit               */
6387 /*-----------------------------------------------------------------*/
6388 static void genGetHbit (iCode *ic)
6389 {
6390         operand *left, *result;
6391         left = IC_LEFT(ic);
6392         result=IC_RESULT(ic);
6393         aopOp (left,ic,FALSE);
6394         aopOp (result,ic,FALSE);
6395         
6396         FENTRY;
6397         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6398         /* get the highest order byte into a */
6399         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6400         if(AOP_TYPE(result) == AOP_CRY){
6401                 pic14_emitcode("rlc","a");
6402                 pic14_outBitC(result);
6403         }
6404         else{
6405                 pic14_emitcode("rl","a");
6406                 pic14_emitcode("anl","a,#0x01");
6407                 pic14_outAcc(result);
6408         }
6409         
6410         
6411         freeAsmop(left,NULL,ic,TRUE);
6412         freeAsmop(result,NULL,ic,TRUE);
6413 }
6414
6415 /*-----------------------------------------------------------------*/
6416 /* AccLsh - shift left accumulator by known count                  */
6417 /* MARK: pic14 always rotates through CARRY!                       */
6418 /*-----------------------------------------------------------------*/
6419 static void AccLsh (pCodeOp *pcop,int shCount)
6420 {
6421         FENTRY;
6422         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6423         shCount &= 0x0007;              // shCount : 0..7
6424         switch(shCount){
6425         case 0 :
6426                 return;
6427                 break;
6428         case 1 :
6429                 emitCLRC;
6430                 emitpcode(POC_RLF,pcop);
6431                 return;
6432                 break;
6433         case 2 :
6434                 emitpcode(POC_RLF,pcop);
6435                 emitpcode(POC_RLF,pcop);
6436                 break;
6437         case 3 :
6438                 emitpcode(POC_RLF,pcop);
6439                 emitpcode(POC_RLF,pcop);
6440                 emitpcode(POC_RLF,pcop);
6441                 break;
6442         case 4 :
6443                 emitpcode(POC_SWAPF,pcop);
6444                 break;
6445         case 5 :
6446                 emitpcode(POC_SWAPF,pcop);
6447                 emitpcode(POC_RLF,pcop);
6448                 break;
6449         case 6 :
6450                 emitpcode(POC_SWAPF,pcop);
6451                 emitpcode(POC_RLF,pcop);
6452                 emitpcode(POC_RLF,pcop);
6453                 break;
6454         case 7 :
6455                 emitpcode(POC_RRFW,pcop);
6456                 emitpcode(POC_RRF,pcop);
6457                 break;
6458         }
6459         /* clear invalid bits */
6460         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6461         emitpcode(POC_ANDWF, pcop);
6462 }
6463
6464 /*-----------------------------------------------------------------*/
6465 /* AccRsh - shift right accumulator by known count                 */
6466 /* MARK: pic14 always rotates through CARRY!                       */
6467 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6468 /*            1: mask out invalid bits (zero-extend)               */
6469 /*            2: sign-extend result (pretty slow)                  */
6470 /*-----------------------------------------------------------------*/
6471 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6472 {
6473         FENTRY;
6474         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6475         shCount &= 0x0007;              // shCount : 0..7
6476         switch(shCount){
6477         case 0 :
6478                 return;
6479                 break;
6480         case 1 :
6481                 /* load sign if needed */
6482                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6483                 else if (mask_mode == 1) emitCLRC;
6484                 emitpcode(POC_RRF,pcop);
6485                 return;
6486                 break;
6487         case 2 :
6488                 /* load sign if needed */
6489                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6490                 emitpcode(POC_RRF,pcop);
6491                 /* load sign if needed */
6492                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6493                 emitpcode(POC_RRF,pcop);
6494                 if (mask_mode == 2) return;
6495                 break;
6496         case 3 :
6497                 /* load sign if needed */
6498                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6499                 emitpcode(POC_RRF,pcop);
6500                 /* load sign if needed */
6501                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6502                 emitpcode(POC_RRF,pcop);
6503                 /* load sign if needed */
6504                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6505                 emitpcode(POC_RRF,pcop);
6506                 if (mask_mode == 2) return;
6507                 break;
6508         case 4 :
6509                 emitpcode(POC_SWAPF,pcop);
6510                 break;
6511         case 5 :
6512                 emitpcode(POC_SWAPF,pcop);
6513                 emitpcode(POC_RRF,pcop);
6514                 break;
6515         case 6 :
6516                 emitpcode(POC_SWAPF,pcop);
6517                 emitpcode(POC_RRF,pcop);
6518                 emitpcode(POC_RRF,pcop);
6519                 break;
6520         case 7 :
6521                 if (mask_mode == 2)
6522                 {
6523                         /* load sign */
6524                         emitpcode(POC_RLFW,pcop);
6525                         emitpcode(POC_CLRF,pcop);
6526                         emitSKPNC;
6527                         emitpcode(POC_COMF,pcop);
6528                         return;
6529                 } else {
6530                         emitpcode(POC_RLFW,pcop);
6531                         emitpcode(POC_RLF,pcop);
6532                 }
6533                 break;
6534         }
6535
6536         if (mask_mode == 0)
6537         {
6538                 /* leave invalid bits undefined */
6539                 return;
6540         }
6541         
6542         /* clear invalid bits -- zero-extend */
6543         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6544         emitpcode(POC_ANDWF, pcop);
6545
6546         if (mask_mode == 2) {
6547           /* sign-extend */
6548           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6549           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6550           emitpcode(POC_IORWF, pcop);
6551         }
6552 }
6553
6554 #if 0
6555 /*-----------------------------------------------------------------*/
6556 /* AccSRsh - signed right shift accumulator by known count                 */
6557 /*-----------------------------------------------------------------*/
6558 static void AccSRsh (int shCount)
6559 {
6560         symbol *tlbl ;
6561         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6562         if(shCount != 0){
6563                 if(shCount == 1){
6564                         pic14_emitcode("mov","c,acc.7");
6565                         pic14_emitcode("rrc","a");
6566                 } else if(shCount == 2){
6567                         pic14_emitcode("mov","c,acc.7");
6568                         pic14_emitcode("rrc","a");
6569                         pic14_emitcode("mov","c,acc.7");
6570                         pic14_emitcode("rrc","a");
6571                 } else {
6572                         tlbl = newiTempLabel(NULL);
6573                         /* rotate right accumulator */
6574                         AccRol(8 - shCount);
6575                         /* and kill the higher order bits */
6576                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6577                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6578                         pic14_emitcode("orl","a,#0x%02x",
6579                                 (unsigned char)~SRMask[shCount]);
6580                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6581                 }
6582         }
6583 }
6584
6585 /*-----------------------------------------------------------------*/
6586 /* shiftR1Left2Result - shift right one byte from left to result   */
6587 /*-----------------------------------------------------------------*/
6588 static void shiftR1Left2ResultSigned (operand *left, int offl,
6589                                                                           operand *result, int offr,
6590                                                                           int shCount)
6591 {
6592         int same;
6593         
6594         FENTRY;
6595         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6596         
6597         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6598         
6599         switch(shCount) {
6600         case 1:
6601                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6602                 if(same) 
6603                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6604                 else {
6605                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6606                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6607                 }
6608                 
6609                 break;
6610         case 2:
6611                 
6612                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6613                 if(same) 
6614                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6615                 else {
6616                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6617                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6618                 }
6619                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6620                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6621                 
6622                 break;
6623                 
6624         case 3:
6625                 if(same)
6626                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6627                 else {
6628                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6629                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6630                 }
6631                 
6632                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6633                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6634                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6635                 
6636                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6637                 emitpcode(POC_IORLW, popGetLit(0xe0));
6638                 
6639                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6640                 break;
6641                 
6642         case 4:
6643                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6644                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6645                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6646                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6647                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6648                 break;
6649         case 5:
6650                 if(same) {
6651                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6652                 } else {
6653                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6654                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6655                 }
6656                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6657                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6658                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6659                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6660                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6661                 break;
6662                 
6663         case 6:
6664                 if(same) {
6665                         emitpcode(POC_MOVLW, popGetLit(0x00));
6666                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6667                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6668                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6669                         emitpcode(POC_IORLW, popGetLit(0x01));
6670                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6671                 } else {
6672                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6673                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6674                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6675                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6676                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6677                 }
6678                 break;
6679                 
6680         case 7:
6681                 if(same) {
6682                         emitpcode(POC_MOVLW, popGetLit(0x00));
6683                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6684                         emitpcode(POC_MOVLW, popGetLit(0xff));
6685                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6686                 } else {
6687                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6688                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6689                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6690                 }
6691                 
6692         default:
6693                 break;
6694         }
6695 }
6696
6697 /*-----------------------------------------------------------------*/
6698 /* shiftR1Left2Result - shift right one byte from left to result   */
6699 /*-----------------------------------------------------------------*/
6700 static void shiftR1Left2Result (operand *left, int offl,
6701                                                                 operand *result, int offr,
6702                                                                 int shCount, int sign)
6703 {
6704         int same;
6705         
6706         FENTRY;
6707         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6708         
6709         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6710         
6711         /* Copy the msb into the carry if signed. */
6712         if(sign) {
6713                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6714                 return;
6715         }
6716         
6717         
6718         
6719         switch(shCount) {
6720         case 1:
6721                 emitCLRC;
6722                 if(same) 
6723                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6724                 else {
6725                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6726                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6727                 }
6728                 break;
6729         case 2:
6730                 emitCLRC;
6731                 if(same) {
6732                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6733                 } else {
6734                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6735                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6736                 }
6737                 emitCLRC;
6738                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6739                 
6740                 break;
6741         case 3:
6742                 if(same)
6743                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6744                 else {
6745                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6746                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6747                 }
6748                 
6749                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6750                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6751                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6752                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6753                 break;
6754                 
6755         case 4:
6756                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6757                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6758                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6759                 break;
6760                 
6761         case 5:
6762                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6763                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6764                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6765                 emitCLRC;
6766                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6767                 
6768                 break;
6769         case 6:
6770                 
6771                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6772                 emitpcode(POC_ANDLW, popGetLit(0x80));
6773                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6774                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6775                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6776                 break;
6777                 
6778         case 7:
6779                 
6780                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6781                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6782                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6783                 
6784                 break;
6785                 
6786         default:
6787                 break;
6788         }
6789 }
6790
6791 /*-----------------------------------------------------------------*/
6792 /* shiftL1Left2Result - shift left one byte from left to result    */
6793 /*-----------------------------------------------------------------*/
6794 static void shiftL1Left2Result (operand *left, int offl,
6795                                                                 operand *result, int offr, int shCount)
6796 {
6797         int same;
6798         
6799         //    char *l;
6800         FENTRY;
6801         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6802         
6803         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6804         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6805         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6806         //    MOVA(l);
6807         /* shift left accumulator */
6808         //AccLsh(shCount); // don't comment out just yet...
6809         //    aopPut(AOP(result),"a",offr);
6810         
6811         switch(shCount) {
6812         case 1:
6813                 /* Shift left 1 bit position */
6814                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6815                 if(same) {
6816                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6817                 } else {
6818                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6819                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6820                 }
6821                 break;
6822         case 2:
6823                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6824                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6825                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6826                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6827                 break;
6828         case 3:
6829                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6830                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6831                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6832                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6833                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6834                 break;
6835         case 4:
6836                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6837                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6838                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6839                 break;
6840         case 5:
6841                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6842                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6843                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6844                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6845                 break;
6846         case 6:
6847                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6848                 emitpcode(POC_ANDLW, popGetLit(0x30));
6849                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6850                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6851                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6852                 break;
6853         case 7:
6854                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6855                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6856                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6857                 break;
6858                 
6859         default:
6860                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6861         }
6862         
6863 }
6864 #endif
6865
6866 /*-----------------------------------------------------------------*/
6867 /* movLeft2Result - move byte from left to result                  */
6868 /*-----------------------------------------------------------------*/
6869 static void movLeft2Result (operand *left, int offl,
6870                                                         operand *result, int offr)
6871 {
6872         char *l;
6873         FENTRY;
6874         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6875         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6876                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6877                 
6878                 if (*l == '@' && (IS_AOP_PREG(result))) {
6879                         pic14_emitcode("mov","a,%s",l);
6880                         aopPut(AOP(result),"a",offr);
6881                 } else {
6882                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6883                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6884                 }
6885         }
6886 }
6887
6888 /*-----------------------------------------------------------------*/
6889 /* shiftLeft_Left2ResultLit - shift left by known count            */
6890 /*-----------------------------------------------------------------*/
6891
6892 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6893 {
6894         int size, same, offr, i;
6895
6896         size = AOP_SIZE(left);
6897         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6898         
6899         same = pic14_sameRegs (AOP(left), AOP(result));
6900         
6901         offr = shCount / 8;
6902         shCount = shCount & 0x07;
6903
6904         size -= offr;
6905
6906         switch (shCount)
6907         {
6908         case 0: /* takes 0 or 2N cycles (for offr==0) */
6909                 if (!same || offr) {
6910                         for (i=size-1; i >= 0; i--)
6911                                 movLeft2Result (left, i, result, offr + i);
6912                 } // if
6913                 break;
6914                 
6915         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6916                 if (same && offr) {
6917                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6918                         shiftLeft_Left2ResultLit (result, result, shCount);
6919                         return; /* prevent clearing result again */
6920                 } else {
6921                         emitCLRC;
6922                         for (i=0; i < size; i++) {
6923                                 if (same && !offr) {
6924                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6925                                 } else {
6926                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6927                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6928                                 } // if
6929                         } // for
6930                 } // if (offr)
6931                 break;
6932                 
6933         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6934                 /* works in-place/with offr as well */
6935                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6936                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6937                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6938
6939                 for (i = size - 2; i >= 0; i--)
6940                 {
6941                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6942                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6943                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6944                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6945                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6946                 } // for i
6947                 break;
6948                 
6949         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6950                 /* works in-place/with offr as well */
6951                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6952                 for (i = size-2; i >= 0; i--) {
6953                         emitpcode (POC_RRFW, popGet (AOP(left), i));
6954                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6955                 } // for i
6956                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6957                 emitpcode (POC_RRF, popGet (AOP(result), offr));
6958                 break;
6959         
6960         default:
6961                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6962                 shiftLeft_Left2ResultLit (result, result, 1);
6963                 return; /* prevent clearing result again */
6964                 break;
6965         } // switch
6966
6967         while (0 < offr--)
6968         {
6969                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6970         } // while
6971 }
6972
6973 /*-----------------------------------------------------------------*/
6974 /* shiftRight_Left2ResultLit - shift right by known count          */
6975 /*-----------------------------------------------------------------*/
6976
6977 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6978 {
6979         int size, same, offr, i;
6980
6981         size = AOP_SIZE(left);
6982         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6983         
6984         same = pic14_sameRegs (AOP(left), AOP(result));
6985         
6986         offr = shCount / 8;
6987         shCount = shCount & 0x07;
6988
6989         size -= offr;
6990
6991         if (size)
6992         {
6993                 switch (shCount)
6994                 {
6995                 case 0: /* takes 0 or 2N cycles (for offr==0) */
6996                         if (!same || offr) {
6997                                 for (i=0; i < size; i++)
6998                                         movLeft2Result (left, i + offr, result, i);
6999                         } // if
7000                         break;
7001                         
7002                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7003                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7004                         if (same && offr) {
7005                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7006                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7007                                 return; /* prevent sign-extending result again */
7008                         } else {
7009                                 emitCLRC;
7010                                 if (sign) {
7011                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7012                                         emitSETC;
7013                                 }
7014                                 for (i = size-1; i >= 0; i--) {
7015                                         if (same && !offr) {
7016                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7017                                         } else {
7018                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7019                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7020                                         }
7021                                 } // for i
7022                         } // if (offr)
7023                         break;
7024                         
7025                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7026                         /* works in-place/with offr as well */
7027                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7028                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7029                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7030
7031                         for (i = 1; i < size; i++)
7032                         {
7033                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7034                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7035                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7036                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7037                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7038                         } // for i
7039
7040                         if (sign)
7041                         {
7042                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7043                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7044                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7045                         } // if
7046                         break;
7047                         
7048                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7049                         /* works in-place/with offr as well */
7050                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7051                         for (i = 0; i < size-1; i++) {
7052                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7053                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7054                         } // for i
7055                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7056                         if (!sign) {
7057                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7058                         } else {
7059                                 emitSKPNC;
7060                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7061                         }
7062                         break;
7063                 
7064                 default:
7065                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7066                         shiftRight_Left2ResultLit (result, result, 1, sign);
7067                         return; /* prevent sign extending result again */
7068                         break;
7069                 } // switch
7070         } // if
7071
7072         addSign (result, size, sign);
7073 }
7074
7075 #if 0
7076 /*-----------------------------------------------------------------*/
7077 /* shiftL2Left2Result - shift left two bytes from left to result   */
7078 /*-----------------------------------------------------------------*/
7079 static void shiftL2Left2Result (operand *left, int offl,
7080                                                                 operand *result, int offr, int shCount)
7081 {
7082         FENTRY;
7083         
7084         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7085         
7086         if(pic14_sameRegs(AOP(result), AOP(left))) {
7087                 switch(shCount) {
7088                 case 0:
7089                         break;
7090                 case 1:
7091                 case 2:
7092                 case 3:
7093                         
7094                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7095                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7096                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7097                         
7098                         while(--shCount) {
7099                                 emitCLRC;
7100                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7101                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7102                         }
7103                         
7104                         break;
7105                 case 4:
7106                 case 5:
7107                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7108                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7109                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7110                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7111                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7112                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7113                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7114                         if(shCount >=5) {
7115                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7116                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7117                         }
7118                         break;
7119                 case 6:
7120                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7121                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7122                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7123                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7124                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7125                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7126                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7127                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7128                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7129                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7130                         break;
7131                 case 7:
7132                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7133                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7134                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7135                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7136                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7137                 }
7138                 
7139         } else {
7140                 switch(shCount) {
7141                 case 0:
7142                         break;
7143                 case 1:
7144                 case 2:
7145                 case 3:
7146                 /* note, use a mov/add for the shift since the mov has a
7147                         chance of getting optimized out */
7148                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7149                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7150                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7151                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7152                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7153                         
7154                         while(--shCount) {
7155                                 emitCLRC;
7156                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7157                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7158                         }
7159                         break;
7160                         
7161                 case 4:
7162                 case 5:
7163                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7164                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7165                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7166                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7167                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7168                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7169                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7170                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7171                         
7172                         
7173                         if(shCount == 5) {
7174                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7175                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7176                         }
7177                         break;
7178                 case 6:
7179                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7180                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7181                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7182                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7183                         
7184                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7185                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7186                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7187                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7188                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7189                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7190                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7191                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7192                         break;
7193                 case 7:
7194                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7195                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7196                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7197                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7198                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7199                 }
7200         }
7201         
7202 }
7203
7204 /*-----------------------------------------------------------------*/
7205 /* shiftR2Left2Result - shift right two bytes from left to result  */
7206 /*-----------------------------------------------------------------*/
7207 static void shiftR2Left2Result (operand *left, int offl,
7208                                                                 operand *result, int offr,
7209                                                                 int shCount, int sign)
7210 {
7211         int same=0;
7212         
7213         FENTRY;
7214         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7215         same = pic14_sameRegs(AOP(result), AOP(left));
7216         
7217         if(same && ((offl + MSB16) == offr)){
7218                 same=1;
7219                 /* don't crash result[offr] */
7220                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7221                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7222         }
7223         /* else {
7224         movLeft2Result(left,offl, result, offr);
7225         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7226         }
7227         */
7228         /* a:x >> shCount (x = lsb(result))*/
7229         /*
7230         if(sign)
7231         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7232         else {
7233         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7234         */
7235         switch(shCount) {
7236         case 0:
7237                 break;
7238         case 1:
7239         case 2:
7240         case 3:
7241                 if(sign)
7242                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7243                 else
7244                         emitCLRC;
7245                 
7246                 if(same) {
7247                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7248                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7249                 } else {
7250                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7251                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7252                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7253                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7254                 }
7255                 
7256                 while(--shCount) {
7257                         if(sign)
7258                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7259                         else
7260                                 emitCLRC;
7261                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7262                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7263                 }
7264                 break;
7265         case 4:
7266         case 5:
7267                 if(same) {
7268                         
7269                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7270                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7271                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7272                         
7273                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7274                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7275                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7276                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7277                 } else {
7278                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7279                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7280                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7281                         
7282                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7283                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7284                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7285                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7286                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7287                 }
7288                 
7289                 if(shCount >=5) {
7290                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7291                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7292                 }
7293                 
7294                 if(sign) {
7295                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7296                         emitpcode(POC_BTFSC, 
7297                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7298                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7299                 }
7300                 
7301                 break;
7302                 
7303         case 6:
7304                 if(same) {
7305                         
7306                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7307                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7308                         
7309                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7310                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7311                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7312                         emitpcode(POC_ANDLW,popGetLit(0x03));
7313                         if(sign) {
7314                                 emitpcode(POC_BTFSC, 
7315                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7316                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7317                         }
7318                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7319                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7320                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7321                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7322                 } else {
7323                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7324                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7325                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7326                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7327                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7328                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7329                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7330                         emitpcode(POC_ANDLW,popGetLit(0x03));
7331                         if(sign) {
7332                                 emitpcode(POC_BTFSC, 
7333                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7334                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7335                         }
7336                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7337                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7338                         
7339                         
7340                 }
7341                 
7342                 break;
7343         case 7:
7344                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7345                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7346                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7347                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7348                 if(sign) {
7349                         emitSKPNC;
7350                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7351                 } else 
7352                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7353   }
7354 }
7355
7356 /*-----------------------------------------------------------------*/
7357 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7358 /*-----------------------------------------------------------------*/
7359 static void shiftLLeftOrResult (operand *left, int offl,
7360                                                                 operand *result, int offr, int shCount)
7361 {
7362         FENTRY;
7363         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7364         
7365         /* shift left accumulator */
7366         AccLsh(left,offl,shCount);
7367         /* or with result */
7368         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7369         assert ( !"broken (modifies left, fails for left==result))" );
7370 }
7371
7372 /*-----------------------------------------------------------------*/
7373 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7374 /*-----------------------------------------------------------------*/
7375 static void shiftRLeftOrResult (operand *left, int offl,
7376                                                                 operand *result, int offr, int shCount)
7377 {
7378         FENTRY;
7379         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7380         
7381         /* shift right accumulator */
7382         AccRsh(left,offl,shCount);
7383         /* or with result */
7384         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7385         assert ( !"broken (modifies left, fails for left==result))" );
7386 }
7387
7388 /*-----------------------------------------------------------------*/
7389 /* genlshOne - left shift a one byte quantity by known count       */
7390 /*-----------------------------------------------------------------*/
7391 static void genlshOne (operand *result, operand *left, int shCount)
7392 {       
7393         FENTRY;
7394         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7395         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7396 }
7397
7398 /*-----------------------------------------------------------------*/
7399 /* genlshTwo - left shift two bytes by known amount != 0           */
7400 /*-----------------------------------------------------------------*/
7401 static void genlshTwo (operand *result,operand *left, int shCount)
7402 {
7403         int size;
7404         
7405         FENTRY;
7406         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7407         size = pic14_getDataSize(result);
7408         
7409         /* if shCount >= 8 */
7410         if (shCount >= 8) {
7411                 shCount -= 8 ;
7412                 
7413                 if (size > 1){
7414                         if (shCount)
7415                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7416                         else 
7417                                 movLeft2Result(left, LSB, result, MSB16);
7418                 }
7419                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7420         }
7421         
7422         /*  1 <= shCount <= 7 */
7423         else {  
7424                 if(size == 1)
7425                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7426                 else 
7427                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7428         }
7429 }
7430
7431 /*-----------------------------------------------------------------*/
7432 /* shiftLLong - shift left one long from left to result            */
7433 /* offl = LSB or MSB16                                             */
7434 /*-----------------------------------------------------------------*/
7435 static void shiftLLong (operand *left, operand *result, int offr )
7436 {
7437         char *l;
7438         int size = AOP_SIZE(result);
7439         
7440         FENTRY;
7441         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7442         if(size >= LSB+offr){
7443                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7444                 MOVA(l);
7445                 pic14_emitcode("add","a,acc");
7446                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7447                         size >= MSB16+offr && offr != LSB )
7448                         pic14_emitcode("xch","a,%s",
7449                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7450                 else      
7451                         aopPut(AOP(result),"a",LSB+offr);
7452         }
7453         
7454         if(size >= MSB16+offr){
7455                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7456                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7457                         MOVA(l);
7458                 }
7459                 pic14_emitcode("rlc","a");
7460                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7461                         size >= MSB24+offr && offr != LSB)
7462                         pic14_emitcode("xch","a,%s",
7463                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7464                 else      
7465                         aopPut(AOP(result),"a",MSB16+offr);
7466         }
7467         
7468         if(size >= MSB24+offr){
7469                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7470                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7471                         MOVA(l);
7472                 }
7473                 pic14_emitcode("rlc","a");
7474                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7475                         size >= MSB32+offr && offr != LSB )
7476                         pic14_emitcode("xch","a,%s",
7477                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7478                 else      
7479                         aopPut(AOP(result),"a",MSB24+offr);
7480         }
7481         
7482         if(size > MSB32+offr){
7483                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7484                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7485                         MOVA(l);  
7486                 }
7487                 pic14_emitcode("rlc","a");
7488                 aopPut(AOP(result),"a",MSB32+offr);
7489         }
7490         if(offr != LSB)
7491                 aopPut(AOP(result),zero,LSB);       
7492 }
7493
7494 /*-----------------------------------------------------------------*/
7495 /* genlshFour - shift four byte by a known amount != 0             */
7496 /*-----------------------------------------------------------------*/
7497 static void genlshFour (operand *result, operand *left, int shCount)
7498 {
7499         int size;
7500         
7501         FENTRY;
7502         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7503         size = AOP_SIZE(result);
7504         
7505         /* if shifting more that 3 bytes */
7506         if (shCount >= 24 ) {
7507                 shCount -= 24;
7508                 if (shCount)
7509                 /* lowest order of left goes to the highest
7510                 order of the destination */
7511                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7512                 else
7513                         movLeft2Result(left, LSB, result, MSB32);
7514                 aopPut(AOP(result),zero,LSB);
7515                 aopPut(AOP(result),zero,MSB16);
7516                 aopPut(AOP(result),zero,MSB32);
7517                 return;
7518         }
7519         
7520         /* more than two bytes */
7521         else if ( shCount >= 16 ) {
7522                 /* lower order two bytes goes to higher order two bytes */
7523                 shCount -= 16;
7524                 /* if some more remaining */
7525                 if (shCount)
7526                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7527                 else {
7528                         movLeft2Result(left, MSB16, result, MSB32);
7529                         movLeft2Result(left, LSB, result, MSB24);
7530                 }
7531                 aopPut(AOP(result),zero,MSB16);
7532                 aopPut(AOP(result),zero,LSB);
7533                 return;
7534         }    
7535         
7536         /* if more than 1 byte */
7537         else if ( shCount >= 8 ) {
7538                 /* lower order three bytes goes to higher order  three bytes */
7539                 shCount -= 8;
7540                 if(size == 2){
7541                         if(shCount)
7542                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7543                         else
7544                                 movLeft2Result(left, LSB, result, MSB16);
7545                 }
7546                 else{   /* size = 4 */
7547                         if(shCount == 0){
7548                                 movLeft2Result(left, MSB24, result, MSB32);
7549                                 movLeft2Result(left, MSB16, result, MSB24);
7550                                 movLeft2Result(left, LSB, result, MSB16);
7551                                 aopPut(AOP(result),zero,LSB);
7552                         }
7553                         else if(shCount == 1)
7554                                 shiftLLong(left, result, MSB16);
7555                         else{
7556                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7557                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7558                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7559                                 aopPut(AOP(result),zero,LSB);
7560                         }
7561                 }
7562         }
7563         
7564         /* 1 <= shCount <= 7 */
7565         else if(shCount <= 2){
7566                 shiftLLong(left, result, LSB);
7567                 if(shCount == 2)
7568                         shiftLLong(result, result, LSB);
7569         }
7570         /* 3 <= shCount <= 7, optimize */
7571         else{
7572                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7573                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7574                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7575         }
7576 }
7577 #endif
7578
7579 #if 0
7580 /*-----------------------------------------------------------------*/
7581 /* genLeftShiftLiteral - left shifting by known count              */
7582 /*-----------------------------------------------------------------*/
7583 static void genLeftShiftLiteral (operand *left,
7584                                                                  operand *right,
7585                                                                  operand *result,
7586                                                                  iCode *ic)
7587 {    
7588         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7589         //int size;
7590         
7591         FENTRY;
7592         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7593         freeAsmop(right,NULL,ic,TRUE);
7594         
7595         aopOp(left,ic,FALSE);
7596         aopOp(result,ic,FALSE);
7597
7598         size = getSize(operandType(result));
7599         
7600 #if VIEW_SIZE
7601         pic14_emitcode("; shift left ","result %d, left %d",size,
7602                 AOP_SIZE(left));
7603 #endif
7604         
7605         /* I suppose that the left size >= result size */
7606         if(shCount == 0){
7607                 while(size--){
7608                         movLeft2Result(left, size, result, size);
7609                 }
7610         }
7611         
7612         else if(shCount >= (size * 8))
7613                 while(size--)
7614                         aopPut(AOP(result),zero,size);
7615                 else{
7616                         switch (size) {
7617                         case 1:
7618                                 genlshOne (result,left,shCount);
7619                                 break;
7620                                 
7621                         case 2:
7622                         case 3:
7623                                 genlshTwo (result,left,shCount);
7624                                 break;
7625                                 
7626                         case 4:
7627                                 genlshFour (result,left,shCount);
7628                                 break;
7629                         }
7630                 }
7631                 freeAsmop(left,NULL,ic,TRUE);
7632                 freeAsmop(result,NULL,ic,TRUE);
7633 }
7634 #endif
7635
7636 /*-----------------------------------------------------------------*
7637 * genMultiAsm - repeat assembly instruction for size of register.
7638 * if endian == 1, then the high byte (i.e base address + size of 
7639 * register) is used first else the low byte is used first;
7640 *-----------------------------------------------------------------*/
7641 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7642 {
7643         
7644         int offset = 0;
7645         
7646         FENTRY;
7647         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7648         
7649         if(!reg)
7650                 return;
7651         
7652         if(!endian) {
7653                 endian = 1;
7654         } else {
7655                 endian = -1;
7656                 offset = size-1;
7657         }
7658         
7659         while(size--) {
7660                 emitpcode(poc,    popGet(AOP(reg),offset));
7661                 offset += endian;
7662         }
7663         
7664 }
7665
7666 #if 0
7667 /*-----------------------------------------------------------------*/
7668 /* genLeftShift - generates code for left shifting                 */
7669 /*-----------------------------------------------------------------*/
7670 static void genLeftShift (iCode *ic)
7671 {
7672         operand *left,*right, *result;
7673         int size, offset;
7674         unsigned long lit = 0L;
7675         char *l;
7676         symbol *tlbl , *tlbl1;
7677         pCodeOp *pctemp;
7678         
7679         FENTRY;
7680         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7681         
7682         right = IC_RIGHT(ic);
7683         left  = IC_LEFT(ic);
7684         result = IC_RESULT(ic);
7685         
7686         aopOp(right,ic,FALSE);
7687         aopOp(left,ic,FALSE);
7688         aopOp(result,ic,FALSE);
7689         
7690         
7691         /* if the shift count is known then do it 
7692         as efficiently as possible */
7693         if (AOP_TYPE(right) == AOP_LIT) {
7694                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7695                 return ;
7696         }
7697         
7698         /* shift count is unknown then we have to form 
7699         a loop get the loop count in B : Note: we take
7700         only the lower order byte since shifting
7701         more that 32 bits make no sense anyway, ( the
7702         largest size of an object can be only 32 bits ) */  
7703         
7704         /* this code fails for RIGHT == RESULT */
7705         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7706         
7707         /* now move the left to the result if they are not the
7708         same */
7709         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7710                 AOP_SIZE(result) > 1) {
7711                 
7712                 size = AOP_SIZE(result);
7713                 offset=0;
7714                 while (size--) {
7715                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7716                         if (*l == '@' && (IS_AOP_PREG(result))) {
7717                                 
7718                                 pic14_emitcode("mov","a,%s",l);
7719                                 aopPut(AOP(result),"a",offset);
7720                         } else {
7721                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7722                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7723                                 //aopPut(AOP(result),l,offset);
7724                         }
7725                         offset++;
7726                 }
7727         }
7728         
7729         if(AOP_TYPE(left) == AOP_LIT)
7730                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7731
7732         size = AOP_SIZE(result);
7733         
7734         /* if it is only one byte then */
7735         if (size == 1) {
7736                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7737                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7738                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7739                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7740                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7741                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7742                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7743                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7744                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7745                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7746                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7747                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7748                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7749                 } else {
7750                         
7751                         tlbl = newiTempLabel(NULL);
7752                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7753                                 mov2w (AOP(left), 0);
7754                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7755                         }
7756                         
7757                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7758                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7759                         emitpLabel(tlbl->key);
7760                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7761                         emitpcode(POC_ADDLW,  popGetLit(1));
7762                         emitSKPC;
7763                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7764                 }
7765                 goto release ;
7766         }
7767         
7768         if (pic14_sameRegs(AOP(left),AOP(result))) {
7769                 
7770                 tlbl = newiTempLabel(NULL);
7771                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7772                 genMultiAsm(POC_RRF, result, size,1);
7773                 emitpLabel(tlbl->key);
7774                 genMultiAsm(POC_RLF, result, size,0);
7775                 emitpcode(POC_ADDLW,  popGetLit(1));
7776                 emitSKPC;
7777                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7778                 goto release;
7779         }
7780         
7781         //tlbl = newiTempLabel(NULL);
7782         //offset = 0 ;   
7783         //tlbl1 = newiTempLabel(NULL);
7784         
7785         //reAdjustPreg(AOP(result));    
7786         
7787         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7788         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7789         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7790         //MOVA(l);
7791         //pic14_emitcode("add","a,acc");         
7792         //aopPut(AOP(result),"a",offset++);
7793         //while (--size) {
7794         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7795         //  MOVA(l);
7796         //  pic14_emitcode("rlc","a");         
7797         //  aopPut(AOP(result),"a",offset++);
7798         //}
7799         //reAdjustPreg(AOP(result));
7800         
7801         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7802         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7803         
7804         
7805         tlbl = newiTempLabel(NULL);
7806         tlbl1= newiTempLabel(NULL);
7807         
7808         size = AOP_SIZE(result);
7809         offset = 1;
7810         
7811         pctemp = popGetTempReg();  /* grab a temporary working register. */
7812         
7813         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7814         
7815         /* offset should be 0, 1 or 3 */
7816         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7817         emitSKPNZ;
7818         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7819         
7820         emitpcode(POC_MOVWF, pctemp);
7821         
7822         
7823         emitpLabel(tlbl->key);
7824         
7825         emitCLRC;
7826         emitpcode(POC_RLF,  popGet(AOP(result),0));
7827         while(--size)
7828                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7829         
7830         emitpcode(POC_DECFSZ,  pctemp);
7831         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7832         emitpLabel(tlbl1->key);
7833         
7834         popReleaseTempReg(pctemp);
7835         
7836         
7837 release:
7838         freeAsmop (right,NULL,ic,TRUE);
7839         freeAsmop(left,NULL,ic,TRUE);
7840         freeAsmop(result,NULL,ic,TRUE);
7841 }
7842 #endif
7843
7844 #if 0
7845 /*-----------------------------------------------------------------*/
7846 /* genrshOne - right shift a one byte quantity by known count      */
7847 /*-----------------------------------------------------------------*/
7848 static void genrshOne (operand *result, operand *left,
7849                                            int shCount, int sign)
7850 {
7851         FENTRY;
7852         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7853         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7854 }
7855
7856 /*-----------------------------------------------------------------*/
7857 /* genrshTwo - right shift two bytes by known amount != 0          */
7858 /*-----------------------------------------------------------------*/
7859 static void genrshTwo (operand *result,operand *left,
7860                                            int shCount, int sign)
7861 {
7862         FENTRY;
7863         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7864         /* if shCount >= 8 */
7865         if (shCount >= 8) {
7866                 shCount -= 8 ;
7867                 if (shCount)
7868                         shiftR1Left2Result(left, MSB16, result, LSB,
7869                         shCount, sign);
7870                 else
7871                         movLeft2Result(left, MSB16, result, LSB);
7872                 
7873                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7874                 
7875                 if(sign) {
7876                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7877                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7878                 }
7879         }
7880         
7881         /*  1 <= shCount <= 7 */
7882         else
7883                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7884 }
7885
7886 /*-----------------------------------------------------------------*/
7887 /* shiftRLong - shift right one long from left to result           */
7888 /* offl = LSB or MSB16                                             */
7889 /*-----------------------------------------------------------------*/
7890 static void shiftRLong (operand *left, int offl,
7891                                                 operand *result, int sign)
7892 {
7893         int size, same;
7894         
7895         FENTRY;
7896         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7897         
7898         size = AOP_SIZE(left);
7899         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7900         
7901         if (sign)
7902                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7903         else
7904                 emitCLRC;
7905
7906         assert (offl >= 0 && offl < size);
7907
7908         same = pic14_sameRegs (AOP(left), AOP(result));
7909
7910         /* perform the shift */
7911         while (size--)
7912         {
7913                 if (same && !offl) {
7914                         emitpcode (POC_RRF, popGet (AOP(result), size));
7915                 } else {
7916                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7917                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7918                 }
7919         } // while
7920
7921         addSign (result, AOP_SIZE(left) - offl, sign);
7922 }
7923
7924 /*-----------------------------------------------------------------*/
7925 /* genrshFour - shift four byte by a known amount != 0             */
7926 /*-----------------------------------------------------------------*/
7927 static void genrshFour (operand *result, operand *left,
7928                                                 int shCount, int sign)
7929 {
7930         FENTRY;
7931         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7932         /* if shifting more that 3 bytes */
7933         if(shCount >= 24 ) {
7934                 shCount -= 24;
7935                 if(shCount)
7936                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7937                 else
7938                         movLeft2Result(left, MSB32, result, LSB);
7939                 
7940                 addSign(result, MSB16, sign);
7941         }
7942         else if(shCount >= 16){
7943                 shCount -= 16;
7944                 if(shCount)
7945                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7946                 else{
7947                         movLeft2Result(left, MSB24, result, LSB);
7948                         movLeft2Result(left, MSB32, result, MSB16);
7949                 }
7950                 addSign(result, MSB24, sign);
7951         }
7952         else if(shCount >= 8){
7953                 shCount -= 8;
7954                 if(shCount == 1)
7955                         shiftRLong(left, MSB16, result, sign);
7956                 else if(shCount == 0){
7957                         movLeft2Result(left, MSB16, result, LSB);
7958                         movLeft2Result(left, MSB24, result, MSB16);
7959                         movLeft2Result(left, MSB32, result, MSB24);
7960                         addSign(result, MSB32, sign);
7961                 }
7962                 else{
7963                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7964                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7965                         /* the last shift is signed */
7966                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7967                         addSign(result, MSB32, sign);
7968                 }
7969         }
7970         else{   /* 1 <= shCount <= 7 */
7971                 if(shCount <= 2){
7972                         shiftRLong(left, LSB, result, sign);
7973                         if(shCount == 2)
7974                                 shiftRLong(result, LSB, result, sign);
7975                 }
7976                 else{
7977                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7978                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7979                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7980                 }
7981         }
7982 }
7983
7984 /*-----------------------------------------------------------------*/
7985 /* genRightShiftLiteral - right shifting by known count            */
7986 /*-----------------------------------------------------------------*/
7987 static void genRightShiftLiteral (operand *left,
7988                                                                   operand *right,
7989                                                                   operand *result,
7990                                                                   iCode *ic,
7991                                                                   int sign)
7992 {    
7993         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7994         int lsize,res_size;
7995         
7996         FENTRY;
7997         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7998         freeAsmop(right,NULL,ic,TRUE);
7999         
8000         aopOp(left,ic,FALSE);
8001         aopOp(result,ic,FALSE);
8002         
8003 #if VIEW_SIZE
8004         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8005                 AOP_SIZE(left));
8006 #endif
8007         
8008         lsize = pic14_getDataSize(left);
8009         res_size = pic14_getDataSize(result);
8010         /* test the LEFT size !!! */
8011         
8012         /* I suppose that the left size >= result size */
8013         if(shCount == 0){
8014                 while(res_size--)
8015                         movLeft2Result(left, res_size, result, res_size);
8016         }
8017         
8018         else if(shCount >= (lsize * 8)){
8019                 
8020                 if(res_size == 1) {
8021                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8022                         if(sign) {
8023                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8024                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8025                         }
8026                 } else {
8027                         
8028                         if(sign) {
8029                                 emitpcode(POC_MOVLW, popGetLit(0));
8030                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8031                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8032                                 while(res_size--)
8033                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8034                                 
8035                         } else {
8036                                 
8037                                 while(res_size--)
8038                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8039                         }
8040                 }
8041         } else {
8042                 
8043                 switch (res_size) {
8044                 case 1:
8045                         genrshOne (result,left,shCount,sign);
8046                         break;
8047                         
8048                 case 2:
8049                         genrshTwo (result,left,shCount,sign);
8050                         break;
8051                         
8052                 case 4:
8053                         genrshFour (result,left,shCount,sign);
8054                         break;
8055                 default :
8056                         break;
8057                 }
8058                 
8059         }
8060
8061         freeAsmop(left,NULL,ic,TRUE);
8062         freeAsmop(result,NULL,ic,TRUE);
8063 }
8064 #endif
8065
8066 #if 0
8067 /*-----------------------------------------------------------------*/
8068 /* genSignedRightShift - right shift of signed number              */
8069 /*-----------------------------------------------------------------*/
8070 static void genSignedRightShift (iCode *ic)
8071 {
8072         operand *right, *left, *result;
8073         int size, offset;
8074         //  char *l;
8075         symbol *tlbl, *tlbl1 ;
8076         pCodeOp *pctemp;
8077         
8078         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8079         
8080         /* we do it the hard way put the shift count in b
8081         and loop thru preserving the sign */
8082         FENTRY;
8083         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8084         
8085         right = IC_RIGHT(ic);
8086         left  = IC_LEFT(ic);
8087         result = IC_RESULT(ic);
8088         
8089         aopOp(right,ic,FALSE);  
8090         aopOp(left,ic,FALSE);
8091         aopOp(result,ic,FALSE);
8092         
8093         
8094         if ( AOP_TYPE(right) == AOP_LIT) {
8095                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8096                 //genRightShiftLiteral (left,right,result,ic,1);
8097                 return ;
8098         }
8099         /* shift count is unknown then we have to form 
8100         a loop get the loop count in B : Note: we take
8101         only the lower order byte since shifting
8102         more that 32 bits make no sense anyway, ( the
8103         largest size of an object can be only 32 bits ) */  
8104         
8105         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8106         //pic14_emitcode("inc","b");
8107         //freeAsmop (right,NULL,ic,TRUE);
8108         //aopOp(left,ic,FALSE);
8109         //aopOp(result,ic,FALSE);
8110         
8111         /* now move the left to the result if they are not the
8112         same */
8113         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8114                 AOP_SIZE(result) > 1) {
8115                 
8116                 size = AOP_SIZE(result);
8117                 offset=0;
8118                 while (size--) { 
8119                         /*
8120                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8121                         if (*l == '@' && IS_AOP_PREG(result)) {
8122                                 pic14_emitcode("mov","a,%s",l);
8123                                 aopPut(AOP(result),"a",offset);
8124                         } else
8125                         aopPut(AOP(result),l,offset);
8126                         */
8127                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8128                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8129                         
8130                         offset++;
8131                 }
8132         }
8133         
8134         /* mov the highest order bit to OVR */    
8135         tlbl = newiTempLabel(NULL);
8136         tlbl1= newiTempLabel(NULL);
8137         
8138         size = AOP_SIZE(result);
8139         offset = size - 1;
8140         
8141         pctemp = popGetTempReg();  /* grab a temporary working register. */
8142         
8143         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8144         
8145         /* offset should be 0, 1 or 3 */
8146         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8147         emitSKPNZ;
8148         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8149         
8150         emitpcode(POC_MOVWF, pctemp);
8151         
8152         
8153         emitpLabel(tlbl->key);
8154         
8155         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8156         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8157         
8158         while(--size) {
8159                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8160         }
8161         
8162         emitpcode(POC_DECFSZ,  pctemp);
8163         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8164         emitpLabel(tlbl1->key);
8165         
8166         popReleaseTempReg(pctemp);
8167 #if 0
8168         size = AOP_SIZE(result);
8169         offset = size - 1;
8170         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8171         pic14_emitcode("rlc","a");
8172         pic14_emitcode("mov","ov,c");
8173         /* if it is only one byte then */
8174         if (size == 1) {
8175                 l = aopGet(AOP(left),0,FALSE,FALSE);
8176                 MOVA(l);
8177                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8178                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8179                 pic14_emitcode("mov","c,ov");
8180                 pic14_emitcode("rrc","a");
8181                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8182                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8183                 aopPut(AOP(result),"a",0);
8184                 goto release ;
8185         }
8186         
8187         reAdjustPreg(AOP(result));
8188         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8189         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8190         pic14_emitcode("mov","c,ov");
8191         while (size--) {
8192                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8193                 MOVA(l);
8194                 pic14_emitcode("rrc","a");         
8195                 aopPut(AOP(result),"a",offset--);
8196         }
8197         reAdjustPreg(AOP(result));
8198         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8199         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8200         
8201 release:
8202 #endif
8203         
8204         freeAsmop(left,NULL,ic,TRUE);
8205         freeAsmop(result,NULL,ic,TRUE);
8206         freeAsmop(right,NULL,ic,TRUE);
8207 }
8208 #endif
8209
8210 /*-----------------------------------------------------------------*/
8211 /* loadSignToC - load the operand's sign bit into CARRY            */
8212 /*-----------------------------------------------------------------*/
8213
8214 static void loadSignToC (operand *op)
8215 {
8216         FENTRY;
8217         assert (op && AOP(op) && AOP_SIZE(op));
8218
8219         emitCLRC;
8220         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8221         emitSETC;
8222 }
8223
8224 /*-----------------------------------------------------------------*/
8225 /* genRightShift - generate code for right shifting                */
8226 /*-----------------------------------------------------------------*/
8227 static void genGenericShift (iCode *ic, int shiftRight)
8228 {
8229         operand *right, *left, *result;
8230         sym_link *retype ;
8231         int size;
8232         symbol *tlbl, *tlbl1, *inverselbl;
8233         
8234         FENTRY;
8235         /* if signed then we do it the hard way preserve the
8236         sign bit moving it inwards */
8237         retype = getSpec(operandType(IC_RESULT(ic)));
8238         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8239         
8240         /* signed & unsigned types are treated the same : i.e. the
8241         signed is NOT propagated inwards : quoting from the
8242         ANSI - standard : "for E1 >> E2, is equivalent to division
8243         by 2**E2 if unsigned or if it has a non-negative value,
8244         otherwise the result is implementation defined ", MY definition
8245         is that the sign does not get propagated */
8246         
8247         right = IC_RIGHT(ic);
8248         left  = IC_LEFT(ic);
8249         result = IC_RESULT(ic);
8250         
8251         aopOp(right,ic,FALSE);
8252         aopOp(left,ic,FALSE);
8253         aopOp(result,ic,FALSE);
8254         
8255         /* if the shift count is known then do it 
8256         as efficiently as possible */
8257         if (AOP_TYPE(right) == AOP_LIT) {
8258                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8259                 if (lit < 0)
8260                 {
8261                         lit = -lit;
8262                         shiftRight = !shiftRight;
8263                 }
8264                 
8265                 if (shiftRight)
8266                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8267                 else
8268                         shiftLeft_Left2ResultLit (left, result, lit);
8269                 //genRightShiftLiteral (left,right,result,ic, 0);
8270                 return ;
8271         }
8272         
8273         /* shift count is unknown then we have to form 
8274         a loop get the loop count in B : Note: we take
8275         only the lower order byte since shifting
8276         more that 32 bits make no sense anyway, ( the
8277         largest size of an object can be only 32 bits ) */  
8278
8279         /* we must not overwrite the shift counter */
8280         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8281         
8282         /* now move the left to the result if they are not the
8283         same */
8284         if (!pic14_sameRegs(AOP(left),AOP(result)))
8285         {
8286                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8287                 while (size--) {
8288                         mov2w(AOP(left), size);
8289                         movwf(AOP(result), size);
8290                 }
8291                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8292         }
8293         
8294         tlbl = newiTempLabel(NULL);
8295         tlbl1= newiTempLabel(NULL);
8296         inverselbl = NULL;
8297         size = AOP_SIZE(result);
8298
8299         mov2w(AOP(right),0);
8300         if (!SPEC_USIGN(operandType(right)))
8301         {
8302                 inverselbl = newiTempLabel(NULL);
8303                 /* signed shift count -- invert shift direction for c<0 */
8304                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8305                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8306         } // if
8307         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8308         /* check for `a = b >> c' with `-c == 0' */
8309         emitSKPNZ;
8310         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8311         emitpLabel(tlbl->key);
8312         /* propagate the sign bit inwards for SIGNED result */
8313         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8314         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8315         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8316         emitSKPC;
8317         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8318
8319         if (!SPEC_USIGN(operandType(right)))
8320         {
8321                 symbol *inv_loop = newiTempLabel(NULL);
8322
8323                 shiftRight = !shiftRight;       /* invert shift direction */
8324                 
8325                 /* we came here from the code above -- we are done */
8326                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8327                 
8328                 /* emit code for shifting N<0 steps, count is already in W */
8329                 emitpLabel(inverselbl->key);
8330                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8331                 emitpLabel(inv_loop->key);
8332                 /* propagate the sign bit inwards for SIGNED result */
8333                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8334                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8335                 emitpcode(POC_ADDLW, popGetLit(1));
8336                 emitSKPC;
8337                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8338         } // if
8339         
8340         emitpLabel(tlbl1->key);
8341         
8342         freeAsmop(left,NULL,ic,TRUE);
8343         freeAsmop (right,NULL,ic,TRUE);
8344         freeAsmop(result,NULL,ic,TRUE);
8345 }
8346
8347 static void genRightShift (iCode *ic)
8348 {
8349         genGenericShift(ic, 1);
8350 }
8351
8352 static void genLeftShift (iCode *ic)
8353 {
8354         genGenericShift(ic, 0);
8355 }
8356
8357 /*-----------------------------------------------------------------*/
8358 /* SetIrp - Set IRP bit                                            */
8359 /*-----------------------------------------------------------------*/
8360 void SetIrp(operand *result) {
8361         FENTRY;
8362         if (AOP_TYPE(result) == AOP_LIT) {
8363                 unsigned lit = (unsigned)operandLitValue(result);
8364                 if (lit&0x100)
8365                         emitSETIRP;
8366                 else
8367                         emitCLRIRP;
8368         } else {
8369                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8370                         int addrs = PCOL(AOP(result))->lit;
8371                         if (addrs & 0x100)
8372                                 emitSETIRP;
8373                         else
8374                                 emitCLRIRP;
8375                 } else {
8376                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8377                         if(AOP_SIZE(result) > 1) {
8378                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8379                                 emitSETIRP;
8380                         }
8381                 }
8382         }
8383 }
8384
8385 static void
8386 setup_fsr (operand *ptr)
8387 {
8388   mov2w_op(ptr, 0);
8389   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8390
8391   /* also setup-up IRP */
8392   SetIrp (ptr);
8393 }
8394
8395 /*-----------------------------------------------------------------*/
8396 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8397 /*                  arbitrary pointer (__code, __data, generic)    */
8398 /*-----------------------------------------------------------------*/
8399 static void
8400 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8401 {
8402     FENTRY;
8403     switch (p_type)
8404     {
8405     case POINTER:
8406     case FPOINTER:
8407       if (!alreadyAddressed) setup_fsr (src);
8408       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8409       break;
8410     
8411     case CPOINTER:
8412       assert( AOP_SIZE(src) == 2 );
8413       mov2w_op(src, 0);
8414       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8415       mov2w_op(src, 1);
8416       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8417       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8418       call_libraryfunc ("__gptrget1");
8419       break;
8420     
8421     case GPOINTER:
8422       assert( AOP_SIZE(src) == 3 );
8423       mov2w_op(src, 0);
8424       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8425       mov2w_op(src, 1);
8426       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8427       mov2w_op(src, 2);
8428       call_libraryfunc ("__gptrget1");
8429       break;
8430     
8431     default:
8432       assert( !"unhandled pointer type" );
8433       break;
8434     }
8435 }
8436
8437 /*-----------------------------------------------------------------*/
8438 /* emitPtrByteSet - emits code to set a byte from src through a    */
8439 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8440 /*-----------------------------------------------------------------*/
8441 static void
8442 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8443 {
8444     FENTRY;
8445     switch (p_type)
8446     {
8447     case POINTER:
8448     case FPOINTER:
8449       if (!alreadyAddressed) setup_fsr (dst);
8450       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8451       break;
8452     
8453     case CPOINTER:
8454       assert( !"trying to assign to __code pointer" );
8455       break;
8456     
8457     case GPOINTER:
8458       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8459       mov2w_op(dst, 0);
8460       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8461       mov2w_op(dst, 1);
8462       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8463       mov2w_op(dst, 2);
8464       call_libraryfunc ("__gptrput1");
8465       break;
8466
8467     default:
8468       assert( !"unhandled pointer type" );
8469       break;
8470     }
8471 }
8472
8473 /*-----------------------------------------------------------------*/
8474 /* genUnpackBits - generates code for unpacking bits               */
8475 /*-----------------------------------------------------------------*/
8476 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8477 {    
8478   int rsize;            /* result size */
8479   sym_link *etype;      /* bitfield type information */
8480   int blen;             /* bitfield length */
8481   int bstr;             /* bitfield starting bit within byte */
8482
8483   FENTRY;
8484   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8485   etype = getSpec(operandType(result));
8486   rsize = getSize (operandType (result));
8487   blen = SPEC_BLEN (etype);
8488   bstr = SPEC_BSTR (etype);
8489
8490   /* single bit field case */
8491   if (blen == 1) {
8492     if (ifx) { /* that is for an if statement */
8493       pCodeOp *pcop;
8494       resolvedIfx rIfx;
8495       resolveIfx(&rIfx,ifx);
8496       if (ptype == -1) /* direct */
8497         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8498       else
8499         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8500       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8501       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8502       ifx->generated=1;
8503     } else {
8504       int i;
8505       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8506       for (i=0; i < AOP_SIZE(result); i++)
8507         emitpcode (POC_CLRF, popGet (AOP(result), i));
8508
8509       switch (ptype)
8510       {
8511       case -1:
8512         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8513         /* adjust result below */
8514         break;
8515         
8516       case POINTER:
8517       case FPOINTER:
8518       case GPOINTER:
8519       case CPOINTER:
8520         emitPtrByteGet (left, ptype, FALSE);
8521         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8522         emitSKPZ;
8523         /* adjust result below */
8524         break;
8525         
8526       default:
8527         assert( !"unhandled pointer type" );
8528       } // switch
8529
8530       /* move sign-/zero extended bit to result */
8531       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8532         emitpcode (POC_INCF, popGet (AOP(result), 0));
8533       } else {
8534         emitpcode (POC_DECF, popGet (AOP(result), 0));
8535       }
8536       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8537     }
8538     return;
8539   }
8540   else if (blen <= 8 && ((blen + bstr) <= 8))
8541   {
8542     /* blen > 1 */
8543     int i;
8544
8545     for (i=0; i < AOP_SIZE(result); i++)
8546       emitpcode (POC_CLRF, popGet (AOP(result), i));
8547
8548     switch (ptype)
8549     {
8550     case -1:
8551       mov2w(AOP(left), 0);
8552       break;
8553       
8554     case POINTER:
8555     case FPOINTER:
8556     case GPOINTER:
8557     case CPOINTER:
8558       emitPtrByteGet (left, ptype, FALSE);
8559       break;
8560       
8561     default:
8562       assert( !"unhandled pointer type" );
8563     } // switch
8564
8565     if (blen < 8)
8566       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8567     movwf(AOP(result), 0);
8568     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8569
8570     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8571     {
8572       /* signed bitfield */
8573       assert (bstr + blen > 0);
8574       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8575       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8576       emitpcode(POC_IORWF, popGet(AOP(result),0));
8577     }
8578     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8579     return;
8580   }
8581
8582   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8583 }
8584
8585 #if 1
8586 /*-----------------------------------------------------------------*/
8587 /* genDataPointerGet - generates code when ptr offset is known     */
8588 /*-----------------------------------------------------------------*/
8589 static void genDataPointerGet (operand *left, 
8590         operand *result, 
8591         iCode *ic)
8592 {
8593         int size , offset = 0;
8594                 
8595         FENTRY;
8596         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8597         
8598         
8599         /* optimization - most of the time, left and result are the same
8600         * address, but different types. for the pic code, we could omit
8601         * the following
8602         */
8603         aopOp(result,ic,TRUE);
8604         
8605         if (pic14_sameRegs (AOP(left), AOP(result)))
8606                 return;
8607         
8608         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8609         
8610         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8611         
8612         size = AOP_SIZE(result);
8613         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8614         
8615         offset = 0;
8616         while (size--) {
8617                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8618                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8619                 offset++;
8620         }
8621         
8622         freeAsmop(left,NULL,ic,TRUE);
8623         freeAsmop(result,NULL,ic,TRUE);
8624 }
8625 #endif
8626
8627 /*-----------------------------------------------------------------*/
8628 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8629 /*-----------------------------------------------------------------*/
8630 static void genNearPointerGet (operand *left, 
8631                                                            operand *result, 
8632                                                            iCode *ic)
8633 {
8634         asmop *aop = NULL;
8635         sym_link *ltype = operandType(left);
8636         sym_link *rtype = operandType(result);
8637         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8638         int direct = 0;
8639
8640         FENTRY;
8641         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8642         
8643         
8644         aopOp(left,ic,FALSE);
8645         
8646         /* if left is rematerialisable and
8647         result is not bit variable type and
8648         the left is pointer to data space i.e
8649         lower 128 bytes of space */
8650         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8651                 !IS_BITVAR(retype)         &&
8652                 PIC_IS_DATA_PTR(ltype)) {
8653                 genDataPointerGet (left,result,ic);
8654                 return ;
8655         }
8656         
8657         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8658         aopOp (result,ic,FALSE);
8659         
8660         /* Check if can access directly instead of via a pointer */
8661         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8662                 && AOP_SIZE(result) == 1)
8663         {
8664                 direct = 1;
8665         }
8666
8667         if (IS_BITFIELD(getSpec(operandType(result)))) 
8668         {
8669                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8670                 goto release;
8671         }
8672         
8673         /* If the pointer value is not in a the FSR then need to put it in */
8674         /* Must set/reset IRP bit for use with FSR. */
8675         if (!direct)
8676           setup_fsr (left);
8677         
8678 //      sym_link *etype;
8679         /* if bitfield then unpack the bits */
8680         {
8681                 /* we have can just get the values */
8682                 int size = AOP_SIZE(result);
8683                 int offset = 0 ;  
8684                 
8685                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8686                 
8687                 while(size--) {
8688                         if (direct)
8689                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8690                         else
8691                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8692                         if (AOP_TYPE(result) == AOP_LIT) {
8693                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8694                         } else {
8695                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8696                         }
8697                         if (size && !direct)
8698                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8699                         offset++;
8700                 }
8701         }
8702         
8703         /* now some housekeeping stuff */
8704         if (aop) {
8705                 /* we had to allocate for this iCode */
8706                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8707                 freeAsmop(NULL,aop,ic,TRUE);
8708         } else { 
8709                 /* we did not allocate which means left
8710                 already in a pointer register, then
8711                 if size > 0 && this could be used again
8712                 we have to point it back to where it 
8713                 belongs */
8714                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8715                 if (AOP_SIZE(result) > 1 &&
8716                         !OP_SYMBOL(left)->remat &&
8717                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8718                         ic->depth )) {
8719                         int size = AOP_SIZE(result) - 1;
8720                         while (size--)
8721                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8722                 }
8723         }
8724         
8725 release:
8726         /* done */
8727         freeAsmop(left,NULL,ic,TRUE);
8728         freeAsmop(result,NULL,ic,TRUE);
8729
8730 }
8731
8732 #if 0
8733 /*-----------------------------------------------------------------*/
8734 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8735 /*-----------------------------------------------------------------*/
8736 static void genPagedPointerGet (operand *left, 
8737                                                                 operand *result, 
8738                                                                 iCode *ic)
8739 {
8740         asmop *aop = NULL;
8741         regs *preg = NULL ;
8742         char *rname ;
8743         sym_link *rtype, *retype;    
8744         
8745         FENTRY;
8746         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8747         
8748         rtype = operandType(result);
8749         retype= getSpec(rtype);
8750         
8751         aopOp(left,ic,FALSE);
8752         
8753         /* if the value is already in a pointer register
8754         then don't need anything more */
8755         if (!AOP_INPREG(AOP(left))) {
8756                 /* otherwise get a free pointer register */
8757                 aop = newAsmop(0);
8758                 preg = getFreePtr(ic,&aop,FALSE);
8759                 pic14_emitcode("mov","%s,%s",
8760                         preg->name,
8761                         aopGet(AOP(left),0,FALSE,TRUE));
8762                 rname = preg->name ;
8763         } else
8764                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8765         
8766         freeAsmop(left,NULL,ic,TRUE);
8767         aopOp (result,ic,FALSE);
8768         
8769         /* if bitfield then unpack the bits */
8770         if (IS_BITFIELD(retype)) 
8771                 genUnpackBits (result,left,rname,PPOINTER,0);
8772         else {
8773                 /* we have can just get the values */
8774                 int size = AOP_SIZE(result);
8775                 int offset = 0 ;  
8776                 
8777                 while (size--) {
8778                         
8779                         pic14_emitcode("movx","a,@%s",rname);
8780                         aopPut(AOP(result),"a",offset);
8781                         
8782                         offset++ ;
8783                         
8784                         if (size)
8785                                 pic14_emitcode("inc","%s",rname);
8786                 }
8787         }
8788         
8789         /* now some housekeeping stuff */
8790         if (aop) {
8791                 /* we had to allocate for this iCode */
8792                 freeAsmop(NULL,aop,ic,TRUE);
8793         } else { 
8794         /* we did not allocate which means left
8795         already in a pointer register, then
8796         if size > 0 && this could be used again
8797         we have to point it back to where it 
8798                 belongs */
8799                 if (AOP_SIZE(result) > 1 &&
8800                         !OP_SYMBOL(left)->remat &&
8801                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8802                         ic->depth )) {
8803                         int size = AOP_SIZE(result) - 1;
8804                         while (size--)
8805                                 pic14_emitcode("dec","%s",rname);
8806                 }
8807         }
8808         
8809         /* done */
8810         freeAsmop(result,NULL,ic,TRUE);
8811         
8812         
8813 }
8814
8815 /*-----------------------------------------------------------------*/
8816 /* genFarPointerGet - gget value from far space                    */
8817 /*-----------------------------------------------------------------*/
8818 static void genFarPointerGet (operand *left,
8819                                                           operand *result, iCode *ic)
8820 {
8821         int size, offset ;
8822         sym_link *retype = getSpec(operandType(result));
8823         
8824         FENTRY;
8825         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8826         
8827         aopOp(left,ic,FALSE);
8828         
8829         /* if the operand is already in dptr 
8830         then we do nothing else we move the value to dptr */
8831         if (AOP_TYPE(left) != AOP_STR) {
8832                 /* if this is remateriazable */
8833                 if (AOP_TYPE(left) == AOP_IMMD)
8834                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8835                 else { /* we need to get it byte by byte */
8836                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8837                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8838                         if (options.model == MODEL_FLAT24)
8839                         {
8840                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8841                         }
8842                 }
8843         }
8844         /* so dptr know contains the address */
8845         freeAsmop(left,NULL,ic,TRUE);
8846         aopOp(result,ic,FALSE);
8847         
8848         /* if bit then unpack */
8849         if (IS_BITFIELD(retype)) 
8850                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8851         else {
8852                 size = AOP_SIZE(result);
8853                 offset = 0 ;
8854                 
8855                 while (size--) {
8856                         pic14_emitcode("movx","a,@dptr");
8857                         aopPut(AOP(result),"a",offset++);
8858                         if (size)
8859                                 pic14_emitcode("inc","dptr");
8860                 }
8861         }
8862         
8863         freeAsmop(result,NULL,ic,TRUE);
8864 }
8865 #endif
8866
8867 #if 0
8868 /*-----------------------------------------------------------------*/
8869 /* genCodePointerGet - get value from code space                  */
8870 /*-----------------------------------------------------------------*/
8871 static void genCodePointerGet (operand *left,
8872                                                            operand *result, iCode *ic)
8873 {
8874         int size, offset ;
8875         sym_link *retype = getSpec(operandType(result));
8876         
8877         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8878         
8879         aopOp(left,ic,FALSE);
8880         
8881         /* if the operand is already in dptr 
8882         then we do nothing else we move the value to dptr */
8883         if (AOP_TYPE(left) != AOP_STR) {
8884                 /* if this is remateriazable */
8885                 if (AOP_TYPE(left) == AOP_IMMD)
8886                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8887                 else { /* we need to get it byte by byte */
8888                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8889                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8890                         if (options.model == MODEL_FLAT24)
8891                         {
8892                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8893                         }
8894                 }
8895         }
8896         /* so dptr know contains the address */
8897         freeAsmop(left,NULL,ic,TRUE);
8898         aopOp(result,ic,FALSE);
8899         
8900         /* if bit then unpack */
8901         if (IS_BITFIELD(retype)) 
8902                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8903         else {
8904                 size = AOP_SIZE(result);
8905                 offset = 0 ;
8906                 
8907                 while (size--) {
8908                         pic14_emitcode("clr","a");
8909                         pic14_emitcode("movc","a,@a+dptr");
8910                         aopPut(AOP(result),"a",offset++);
8911                         if (size)
8912                                 pic14_emitcode("inc","dptr");
8913                 }
8914         }
8915         
8916         freeAsmop(result,NULL,ic,TRUE);
8917 }
8918 #endif
8919 /*-----------------------------------------------------------------*/
8920 /* genGenPointerGet - gget value from generic pointer space        */
8921 /*-----------------------------------------------------------------*/
8922 static void genGenPointerGet (operand *left,
8923                                                           operand *result, iCode *ic)
8924 {
8925         FENTRY;
8926         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8927         aopOp(left,ic,FALSE);
8928         aopOp(result,ic,FALSE);
8929         
8930         
8931         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8932
8933         if (IS_BITFIELD(getSpec(operandType(result))))
8934         {
8935           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8936           return;
8937         }
8938
8939         {
8940           /* emit call to __gptrget */
8941           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
8942           int size = AOP_SIZE(result);
8943           int idx = 0;
8944
8945           assert (size > 0 && size <= 4);
8946
8947           /* pass arguments */
8948           assert (AOP_SIZE(left) == 3);
8949           mov2w(AOP(left), 0);
8950           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8951           mov2w(AOP(left), 1);
8952           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8953           mov2w(AOP(left), 2);
8954           call_libraryfunc (func[size]);
8955           
8956           /* save result */
8957           movwf (AOP(result), --size);
8958           while (size--) {
8959             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
8960             movwf (AOP(result), size);
8961           } // while
8962         }
8963         
8964         freeAsmop(left,NULL,ic,TRUE);
8965         freeAsmop(result,NULL,ic,TRUE);
8966         
8967 }
8968
8969 /*-----------------------------------------------------------------*/
8970 /* genConstPointerGet - get value from const generic pointer space */
8971 /*-----------------------------------------------------------------*/
8972 static void genConstPointerGet (operand *left,
8973                                                                 operand *result, iCode *ic)
8974 {
8975         //sym_link *retype = getSpec(operandType(result));
8976         #if 0
8977         symbol *albl, *blbl;//, *clbl;
8978         pCodeOp *pcop;
8979         #endif
8980         PIC_OPCODE poc;
8981         int i, size, lit;
8982         
8983         FENTRY;
8984         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8985         aopOp(left,ic,FALSE);
8986         aopOp(result,ic,FALSE);
8987         
8988         size = AOP_SIZE(result);
8989         
8990         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8991         
8992         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8993
8994         lit = op_isLitLike (left);
8995         poc = lit ? POC_MOVLW : POC_MOVFW;
8996
8997         if (IS_BITFIELD(getSpec(operandType(result))))
8998         {
8999                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9000                 goto release;
9001         }
9002
9003         {
9004                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9005                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9006                 assert (size > 0 && size <= 4);
9007                 
9008                 mov2w_op(left, 0);
9009                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9010                 mov2w_op(left, 1);
9011                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9012                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9013                 call_libraryfunc (func[size]);
9014
9015                 movwf(AOP(result),size-1);
9016                 for (i = 1; i < size; i++)
9017                 {
9018                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9019                         movwf(AOP(result),size - 1 - i);
9020                 } // for
9021         }
9022         
9023 release:
9024         freeAsmop(left,NULL,ic,TRUE);
9025         freeAsmop(result,NULL,ic,TRUE);
9026         
9027 }
9028 /*-----------------------------------------------------------------*/
9029 /* genPointerGet - generate code for pointer get                   */
9030 /*-----------------------------------------------------------------*/
9031 static void genPointerGet (iCode *ic)
9032 {
9033         operand *left, *result ;
9034         sym_link *type, *etype;
9035         int p_type = -1;
9036         
9037         FENTRY;
9038         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9039         
9040         left = IC_LEFT(ic);
9041         result = IC_RESULT(ic) ;
9042         
9043         /* depending on the type of pointer we need to
9044         move it to the correct pointer register */
9045         type = operandType(left);
9046         etype = getSpec(type);
9047         
9048         if (IS_PTR_CONST(type))
9049                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9050         
9051         /* if left is of type of pointer then it is simple */
9052         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9053                 p_type = DCL_TYPE(type);
9054         else {
9055                 /* we have to go by the storage class */
9056                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9057                 
9058                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9059                 
9060                 if (SPEC_OCLS(etype)->codesp ) {
9061                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9062                         //p_type = CPOINTER ; 
9063                 }
9064                 else
9065                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9066                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9067                         /*p_type = FPOINTER ;*/ 
9068                         else
9069                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9070                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9071                                 /*        p_type = PPOINTER; */
9072                                 else
9073                                         if (SPEC_OCLS(etype) == idata )
9074                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9075                                         /*      p_type = IPOINTER; */
9076                                         else
9077                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9078                                         /*      p_type = POINTER ; */
9079         }
9080         
9081         /* now that we have the pointer type we assign
9082         the pointer values */
9083         switch (p_type) {
9084                 
9085         case POINTER: 
9086         case FPOINTER:
9087         //case IPOINTER:
9088                 genNearPointerGet (left,result,ic);
9089                 break;
9090 /*
9091         case PPOINTER:
9092                 genPagedPointerGet(left,result,ic);
9093                 break;
9094                 
9095         case FPOINTER:
9096                 genFarPointerGet (left,result,ic);
9097                 break;
9098 */              
9099         case CPOINTER:
9100                 genConstPointerGet (left,result,ic);
9101                 break;
9102                 
9103         case GPOINTER:
9104                 genGenPointerGet (left,result,ic);
9105                 break;
9106         default:
9107                 assert ( !"unhandled pointer type" );
9108                 break;
9109         }
9110         
9111 }
9112
9113 /*-----------------------------------------------------------------*/
9114 /* genPackBits - generates code for packed bit storage             */
9115 /*-----------------------------------------------------------------*/
9116 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9117 {
9118   int blen;             /* bitfield length */
9119   int bstr;             /* bitfield starting bit within byte */
9120   int litval;           /* source literal value (if AOP_LIT) */
9121   unsigned char mask;   /* bitmask within current byte */
9122
9123   FENTRY;
9124   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9125
9126   blen = SPEC_BLEN (etype);
9127   bstr = SPEC_BSTR (etype);
9128
9129   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9130   if ((blen <= 8) && ((bstr + blen) <= 8))
9131   {
9132     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9133             (unsigned char) (0xFF >> (8 - bstr)));
9134
9135     if (AOP_TYPE (right) == AOP_LIT)
9136     {
9137       /* Case with a bitfield length <8 and literal source */
9138       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9139       if (blen == 1) {
9140         pCodeOp *pcop;
9141         
9142         switch (p_type)
9143         {
9144         case -1:
9145           if (AOP(result)->type == AOP_PCODE)
9146             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9147           else
9148             pcop = popGet(AOP(result),0);
9149           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9150           break;
9151         
9152         case POINTER:
9153         case FPOINTER:
9154           setup_fsr (result);
9155           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9156           break;
9157         
9158         case CPOINTER:
9159           assert( !"trying to assign to bitfield via pointer to __code space" );
9160           break;
9161         
9162         case GPOINTER:
9163           emitPtrByteGet(result, p_type, FALSE);
9164           if (lit) {
9165             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9166           } else {
9167             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9168           }
9169           emitPtrByteSet(result, p_type, TRUE);
9170           break;
9171         
9172         default:
9173           assert( !"unhandled pointer type" );
9174           break;
9175         } // switch (p_type)
9176       } else {
9177         /* blen > 1 */
9178         litval = lit << bstr;
9179         litval &= (~mask) & 0x00ff;
9180         
9181         switch (p_type)
9182         {
9183         case -1:
9184           mov2w (AOP(result), 0);
9185           if ((litval|mask) != 0x00ff)
9186             emitpcode(POC_ANDLW, popGetLit (mask));
9187           if (litval != 0x00)
9188             emitpcode(POC_IORLW, popGetLit (litval));
9189           movwf (AOP(result), 0);
9190           break;
9191         
9192         case POINTER:
9193         case FPOINTER:
9194         case GPOINTER:
9195           emitPtrByteGet(result, p_type, FALSE);
9196           if ((litval|mask) != 0x00ff)
9197             emitpcode(POC_ANDLW, popGetLit (mask));
9198           if (litval != 0x00)
9199             emitpcode(POC_IORLW, popGetLit (litval));
9200           emitPtrByteSet(result, p_type, TRUE);
9201           break;
9202         
9203         case CPOINTER:
9204           assert( !"trying to assign to bitfield via pointer to __code space" );
9205           break;
9206         
9207         default:
9208           assert( !"unhandled pointer type" );
9209           break;
9210         } // switch
9211       } // if (blen > 1)
9212     }
9213     else
9214     {
9215       /* right is no literal */
9216       if (blen==1) {
9217         switch (p_type)
9218         {
9219         case -1:
9220           /* Note more efficient code, of pre clearing bit then only setting it if required,
9221            * can only be done if it is known that the result is not a SFR */
9222           emitpcode(POC_RRFW,popGet(AOP(right),0));
9223           emitSKPC;
9224           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9225           emitSKPNC;
9226           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9227           break;
9228         
9229         case POINTER:
9230         case FPOINTER:
9231         case GPOINTER:
9232           emitPtrByteGet (result, p_type, FALSE);
9233           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9234           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9235           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9236           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9237           emitPtrByteSet (result, p_type, TRUE);
9238           break;
9239         
9240         case CPOINTER:
9241           assert( !"trying to assign to bitfield via pointer to __code space" );
9242           break;
9243         
9244         default:
9245           assert( !"unhandled pointer type" );
9246           break;
9247         } // switch
9248         return;
9249       } else {
9250         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9251         pCodeOp *temp = popGetTempReg ();
9252
9253         mov2w (AOP(right), 0);
9254         if (blen < 8) {
9255           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9256         }
9257         emitpcode(POC_MOVWF, temp);
9258         if (bstr) {
9259           AccLsh (temp, bstr);
9260         }
9261         
9262         switch (p_type)
9263         {
9264         case -1:
9265           mov2w (AOP(result), 0);
9266           emitpcode(POC_ANDLW, popGetLit (mask));
9267           emitpcode(POC_IORFW, temp);
9268           movwf (AOP(result), 0);
9269           break;
9270         
9271         case POINTER:
9272         case FPOINTER:
9273         case GPOINTER:
9274           emitPtrByteGet (result, p_type, FALSE);
9275           emitpcode(POC_ANDLW, popGetLit (mask));
9276           emitpcode(POC_IORFW, temp);
9277           emitPtrByteSet (result, p_type, TRUE);
9278           break;
9279         
9280         case CPOINTER:
9281           assert( !"trying to assign to bitfield via pointer to __code space" );
9282           break;
9283         
9284         default:
9285           assert( !"unhandled pointer type" );
9286           break;
9287         } // switch
9288
9289         popReleaseTempReg (temp);
9290       } // if (blen > 1)
9291     } // if (AOP(right)->type != AOP_LIT)
9292     return;
9293   } // if (blen <= 8 && ((blen + bstr) <= 8))
9294
9295   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9296 }
9297
9298 /*-----------------------------------------------------------------*/
9299 /* genDataPointerSet - remat pointer to data space                 */
9300 /*-----------------------------------------------------------------*/
9301 static void genDataPointerSet(operand *right,
9302         operand *result,
9303         iCode *ic)
9304 {
9305         int size, offset = 0 ;
9306         int ressize;
9307         
9308         FENTRY;
9309         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9310         aopOp(right,ic,FALSE);
9311         aopOp(result,ic,FALSE);
9312         
9313         assert (IS_SYMOP(result));
9314         assert (IS_PTR(OP_SYM_TYPE(result)));
9315         
9316         if (AOP_TYPE(right) == AOP_LIT)
9317           size = 4;
9318         else
9319           size = AOP_SIZE(right);
9320         ressize = getSize(OP_SYM_ETYPE(result));
9321         if (size > ressize) size = ressize;
9322         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9323         
9324         //assert( !"what's going on here?" );
9325
9326         /*
9327         if ( AOP_TYPE(result) == AOP_PCODE) {
9328         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9329         AOP(result)->aopu.pcop->name,
9330         PCOI(AOP(result)->aopu.pcop)->offset);
9331         }
9332         */
9333         
9334         // tsd, was l+1 - the underline `_' prefix was being stripped
9335         while (size--) {
9336                 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9337                 
9338                 if (AOP_TYPE(right) == AOP_LIT) {
9339                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9340                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9341                         if(lit&0xff) {
9342                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9343                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9344                         } else {
9345                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9346                         }
9347                 } else {
9348                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9349                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9350                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9351                 }
9352                 
9353                 offset++;
9354         }
9355         
9356         freeAsmop(right,NULL,ic,TRUE);
9357         freeAsmop(result,NULL,ic,TRUE);
9358 }
9359
9360 /*-----------------------------------------------------------------*/
9361 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9362 /*-----------------------------------------------------------------*/
9363 static void genNearPointerSet (operand *right,
9364                                                            operand *result, 
9365                                                            iCode *ic)
9366 {
9367         asmop *aop = NULL;
9368         sym_link *ptype = operandType(result);
9369         sym_link *retype = getSpec(operandType(right));
9370         sym_link *letype = getSpec(ptype);
9371         int direct = 0;
9372         
9373         
9374         FENTRY;
9375         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9376         aopOp(result,ic,FALSE);
9377         
9378 #if 1
9379         /* if the result is rematerializable &
9380         in data space & not a bit variable */
9381         //if (AOP_TYPE(result) == AOP_IMMD &&
9382         if (AOP_TYPE(result) == AOP_PCODE &&
9383                 PIC_IS_DATA_PTR(ptype) &&
9384                 !IS_BITVAR (retype) &&
9385                 !IS_BITVAR (letype)) {
9386                 genDataPointerSet (right,result,ic);
9387                 freeAsmop(result,NULL,ic,TRUE);
9388                 return;
9389         }
9390 #endif
9391
9392         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9393         aopOp(right,ic,FALSE);
9394         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9395         
9396         /* Check if can access directly instead of via a pointer */
9397         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9398                 direct = 1;
9399         }
9400         
9401         if (IS_BITFIELD (letype))
9402         {
9403           genPackBits (letype, result, right, direct?-1:POINTER);
9404           return;
9405         }
9406         
9407         /* If the pointer value is not in a the FSR then need to put it in */
9408         /* Must set/reset IRP bit for use with FSR. */
9409         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9410         if (!direct)
9411                 setup_fsr (result);
9412
9413         {
9414                 /* we have can just get the values */
9415                 int size = AOP_SIZE(right);
9416                 int offset = 0 ;    
9417                 
9418                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9419                 while (size--) {
9420                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9421                         if (*l == '@' ) {
9422                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9423                         } else {
9424                                 if (AOP_TYPE(right) == AOP_LIT) {
9425                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9426                                 } else {
9427                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9428                                 }
9429                                 if (direct)
9430                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9431                                 else
9432                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9433                         }
9434                         if (size && !direct)
9435                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9436                         offset++;
9437                 }
9438         }
9439         
9440         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9441         /* now some housekeeping stuff */
9442         if (aop) {
9443                 /* we had to allocate for this iCode */
9444                 freeAsmop(NULL,aop,ic,TRUE);
9445         } else { 
9446                 /* we did not allocate which means left
9447                 already in a pointer register, then
9448                 if size > 0 && this could be used again
9449                 we have to point it back to where it 
9450                 belongs */
9451                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9452                 if (AOP_SIZE(right) > 1 &&
9453                         !OP_SYMBOL(result)->remat &&
9454                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9455                         ic->depth )) {
9456                         int size = AOP_SIZE(right) - 1;
9457                         while (size--)
9458                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9459                 }
9460         }
9461         
9462         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9463         /* done */
9464
9465         freeAsmop(right,NULL,ic,TRUE);
9466         freeAsmop(result,NULL,ic,TRUE);
9467 }
9468
9469 #if 0
9470 /*-----------------------------------------------------------------*/
9471 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9472 /*-----------------------------------------------------------------*/
9473 static void genPagedPointerSet (operand *right,
9474                                                                 operand *result, 
9475                                                                 iCode *ic)
9476 {
9477         asmop *aop = NULL;
9478         regs *preg = NULL ;
9479         char *rname , *l;
9480         sym_link *retype;
9481         
9482         FENTRY;
9483         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9484         
9485         retype= getSpec(operandType(right));
9486         
9487         aopOp(result,ic,FALSE);
9488         
9489         /* if the value is already in a pointer register
9490         then don't need anything more */
9491         if (!AOP_INPREG(AOP(result))) {
9492                 /* otherwise get a free pointer register */
9493                 aop = newAsmop(0);
9494                 preg = getFreePtr(ic,&aop,FALSE);
9495                 pic14_emitcode("mov","%s,%s",
9496                         preg->name,
9497                         aopGet(AOP(result),0,FALSE,TRUE));
9498                 rname = preg->name ;
9499         } else
9500                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9501         
9502         freeAsmop(result,NULL,ic,TRUE);
9503         aopOp (right,ic,FALSE);
9504         
9505         /* if bitfield then unpack the bits */
9506         if (IS_BITFIELD(retype)) 
9507                 genPackBits (retype,result,right,rname,PPOINTER);
9508         else {
9509                 /* we have can just get the values */
9510                 int size = AOP_SIZE(right);
9511                 int offset = 0 ;  
9512                 
9513                 while (size--) {
9514                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9515                         
9516                         MOVA(l);
9517                         pic14_emitcode("movx","@%s,a",rname);
9518                         
9519                         if (size)
9520                                 pic14_emitcode("inc","%s",rname);
9521                         
9522                         offset++;
9523                 }
9524         }
9525         
9526         /* now some housekeeping stuff */
9527         if (aop) {
9528                 /* we had to allocate for this iCode */
9529                 freeAsmop(NULL,aop,ic,TRUE);
9530         } else { 
9531         /* we did not allocate which means left
9532         already in a pointer register, then
9533         if size > 0 && this could be used again
9534         we have to point it back to where it 
9535                 belongs */
9536                 if (AOP_SIZE(right) > 1 &&
9537                         !OP_SYMBOL(result)->remat &&
9538                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9539                         ic->depth )) {
9540                         int size = AOP_SIZE(right) - 1;
9541                         while (size--)
9542                                 pic14_emitcode("dec","%s",rname);
9543                 }
9544         }
9545         
9546         /* done */
9547         freeAsmop(right,NULL,ic,TRUE);
9548         
9549         
9550 }
9551
9552 /*-----------------------------------------------------------------*/
9553 /* genFarPointerSet - set value from far space                     */
9554 /*-----------------------------------------------------------------*/
9555 static void genFarPointerSet (operand *right,
9556                                                           operand *result, iCode *ic)
9557 {
9558         int size, offset ;
9559         sym_link *retype = getSpec(operandType(right));
9560         
9561         FENTRY;
9562         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9563         aopOp(result,ic,FALSE);
9564         
9565         /* if the operand is already in dptr 
9566         then we do nothing else we move the value to dptr */
9567         if (AOP_TYPE(result) != AOP_STR) {
9568                 /* if this is remateriazable */
9569                 if (AOP_TYPE(result) == AOP_IMMD)
9570                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9571                 else { /* we need to get it byte by byte */
9572                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9573                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9574                         if (options.model == MODEL_FLAT24)
9575                         {
9576                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9577                         }
9578                 }
9579         }
9580         /* so dptr know contains the address */
9581         freeAsmop(result,NULL,ic,TRUE);
9582         aopOp(right,ic,FALSE);
9583         
9584         /* if bit then unpack */
9585         if (IS_BITFIELD(retype)) 
9586                 genPackBits(retype,result,right,"dptr",FPOINTER);
9587         else {
9588                 size = AOP_SIZE(right);
9589                 offset = 0 ;
9590                 
9591                 while (size--) {
9592                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9593                         MOVA(l);
9594                         pic14_emitcode("movx","@dptr,a");
9595                         if (size)
9596                                 pic14_emitcode("inc","dptr");
9597                 }
9598         }
9599         
9600         freeAsmop(right,NULL,ic,TRUE);
9601 }
9602 #endif
9603
9604 /*-----------------------------------------------------------------*/
9605 /* genGenPointerSet - set value from generic pointer space         */
9606 /*-----------------------------------------------------------------*/
9607 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9608 {
9609         sym_link *retype = getSpec(operandType(result));
9610         
9611         FENTRY;
9612         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9613         aopOp(right,ic,FALSE);
9614         aopOp(result,ic,FALSE);
9615
9616         
9617         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9618
9619         if (IS_BITFIELD(retype))
9620         {
9621           genPackBits (retype, result, right, GPOINTER);
9622           return;
9623         }
9624
9625         {
9626           /* emit call to __gptrput */
9627           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9628           int size = AOP_SIZE(right);
9629           int idx = 0;
9630
9631           assert (size == getSize(OP_SYM_ETYPE(result)));
9632           assert (size > 0 && size <= 4);
9633
9634           /* pass arguments */
9635           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9636           {
9637             int off = size;
9638             idx = 2;
9639             while (off--)
9640             {
9641               mov2w_op (right, off);
9642               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9643             }
9644             idx = 0;
9645           }
9646           /* - address */
9647           assert (AOP_SIZE(result) == 3);
9648           mov2w(AOP(result), 0);
9649           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9650           mov2w(AOP(result), 1);
9651           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9652           mov2w(AOP(result), 2);
9653           call_libraryfunc (func[size]);
9654         }
9655         
9656         freeAsmop(right,NULL,ic,TRUE);
9657         freeAsmop(result,NULL,ic,TRUE);
9658 }
9659
9660 /*-----------------------------------------------------------------*/
9661 /* genPointerSet - stores the value into a pointer location        */
9662 /*-----------------------------------------------------------------*/
9663 static void genPointerSet (iCode *ic)
9664 {    
9665         operand *right, *result ;
9666         sym_link *type, *etype;
9667         int p_type;
9668         
9669         FENTRY;
9670         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9671         
9672         right = IC_RIGHT(ic);
9673         result = IC_RESULT(ic) ;
9674         
9675         /* depending on the type of pointer we need to
9676         move it to the correct pointer register */
9677         type = operandType(result);
9678         etype = getSpec(type);
9679         /* if left is of type of pointer then it is simple */
9680         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9681                 p_type = DCL_TYPE(type);
9682         }
9683         else {
9684                 /* we have to go by the storage class */
9685                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9686                 
9687                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9688                 /*      p_type = CPOINTER ;  */
9689                 /*  } */
9690                 /*  else */
9691                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9692                 /*    p_type = FPOINTER ; */
9693                 /*      else */
9694                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9695                 /*        p_type = PPOINTER ; */
9696                 /*    else */
9697                 /*        if (SPEC_OCLS(etype) == idata ) */
9698                 /*      p_type = IPOINTER ; */
9699                 /*        else */
9700                 /*      p_type = POINTER ; */
9701         }
9702         
9703         /* now that we have the pointer type we assign
9704         the pointer values */
9705         switch (p_type) {
9706                 
9707         case POINTER:
9708         case FPOINTER:
9709         //case IPOINTER:
9710                 genNearPointerSet (right,result,ic);
9711                 break;
9712 /*
9713         case PPOINTER:
9714                 genPagedPointerSet (right,result,ic);
9715                 break;
9716                 
9717         case FPOINTER:
9718                 genFarPointerSet (right,result,ic);
9719                 break;
9720 */
9721         case GPOINTER:
9722                 genGenPointerSet (right,result,ic);
9723                 break;
9724                 
9725         default:
9726                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9727                         "genPointerSet: illegal pointer type");
9728         }
9729 }
9730
9731 /*-----------------------------------------------------------------*/
9732 /* genIfx - generate code for Ifx statement                        */
9733 /*-----------------------------------------------------------------*/
9734 static void genIfx (iCode *ic, iCode *popIc)
9735 {
9736         operand *cond = IC_COND(ic);
9737         int isbit =0;
9738         
9739         FENTRY;
9740         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9741         
9742         aopOp(cond,ic,FALSE);
9743         
9744         /* get the value into acc */
9745         if (AOP_TYPE(cond) != AOP_CRY)
9746                 pic14_toBoolean(cond);
9747         else
9748                 isbit = 1;
9749         
9750         /* if there was something to be popped then do it */
9751         if (popIc)
9752                 genIpop(popIc);
9753         
9754         if (isbit)
9755         {
9756                 /* This assumes that CARRY is set iff cond is true */
9757                 if (IC_TRUE(ic))
9758                 {
9759                         assert (!IC_FALSE(ic));
9760                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9761                         //emitSKPNC;
9762                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9763                 } else {
9764                         assert (IC_FALSE(ic));
9765                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9766                         //emitSKPC;
9767                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9768                 }
9769                 if (0)
9770                 {
9771                         static int hasWarned = 0;
9772                         if (!hasWarned)
9773                         {
9774                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9775                                 hasWarned = 1;
9776                         }
9777                 }
9778         }
9779         else
9780         {
9781                 /* now Z is set iff !cond */
9782                 if (IC_TRUE(ic))
9783                 {
9784                         assert (!IC_FALSE(ic));
9785                         emitSKPZ;
9786                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9787                 } else {
9788                         emitSKPNZ;
9789                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9790                 }
9791         }
9792         
9793         ic->generated = 1;
9794         
9795         /* the result is now in the accumulator */
9796         freeAsmop(cond,NULL,ic,TRUE);
9797 }
9798
9799 /*-----------------------------------------------------------------*/
9800 /* genAddrOf - generates code for address of                       */
9801 /*-----------------------------------------------------------------*/
9802 static void genAddrOf (iCode *ic)
9803 {
9804         operand *right, *result, *left;
9805         int size, offset ;
9806         
9807         FENTRY;
9808         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9809         
9810         
9811         //aopOp(IC_RESULT(ic),ic,FALSE);
9812         
9813         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9814         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9815         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9816         
9817         DEBUGpic14_AopType(__LINE__,left,right,result);
9818         assert (IS_SYMOP (left));
9819         
9820         /* sanity check: generic pointers to code space are not yet supported,
9821          * pionters to codespace must not be assigned addresses of __data values. */
9822  #if 0
9823         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9824         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)));
9825         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)));
9826         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)));
9827         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)));
9828 #endif
9829
9830         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9831           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9832                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9833                 OP_SYMBOL(left)->name);
9834         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9835           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9836                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9837                 OP_SYMBOL(left)->name);
9838         }
9839         
9840         size = AOP_SIZE(IC_RESULT(ic));
9841         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9842                 /* strip tag */
9843                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9844         }
9845         offset = 0;
9846         
9847         while (size--) {
9848                 /* fixing bug #863624, reported from (errolv) */
9849                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9850                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9851                 
9852 #if 0
9853                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9854                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9855 #endif
9856                 offset++;
9857         }
9858
9859         if (IS_GENPTR(OP_SYM_TYPE(result)))
9860         {
9861                 /* provide correct tag */
9862                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9863                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9864                 movwf (AOP(result), 2);
9865         }
9866         
9867         freeAsmop(left,NULL,ic,FALSE);
9868         freeAsmop(result,NULL,ic,TRUE);
9869         
9870 }
9871
9872 #if 0
9873 /*-----------------------------------------------------------------*/
9874 /* genFarFarAssign - assignment when both are in far space         */
9875 /*-----------------------------------------------------------------*/
9876 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9877 {
9878         int size = AOP_SIZE(right);
9879         int offset = 0;
9880         char *l ;
9881         /* first push the right side on to the stack */
9882         while (size--) {
9883                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9884                 MOVA(l);
9885                 pic14_emitcode ("push","acc");
9886         }
9887         
9888         freeAsmop(right,NULL,ic,FALSE);
9889         /* now assign DPTR to result */
9890         aopOp(result,ic,FALSE);
9891         size = AOP_SIZE(result);
9892         while (size--) {
9893                 pic14_emitcode ("pop","acc");
9894                 aopPut(AOP(result),"a",--offset);
9895         }
9896         freeAsmop(result,NULL,ic,FALSE);
9897         
9898 }
9899 #endif
9900
9901 /*-----------------------------------------------------------------*/
9902 /* genAssign - generate code for assignment                        */
9903 /*-----------------------------------------------------------------*/
9904 static void genAssign (iCode *ic)
9905 {
9906         operand *result, *right;
9907         int size, offset,know_W;
9908         unsigned long lit = 0L;
9909         
9910         result = IC_RESULT(ic);
9911         right  = IC_RIGHT(ic) ;
9912         
9913         FENTRY;
9914         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9915         
9916         /* if they are the same */
9917         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9918                 return ;
9919         
9920         aopOp(right,ic,FALSE);
9921         aopOp(result,ic,TRUE);
9922         
9923         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9924         
9925         /* if they are the same registers */
9926         if (pic14_sameRegs(AOP(right),AOP(result)))
9927                 goto release;
9928
9929         /* special case: assign from __code */
9930         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9931                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9932                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9933                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9934                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9935         {
9936           emitpComment ("genAssign from CODESPACE");
9937           genConstPointerGet (right, result, ic);
9938           goto release;
9939         }
9940         
9941         /* just for symmetry reasons... */
9942         if (!IS_ITEMP(result)
9943                 && IS_SYMOP (result)
9944                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9945         {
9946           assert ( !"cannot write to CODESPACE" );
9947         }
9948
9949         /* if the result is a bit */
9950         if (AOP_TYPE(result) == AOP_CRY) {
9951                 
9952         /* if the right size is a literal then
9953                 we know what the value is */
9954                 if (AOP_TYPE(right) == AOP_LIT) {
9955                         
9956                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9957                                 popGet(AOP(result),0));
9958                         
9959                         if (((int) operandLitValue(right))) 
9960                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9961                                 AOP(result)->aopu.aop_dir,
9962                                 AOP(result)->aopu.aop_dir);
9963                         else
9964                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9965                                 AOP(result)->aopu.aop_dir,
9966                                 AOP(result)->aopu.aop_dir);
9967                         goto release;
9968                 }
9969                 
9970                 /* the right is also a bit variable */
9971                 if (AOP_TYPE(right) == AOP_CRY) {
9972                         emitpcode(POC_BCF,    popGet(AOP(result),0));
9973                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9974                         emitpcode(POC_BSF,    popGet(AOP(result),0));
9975                         
9976                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9977                                 AOP(result)->aopu.aop_dir,
9978                                 AOP(result)->aopu.aop_dir);
9979                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9980                                 AOP(right)->aopu.aop_dir,
9981                                 AOP(right)->aopu.aop_dir);
9982                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9983                                 AOP(result)->aopu.aop_dir,
9984                                 AOP(result)->aopu.aop_dir);
9985                         goto release ;
9986                 }
9987                 
9988                 /* we need to or */
9989                 emitpcode(POC_BCF,    popGet(AOP(result),0));
9990                 pic14_toBoolean(right);
9991                 emitSKPZ;
9992                 emitpcode(POC_BSF,    popGet(AOP(result),0));
9993                 //aopPut(AOP(result),"a",0);
9994                 goto release ;
9995         }
9996         
9997         /* bit variables done */
9998         /* general case */
9999         size = AOP_SIZE(result);
10000         offset = 0 ;
10001         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10002                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10003                 if(aopIdx(AOP(result),0) == 4) {
10004                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10005                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10006                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10007                         goto release;
10008                 } else
10009                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10010         }
10011         
10012         know_W=-1;
10013         while (size--) {
10014         
10015                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10016                 if(AOP_TYPE(right) == AOP_LIT) {
10017                         lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10018                         if(lit&0xff) {
10019                                 if(know_W != (int)(lit&0xff))
10020                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10021                                 know_W = lit&0xff;
10022                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10023                         } else
10024                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10025                         
10026                 } else if (AOP_TYPE(right) == AOP_CRY) {
10027                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10028                         if(offset == 0) {
10029                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10030                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10031                         }
10032                 } else {
10033                         mov2w_op (right, offset);
10034                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10035                 }
10036                 
10037                 offset++;
10038         }
10039         
10040         
10041 release:
10042         freeAsmop (right,NULL,ic,FALSE);
10043         freeAsmop (result,NULL,ic,TRUE);
10044 }   
10045
10046 /*-----------------------------------------------------------------*/
10047 /* genJumpTab - genrates code for jump table                       */
10048 /*-----------------------------------------------------------------*/
10049 static void genJumpTab (iCode *ic)
10050 {
10051         symbol *jtab;
10052         char *l;
10053         
10054         FENTRY;
10055         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10056         
10057         aopOp(IC_JTCOND(ic),ic,FALSE);
10058         /* get the condition into accumulator */
10059         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10060         MOVA(l);
10061         /* multiply by three */
10062         pic14_emitcode("add","a,acc");
10063         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10064         
10065         jtab = newiTempLabel(NULL);
10066         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10067         pic14_emitcode("jmp","@a+dptr");
10068         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10069         
10070         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10071         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10072         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10073         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10074         emitSKPNC;
10075         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10076         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10077         emitpLabel(jtab->key);
10078         
10079         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10080         
10081         /* now generate the jump labels */
10082         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10083         jtab = setNextItem(IC_JTLABELS(ic))) {
10084                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10085                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10086                 
10087         }
10088         
10089 }
10090
10091 /*-----------------------------------------------------------------*/
10092 /* genMixedOperation - gen code for operators between mixed types  */
10093 /*-----------------------------------------------------------------*/
10094 /*
10095 TSD - Written for the PIC port - but this unfortunately is buggy.
10096 This routine is good in that it is able to efficiently promote 
10097 types to different (larger) sizes. Unfortunately, the temporary
10098 variables that are optimized out by this routine are sometimes
10099 used in other places. So until I know how to really parse the 
10100 iCode tree, I'm going to not be using this routine :(.
10101 */
10102 static int genMixedOperation (iCode *ic)
10103 {
10104         FENTRY;
10105 #if 0
10106         operand *result = IC_RESULT(ic);
10107         sym_link *ctype = operandType(IC_LEFT(ic));
10108         operand *right = IC_RIGHT(ic);
10109         int ret = 0;
10110         int big,small;
10111         int offset;
10112         
10113         iCode *nextic;
10114         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10115         
10116         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10117         
10118         nextic = ic->next;
10119         if(!nextic)
10120                 return 0;
10121         
10122         nextright = IC_RIGHT(nextic);
10123         nextleft  = IC_LEFT(nextic);
10124         nextresult = IC_RESULT(nextic);
10125         
10126         aopOp(right,ic,FALSE);
10127         aopOp(result,ic,FALSE);
10128         aopOp(nextright,  nextic, FALSE);
10129         aopOp(nextleft,   nextic, FALSE);
10130         aopOp(nextresult, nextic, FALSE);
10131         
10132         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10133                 
10134                 operand *t = right;
10135                 right = nextright;
10136                 nextright = t; 
10137                 
10138                 pic14_emitcode(";remove right +","");
10139                 
10140         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10141         /*
10142         operand *t = right;
10143         right = nextleft;
10144         nextleft = t; 
10145                 */
10146                 pic14_emitcode(";remove left +","");
10147         } else
10148                 return 0;
10149         
10150         big = AOP_SIZE(nextleft);
10151         small = AOP_SIZE(nextright);
10152         
10153         switch(nextic->op) {
10154                 
10155         case '+':
10156                 pic14_emitcode(";optimize a +","");
10157                 /* if unsigned or not an integral type */
10158                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10159                         pic14_emitcode(";add a bit to something","");
10160                 } else {
10161                         
10162                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10163                         
10164                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10165                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10166                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10167                         } else
10168                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10169                         
10170                         offset = 0;
10171                         while(--big) {
10172                                 
10173                                 offset++;
10174                                 
10175                                 if(--small) {
10176                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10177                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10178                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10179                                         }
10180                                         
10181                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10182                                         emitSKPNC;
10183                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10184                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10185                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10186                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10187                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10188                                         
10189                                 } else {
10190                                         pic14_emitcode("rlf","known_zero,w");
10191                                         
10192                                         /*
10193                                         if right is signed
10194                                         btfsc  right,7
10195                                         addlw ff
10196                                         */
10197                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10198                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10199                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10200                                         } else {
10201                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10202                                         }
10203                                 }
10204                         }
10205                         ret = 1;
10206                 }
10207         }
10208         ret = 1;
10209         
10210 release:
10211         freeAsmop(right,NULL,ic,TRUE);
10212         freeAsmop(result,NULL,ic,TRUE);
10213         freeAsmop(nextright,NULL,ic,TRUE);
10214         freeAsmop(nextleft,NULL,ic,TRUE);
10215         if(ret)
10216                 nextic->generated = 1;
10217         
10218         return ret;
10219 #else
10220         return 0;
10221 #endif
10222 }
10223 /*-----------------------------------------------------------------*/
10224 /* genCast - gen code for casting                                  */
10225 /*-----------------------------------------------------------------*/
10226 static void genCast (iCode *ic)
10227 {
10228         operand *result = IC_RESULT(ic);
10229         sym_link *restype = operandType(result);
10230         sym_link *rtype = operandType(IC_RIGHT(ic));
10231         operand *right = IC_RIGHT(ic);
10232         int size, offset ;
10233         
10234         FENTRY;
10235         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10236         /* if they are equivalent then do nothing */
10237         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10238                 return ;
10239         
10240         aopOp(right,ic,FALSE) ;
10241         aopOp(result,ic,FALSE);
10242         
10243         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10244         
10245         /* if the result is a bit */
10246         if (AOP_TYPE(result) == AOP_CRY) {
10247                 assert(!"assigning to bit variables is not supported");
10248         }
10249         
10250         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10251                 int offset = 1;
10252                 size = AOP_SIZE(result);
10253                 
10254                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10255                 
10256                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10257                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10258                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10259                 
10260                 while (size--)
10261                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10262                 
10263                 goto release;
10264         }
10265         
10266         if (IS_PTR(restype))
10267         {
10268           operand *result = IC_RESULT(ic);
10269           //operand *left = IC_LEFT(ic);
10270           operand *right = IC_RIGHT(ic);
10271           int tag = 0xff;
10272           
10273           /* copy common part */
10274           int max, size = AOP_SIZE(result);
10275           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10276           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10277
10278           /* warn if we discard generic opinter tag */
10279           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10280           {
10281             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10282           } // if
10283
10284           max = size;
10285           while (size--)
10286           {
10287             mov2w_op (right, size);
10288             movwf (AOP(result), size);
10289           } // while
10290
10291           /* upcast into generic pointer type? */
10292           if (IS_GENPTR(restype)
10293                 && (size < AOP_SIZE(result))
10294                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10295           {
10296             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10297             if (IS_PTR(rtype))
10298             {
10299               switch (DCL_TYPE(rtype))
10300               {
10301               case POINTER:     /* __data */
10302               case FPOINTER:    /* __data */
10303                 assert (AOP_SIZE(right) == 2);
10304                 tag = GPTRTAG_DATA;
10305                 break;
10306
10307               case CPOINTER:    /* __code */
10308                 assert (AOP_SIZE(right) == 2);
10309                 tag = GPTRTAG_CODE;
10310                 break;
10311                 
10312               case GPOINTER:    /* unknown destination, __data or __code */
10313                 /* assume __data space (address of immediate) */
10314                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10315                 if (AOP(right)->code)
10316                   tag = GPTRTAG_CODE;
10317                 else
10318                   tag = GPTRTAG_DATA;
10319                 break;
10320                 
10321               default:
10322                 assert (!"unhandled pointer type");
10323               } // switch
10324             } else {
10325               /* convert other values into pointers to __data space */
10326               tag = GPTRTAG_DATA;
10327             }
10328
10329             assert (AOP_SIZE(result) == 3);
10330             if (tag == 0) {
10331               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10332             } else {
10333               emitpcode(POC_MOVLW, popGetLit(tag));
10334               movwf(AOP(result), 2);
10335             }
10336           } else {
10337             addSign(result, max, 0);
10338           } // if
10339           goto release;
10340         }
10341         
10342         /* if they are the same size : or less */
10343         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10344                 
10345                 /* if they are in the same place */
10346                 if (pic14_sameRegs(AOP(right),AOP(result)))
10347                         goto release;
10348                 
10349                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10350                 if (IS_PTR_CONST(rtype))
10351                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10352                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10353                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10354                 
10355                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10356                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10357                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10358                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10359                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10360                         if(AOP_SIZE(result) <2)
10361                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10362                         
10363                 } else {
10364                         
10365                         /* if they in different places then copy */
10366                         size = AOP_SIZE(result);
10367                         offset = 0 ;
10368                         while (size--) {
10369                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10370                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10371                                 
10372                                 //aopPut(AOP(result),
10373                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10374                                 // offset);
10375                                 
10376                                 offset++;
10377                         }
10378                 }
10379                 goto release;
10380         }
10381         
10382         /* so we now know that the size of destination is greater
10383         than the size of the source.
10384         Now, if the next iCode is an operator then we might be
10385         able to optimize the operation without performing a cast.
10386         */
10387         if(0 && genMixedOperation(ic)) {
10388                 /* XXX: cannot optimize: must copy regs! */
10389                 goto release;
10390         }
10391         
10392         /* we move to result for the size of source */
10393         size = AOP_SIZE(right);
10394         offset = 0 ;
10395         while (size--) {
10396                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10397                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10398                 offset++;
10399         }
10400
10401         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10402
10403 release:
10404         freeAsmop(right,NULL,ic,TRUE);
10405         freeAsmop(result,NULL,ic,TRUE);
10406         
10407 }
10408
10409 /*-----------------------------------------------------------------*/
10410 /* genDjnz - generate decrement & jump if not zero instrucion      */
10411 /*-----------------------------------------------------------------*/
10412 static int genDjnz (iCode *ic, iCode *ifx)
10413 {
10414         symbol *lbl, *lbl1;
10415         FENTRY;
10416         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10417         
10418         if (!ifx)
10419                 return 0;
10420         
10421                 /* if the if condition has a false label
10422         then we cannot save */
10423         if (IC_FALSE(ifx))
10424                 return 0;
10425         
10426                 /* if the minus is not of the form 
10427         a = a - 1 */
10428         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10429                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10430                 return 0;
10431         
10432         if (operandLitValue(IC_RIGHT(ic)) != 1)
10433                 return 0;
10434         
10435                 /* if the size of this greater than one then no
10436         saving */
10437         if (getSize(operandType(IC_RESULT(ic))) > 1)
10438                 return 0;
10439         
10440         /* otherwise we can save BIG */
10441         lbl = newiTempLabel(NULL);
10442         lbl1= newiTempLabel(NULL);
10443         
10444         aopOp(IC_RESULT(ic),ic,FALSE);
10445         
10446         if (IS_AOP_PREG(IC_RESULT(ic))) {
10447                 pic14_emitcode("dec","%s",
10448                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10449                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10450                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10451         } else {  
10452                 
10453                 
10454                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10455                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10456                 
10457                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10458                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10459                 
10460         }
10461         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10462         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10463         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10464         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10465         
10466         
10467         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10468         ifx->generated = 1;
10469         return 1;
10470 }
10471
10472 /*-----------------------------------------------------------------*/
10473 /* genReceive - generate code for a receive iCode                  */
10474 /*-----------------------------------------------------------------*/
10475 static void genReceive (iCode *ic)
10476 {
10477         FENTRY;
10478         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10479         
10480         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10481                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10482                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10483                 
10484                 int size = getSize(operandType(IC_RESULT(ic)));
10485                 int offset =  fReturnSizePic - size;
10486                 while (size--) {
10487                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10488                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10489                         offset++;
10490                 }
10491                 aopOp(IC_RESULT(ic),ic,FALSE);
10492                 size = AOP_SIZE(IC_RESULT(ic));
10493                 offset = 0;
10494                 while (size--) {
10495                         pic14_emitcode ("pop","acc");
10496                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10497                 }
10498                 
10499         } else {
10500                 _G.accInUse++;
10501                 aopOp(IC_RESULT(ic),ic,FALSE);
10502                 _G.accInUse--;
10503                 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10504                 assignResultValue(IC_RESULT(ic));
10505         }
10506         
10507         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10508 }
10509
10510 /*-----------------------------------------------------------------*/
10511 /* genDummyRead - generate code for dummy read of volatiles        */
10512 /*-----------------------------------------------------------------*/
10513 static void
10514 genDummyRead (iCode * ic)
10515 {
10516         FENTRY;
10517         pic14_emitcode ("; genDummyRead","");
10518         pic14_emitcode ("; not implemented","");
10519         
10520         ic = ic;
10521 }
10522
10523 /*-----------------------------------------------------------------*/
10524 /* genpic14Code - generate code for pic14 based controllers        */
10525 /*-----------------------------------------------------------------*/
10526 /*
10527 * At this point, ralloc.c has gone through the iCode and attempted
10528 * to optimize in a way suitable for a PIC. Now we've got to generate
10529 * PIC instructions that correspond to the iCode.
10530 *
10531 * Once the instructions are generated, we'll pass through both the
10532 * peep hole optimizer and the pCode optimizer.
10533 *-----------------------------------------------------------------*/
10534
10535 void genpic14Code (iCode *lic)
10536 {
10537         iCode *ic;
10538         int cln = 0;
10539         const char *cline;
10540         
10541         FENTRY;
10542         lineHead = lineCurr = NULL;
10543         
10544         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10545         addpBlock(pb);
10546         
10547         /* if debug information required */
10548         if (options.debug && currFunc) { 
10549                 if (currFunc) {
10550                         debugFile->writeFunction (currFunc, lic);
10551                 }
10552         }
10553         
10554         
10555         for (ic = lic ; ic ; ic = ic->next ) {
10556                 
10557                 //DEBUGpic14_emitcode(";ic","");
10558                 //fprintf (stderr, "in ic loop\n");
10559                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10560                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10561                 
10562                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10563                   cln = ic->lineno;
10564                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10565                   cline = printCLine (ic->filename, ic->lineno);
10566                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10567                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10568                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10569                 }
10570                 
10571                 if (options.iCodeInAsm) {
10572                   char *iLine = printILine(ic);
10573                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10574                   dbuf_free(iLine);
10575                 }
10576                 /* if the result is marked as
10577                 spilt and rematerializable or code for
10578                 this has already been generated then
10579                 do nothing */
10580                 if (resultRemat(ic) || ic->generated ) 
10581                         continue ;
10582                 
10583                 /* depending on the operation */
10584                 switch (ic->op) {
10585                 case '!' :
10586                         genNot(ic);
10587                         break;
10588                         
10589                 case '~' :
10590                         genCpl(ic);
10591                         break;
10592                         
10593                 case UNARYMINUS:
10594                         genUminus (ic);
10595                         break;
10596                         
10597                 case IPUSH:
10598                         genIpush (ic);
10599                         break;
10600                         
10601                 case IPOP:
10602                         /* IPOP happens only when trying to restore a 
10603                         spilt live range, if there is an ifx statement
10604                         following this pop then the if statement might
10605                         be using some of the registers being popped which
10606                         would destory the contents of the register so
10607                         we need to check for this condition and handle it */
10608                         if (ic->next            && 
10609                                 ic->next->op == IFX &&
10610                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10611                                 genIfx (ic->next,ic);
10612                         else
10613                                 genIpop (ic);
10614                         break; 
10615                         
10616                 case CALL:
10617                         genCall (ic);
10618                         break;
10619                         
10620                 case PCALL:
10621                         genPcall (ic);
10622                         break;
10623                         
10624                 case FUNCTION:
10625                         genFunction (ic);
10626                         break;
10627                         
10628                 case ENDFUNCTION:
10629                         genEndFunction (ic);
10630                         break;
10631                         
10632                 case RETURN:
10633                         genRet (ic);
10634                         break;
10635                         
10636                 case LABEL:
10637                         genLabel (ic);
10638                         break;
10639                         
10640                 case GOTO:
10641                         genGoto (ic);
10642                         break;
10643                         
10644                 case '+' :
10645                         genPlus (ic) ;
10646                         break;
10647                         
10648                 case '-' :
10649                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10650                                 genMinus (ic);
10651                         break;
10652                         
10653                 case '*' :
10654                         genMult (ic);
10655                         break;
10656                         
10657                 case '/' :
10658                         genDiv (ic) ;
10659                         break;
10660                         
10661                 case '%' :
10662                         genMod (ic);
10663                         break;
10664                         
10665                 case '>' :
10666                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10667                         break;
10668                         
10669                 case '<' :
10670                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10671                         break;
10672                         
10673                 case LE_OP:
10674                 case GE_OP:
10675                 case NE_OP:
10676                         
10677                         /* note these two are xlated by algebraic equivalence
10678                         during parsing SDCC.y */
10679                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10680                                 "got '>=' or '<=' shouldn't have come here");
10681                         break;  
10682                         
10683                 case EQ_OP:
10684                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10685                         break;      
10686                         
10687                 case AND_OP:
10688                         genAndOp (ic);
10689                         break;
10690                         
10691                 case OR_OP:
10692                         genOrOp (ic);
10693                         break;
10694                         
10695                 case '^' :
10696                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10697                         break;
10698                         
10699                 case '|' :
10700                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10701                         break;
10702                         
10703                 case BITWISEAND:
10704                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10705                         break;
10706                         
10707                 case INLINEASM:
10708                         genInline (ic);
10709                         break;
10710                         
10711                 case RRC:
10712                         genRRC (ic);
10713                         break;
10714                         
10715                 case RLC:
10716                         genRLC (ic);
10717                         break;
10718                         
10719                 case GETHBIT:
10720                         genGetHbit (ic);
10721                         break;
10722                         
10723                 case LEFT_OP:
10724                         genLeftShift (ic);
10725                         break;
10726                         
10727                 case RIGHT_OP:
10728                         genRightShift (ic);
10729                         break;
10730                         
10731                 case GET_VALUE_AT_ADDRESS:
10732                         genPointerGet(ic);
10733                         break;
10734                         
10735                 case '=' :
10736                         if (POINTER_SET(ic))
10737                                 genPointerSet(ic);
10738                         else
10739                                 genAssign(ic);
10740                         break;
10741                         
10742                 case IFX:
10743                         genIfx (ic,NULL);
10744                         break;
10745                         
10746                 case ADDRESS_OF:
10747                         genAddrOf (ic);
10748                         break;
10749                         
10750                 case JUMPTABLE:
10751                         genJumpTab (ic);
10752                         break;
10753                         
10754                 case CAST:
10755                         genCast (ic);
10756                         break;
10757                         
10758                 case RECEIVE:
10759                         genReceive(ic);
10760                         break;
10761                         
10762                 case SEND:
10763                         addSet(&_G.sendSet,ic);
10764                         break;
10765                         
10766                 case DUMMY_READ_VOLATILE:
10767                         genDummyRead (ic);
10768                         break;
10769                         
10770                 default :
10771                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10772                         ic = ic;
10773                         break;
10774                 }
10775         }
10776
10777         
10778         /* now we are ready to call the
10779         peep hole optimizer */
10780         if (!options.nopeep) {
10781                 peepHole (&lineHead);
10782         }
10783         /* now do the actual printing */
10784         printLine (lineHead,codeOutBuf);
10785         
10786 #ifdef PCODE_DEBUG
10787         DFPRINTF((stderr,"printing pBlock\n\n"));
10788         printpBlock(stdout,pb);
10789 #endif
10790         
10791         return;
10792 }
10793
10794 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10795  * (meaning: representing its own address) or not (referencing its contents).
10796  * This can only be decided based on the operand's type. */
10797 int
10798 aop_isLitLike (asmop *aop)
10799 {
10800   assert (aop);
10801   if (aop->type == AOP_LIT) return 1;
10802 if (aop->type == AOP_IMMD) return 1;
10803   if ((aop->type == AOP_PCODE) &&
10804                 ((aop->aopu.pcop->type == PO_LITERAL)))
10805   {
10806     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10807      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10808     return 1;
10809   }
10810   return 0;
10811 }
10812
10813 int
10814 op_isLitLike (operand *op)
10815 {
10816   assert (op);
10817   if (aop_isLitLike (AOP(op))) return 1;
10818   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10819   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10820   return 0;
10821 }
10822