* src/pic16/gen.c (pic16_aopOp): use WREG as destination even for
[fw/sdcc] / src / pic16 / gen.c
1  /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
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   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
10   Bug Fixes  -  Raphael Neider <rneider AT web.de> (2004,2005)
11   
12   This program is free software; you can redistribute it and/or modify it
13   under the terms of the GNU General Public License as published by the
14   Free Software Foundation; either version 2, or (at your option) any
15   later version.
16   
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21   
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software
24   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25   
26   In other words, you are welcome to use, share and improve this program.
27   You are forbidden to forbid anyone else to use, share and improve
28   what you give them.   Help stamp out software-hoarding!
29   
30   Notes:
31   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
32                 Made everything static
33 -------------------------------------------------------------------------*/
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "SDCCglobl.h"
40 #include "newalloc.h"
41
42 #include "common.h"
43 #include "SDCCpeeph.h"
44 #include "ralloc.h"
45 #include "pcode.h"
46 #include "gen.h"
47 #include "genutils.h"
48 #include "device.h"
49 #include "main.h"
50
51 /* Set the following to 1 to enable the slower/bigger
52  * but more robust generic shifting routine (which also
53  * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
55
56 /* Set the following to 1 to enable the new
57  * stripped down genCmp version.
58  * This version should be easier to understand,
59  * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
61
62 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
63 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
64 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
66 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
67
68 /* If you change these, you also have to update the library files
69  * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
70 #define GPTR_TAG_DATA   0x80
71 #define GPTR_TAG_EEPROM 0x40
72 #define GPTR_TAG_CODE   0x00    /* must be 0 becaue of UPPER(sym)==0 */
73
74 /* Wrapper to execute `code' at most once. */
75 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
76
77 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
78 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
79 void pic16_genMult8X8_8 (operand *, operand *,operand *);
80 void pic16_genMult16X16_16(operand *, operand *, operand *);
81 void pic16_genMult32X32_32(operand *, operand *, operand *);
82 pCode *pic16_AssembleLine(char *line, int peeps);
83 extern void pic16_printpBlock(FILE *of, pBlock *pb);
84 static asmop *newAsmop (short type);
85 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
86 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
87 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
88 static pCodeOp *pic16_popRegFromIdx(int rIdx);
89
90 //static int aopIdx (asmop *aop, int offset);
91
92 int pic16_labelOffset=0;
93 extern int pic16_debug_verbose;
94 #if !(USE_GENERIC_SIGNED_SHIFT)
95 static int optimized_for_speed = 0;
96 #endif
97 /*
98   hack hack
99
100 */
101
102 extern set *externs;
103
104 /* max_key keeps track of the largest label number used in 
105    a function. This is then used to adjust the label offset
106    for the next function.
107 */
108 static int max_key=0;
109 static int GpsuedoStkPtr=0;
110
111 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
112
113 unsigned int pic16aopLiteral (value *val, int offset);
114 const char *pic16_AopType(short type);
115 static iCode *ifxForOp ( operand *op, iCode *ic );
116
117 void pic16_pushpCodeOp(pCodeOp *pcop);
118 void pic16_poppCodeOp(pCodeOp *pcop);
119
120 static bool is_LitOp(operand *op);
121 static bool is_LitAOp(asmop *aop);
122
123
124 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
125
126 /* set the following macro to 1 to enable passing the
127  * first byte of functions parameters via WREG */
128 #define USE_WREG_IN_FUNC_PARAMS 0
129
130
131 /* this is the down and dirty file with all kinds of 
132    kludgy & hacky stuff. This is what it is all about
133    CODE GENERATION for a specific MCU . some of the
134    routines may be reusable, will have to see */
135
136 static char *zero = "#0x00";
137 static char *one  = "#0x01";
138 //static char *spname = "sp";
139
140
141 /*
142  * Function return value policy (MSB-->LSB):
143  *  8 bits      -> WREG
144  * 16 bits      -> PRODL:WREG
145  * 24 bits      -> PRODH:PRODL:WREG
146  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
147  * >32 bits     -> on stack, and FSR0 points to the beginning
148  *
149  */
150  
151
152 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
153 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
154 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
155 static char **fReturn = fReturnpic16;
156
157 static char *accUse[] = {"WREG"};
158
159 //static short rbank = -1;
160
161 static struct {
162     short r0Pushed;
163     short r1Pushed;
164     short fsr0Pushed;
165     short accInUse;
166     short inLine;
167     short debugLine;
168     short nRegsSaved;
169     short ipushRegs;
170     set *sendSet;
171     set *stackRegSet;
172     int usefastretfie;
173     bitVect *fregsUsed;                 /* registers used in function */
174     bitVect *sregsAlloc;
175     set *sregsAllocSet;                 /* registers used to store stack variables */
176     int stack_lat;                      /* stack offset latency */
177     int resDirect;
178     int useWreg;                        /* flag when WREG is used to pass function parameter */
179 } _G;
180
181 extern int pic16_ptrRegReq ;
182 extern int pic16_nRegs;
183 extern FILE *codeOutFile;
184 //static void saverbank (int, iCode *,bool);
185
186 static lineNode *lineHead = NULL;
187 static lineNode *lineCurr = NULL;
188
189 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
190 0xE0, 0xC0, 0x80, 0x00};
191 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
192 0x07, 0x03, 0x01, 0x00};
193
194 static  pBlock *pb;
195
196 /*-----------------------------------------------------------------*/
197 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
198 /*                 exponent of 2 is returned, otherwise -1 is      */
199 /*                 returned.                                       */
200 /* note that this is similar to the function `powof2' in SDCCsymt  */
201 /* if(n == 2^y)                                                    */
202 /*   return y;                                                     */
203 /* return -1;                                                      */
204 /*-----------------------------------------------------------------*/
205 int pic16_my_powof2 (unsigned long num)
206 {
207   if(num) {
208     if( (num & (num-1)) == 0) {
209       int nshifts = -1;
210       while(num) {
211         num>>=1;
212         nshifts++;
213       }
214       return nshifts;
215     }
216   }
217
218   return -1;
219 }
220
221 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
222 {
223   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
224                        line_no,
225                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
226                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
227                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
228                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
229                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
230                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
231                        ((result) ? AOP_SIZE(result) : 0));
232 }
233
234 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
235 {
236
237   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
238                        line_no,
239                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
240                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
241                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
242                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
243                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
244                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
245
246 }
247
248 void pic16_emitpcomment (char *fmt, ...)
249 {
250     va_list ap;
251     char lb[INITIAL_INLINEASM];  
252     unsigned char *lbp = (unsigned char *)lb;
253
254     va_start(ap,fmt);   
255
256     lb[0] = ';';
257     vsprintf(lb+1,fmt,ap);
258
259     while (isspace(*lbp)) lbp++;
260
261     if (lbp && *lbp) 
262         lineCurr = (lineCurr ?
263                     connectLine(lineCurr,newLineNode(lb)) :
264                     (lineHead = newLineNode(lb)));
265     lineCurr->isInline = _G.inLine;
266     lineCurr->isDebug  = _G.debugLine;
267
268     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
269     va_end(ap);
270
271 //      fprintf(stderr, "%s\n", lb);
272 }
273
274 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
275 {
276     va_list ap;
277     char lb[INITIAL_INLINEASM];  
278     unsigned char *lbp = (unsigned char *)lb;
279
280     if(!pic16_debug_verbose)
281       return;
282
283     va_start(ap,fmt);   
284
285     if (inst && *inst) {
286         if (fmt && *fmt)
287             sprintf(lb,"%s\t",inst);
288         else
289             sprintf(lb,"%s",inst);
290         vsprintf(lb+(strlen(lb)),fmt,ap);
291     }  else
292         vsprintf(lb,fmt,ap);
293
294     while (isspace(*lbp)) lbp++;
295
296     if (lbp && *lbp) 
297         lineCurr = (lineCurr ?
298                     connectLine(lineCurr,newLineNode(lb)) :
299                     (lineHead = newLineNode(lb)));
300     lineCurr->isInline = _G.inLine;
301     lineCurr->isDebug  = _G.debugLine;
302
303     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
304     va_end(ap);
305
306 //      fprintf(stderr, "%s\n", lb);
307 }
308
309
310
311 void pic16_emitpLabel(int key)
312 {
313   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
314 }
315
316 void pic16_emitpLabelFORCE(int key)
317 {
318   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
319 }
320
321 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
322  * NEVER call pic16_emitpcode_real directly, please... */
323 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
324 {
325
326   if(pcop)
327     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
328   else
329     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
330 }
331
332 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
333 {
334   if(pcop)
335     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
336   else
337     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
338 }
339   
340 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
341 {
342
343   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
344
345 }
346
347
348 #if 1
349 #define pic16_emitcode  DEBUGpic16_emitcode
350 #else
351 /*-----------------------------------------------------------------*/
352 /* pic16_emitcode - writes the code into a file : for now it is simple    */
353 /*-----------------------------------------------------------------*/
354 void pic16_emitcode (char *inst,char *fmt, ...)
355 {
356     va_list ap;
357     char lb[INITIAL_INLINEASM];  
358     unsigned char *lbp = lb;
359
360     va_start(ap,fmt);   
361
362     if (inst && *inst) {
363         if (fmt && *fmt)
364             sprintf(lb,"%s\t",inst);
365         else
366             sprintf(lb,"%s",inst);
367         vsprintf(lb+(strlen(lb)),fmt,ap);
368     }  else
369         vsprintf(lb,fmt,ap);
370
371     while (isspace(*lbp)) lbp++;
372
373     if (lbp && *lbp) 
374         lineCurr = (lineCurr ?
375                     connectLine(lineCurr,newLineNode(lb)) :
376                     (lineHead = newLineNode(lb)));
377     lineCurr->isInline = _G.inLine;
378     lineCurr->isDebug  = _G.debugLine;
379
380 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
381
382 //    if(pic16_debug_verbose)
383 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
384
385     va_end(ap);
386 }
387 #endif
388
389
390 /*-----------------------------------------------------------------*/
391 /* pic16_emitDebuggerSymbol - associate the current code location  */
392 /*   with a debugger symbol                                        */
393 /*-----------------------------------------------------------------*/
394 void
395 pic16_emitDebuggerSymbol (char * debugSym)
396 {
397   _G.debugLine = 1;
398   pic16_emitcode (";", "%s ==.", debugSym);
399   _G.debugLine = 0;
400 }
401
402
403 /*-----------------------------------------------------------------*/
404 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
405 /*-----------------------------------------------------------------*/
406 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
407 {
408 //    bool r0iu = FALSE , r1iu = FALSE;
409 //    bool r0ou = FALSE , r1ou = FALSE;
410     bool fsr0iu = FALSE, fsr0ou;
411     bool fsr2iu = FALSE, fsr2ou;
412     
413     //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__,  __FUNCTION__, __LINE__, ic->op, result);
414
415     
416     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
417     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
418     
419     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
420     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
421
422     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
423         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
424         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
425     }
426
427     if(!fsr0iu && !fsr0ou) {
428         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
429         (*aopp)->type = AOP_FSR0;
430
431         //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
432         
433       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
434     }
435
436 #if 0
437     /* no usage of FSR2 */
438     if(!fsr2iu && !fsr2ou) {
439         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
440         (*aopp)->type = AOP_FSR2;
441
442       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
443     }
444 #endif
445         
446     /* now we know they both have usage */
447     /* if fsr0 not used in this instruction */
448     if (!fsr0iu) {
449         if (!_G.fsr0Pushed) {
450                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
451                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
452                 _G.fsr0Pushed++;
453         }
454
455         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
456         (*aopp)->type = AOP_FSR0;
457
458 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
459
460       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
461     }
462         
463
464     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
465     assert( 0 );
466
467     return NULL;
468 #if 0
469     /* the logic: if r0 & r1 used in the instruction
470     then we are in trouble otherwise */
471
472     /* first check if r0 & r1 are used by this
473     instruction, in which case we are in trouble */
474     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
475         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
476     {
477         goto endOfWorld;      
478     }
479
480     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
481     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
482
483     /* if no usage of r0 then return it */
484     if (!r0iu && !r0ou) {
485         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
486         (*aopp)->type = AOP_R0; 
487         
488         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
489     }
490
491     /* if no usage of r1 then return it */
492     if (!r1iu && !r1ou) {
493         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
494         (*aopp)->type = AOP_R1;
495
496         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
497     }    
498
499     /* now we know they both have usage */
500     /* if r0 not used in this instruction */
501     if (!r0iu) {
502         /* push it if not already pushed */
503         if (!_G.r0Pushed) {
504           //pic16_emitcode ("push","%s",
505           //          pic16_regWithIdx(R0_IDX)->dname);
506             _G.r0Pushed++ ;
507         }
508         
509         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
510         (*aopp)->type = AOP_R0;
511
512         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
513     }
514
515     /* if r1 not used then */
516
517     if (!r1iu) {
518         /* push it if not already pushed */
519         if (!_G.r1Pushed) {
520           //pic16_emitcode ("push","%s",
521           //          pic16_regWithIdx(R1_IDX)->dname);
522             _G.r1Pushed++ ;
523         }
524         
525         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
526         (*aopp)->type = AOP_R1;
527         return pic16_regWithIdx(R1_IDX);
528     }
529
530 endOfWorld :
531     /* I said end of world but not quite end of world yet */
532     /* if this is a result then we can push it on the stack*/
533     if (result) {
534         (*aopp)->type = AOP_STK;    
535         return NULL;
536     }
537
538     /* other wise this is true end of the world */
539     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
540            "getFreePtr should never reach here");
541     exit(0);
542 #endif
543 }
544
545 /*-----------------------------------------------------------------*/
546 /* newAsmop - creates a new asmOp                                  */
547 /*-----------------------------------------------------------------*/
548 static asmop *newAsmop (short type)
549 {
550     asmop *aop;
551
552     aop = Safe_calloc(1,sizeof(asmop));
553     aop->type = type;
554     return aop;
555 }
556
557 static void genSetDPTR(int n)
558 {
559     if (!n)
560     {
561         pic16_emitcode(";", "Select standard DPTR");
562         pic16_emitcode("mov", "dps, #0x00");
563     }
564     else
565     {
566         pic16_emitcode(";", "Select alternate DPTR");
567         pic16_emitcode("mov", "dps, #0x01");
568     }
569 }
570
571 /*-----------------------------------------------------------------*/
572 /* resolveIfx - converts an iCode ifx into a form more useful for  */
573 /*              generating code                                    */
574 /*-----------------------------------------------------------------*/
575 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
576 {
577   FENTRY2;
578   
579 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
580
581   if(!resIfx) 
582     return;
583
584
585   resIfx->condition = 1;    /* assume that the ifx is true */
586   resIfx->generated = 0;    /* indicate that the ifx has not been used */
587
588   if(!ifx) {
589     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
590
591 #if 1
592     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
593                         __FUNCTION__,__LINE__,resIfx->lbl->key);
594 #endif
595
596   } else {
597     if(IC_TRUE(ifx)) {
598       resIfx->lbl = IC_TRUE(ifx);
599     } else {
600       resIfx->lbl = IC_FALSE(ifx);
601       resIfx->condition = 0;
602     }
603
604 #if 1
605     if(IC_TRUE(ifx)) 
606       DEBUGpic16_emitcode("; +++","ifx true is non-null");
607     else
608       DEBUGpic16_emitcode("; +++","ifx true is null");
609     if(IC_FALSE(ifx)) 
610       DEBUGpic16_emitcode("; +++","ifx false is non-null");
611     else
612       DEBUGpic16_emitcode("; +++","ifx false is null");
613 #endif
614   }
615
616   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
617
618 }
619 #if 0
620 /*-----------------------------------------------------------------*/
621 /* pointerCode - returns the code for a pointer type               */
622 /*-----------------------------------------------------------------*/
623 static int pointerCode (sym_link *etype)
624 {
625
626     return PTR_TYPE(SPEC_OCLS(etype));
627
628 }
629 #endif
630
631 /*-----------------------------------------------------------------*/
632 /* aopForSym - for a true symbol                                   */
633 /*-----------------------------------------------------------------*/
634 static asmop *aopForSym (iCode *ic, operand *op, bool result)
635 {
636     symbol *sym=OP_SYMBOL(op);
637     asmop *aop;
638     memmap *space= SPEC_OCLS(sym->etype);
639
640     FENTRY2;
641     
642     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
643     
644 //    sym = OP_SYMBOL(op);
645
646     /* if already has one */
647     if (sym->aop) {
648             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
649         return sym->aop;
650     }
651
652 #if 0
653     /* if symbol was initially placed onStack then we must re-place it
654      * to direct memory, since pic16 does not have a specific stack */
655     if(sym->onStack) {
656         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
657     }
658 #endif
659
660
661 #if 0
662     if(sym->iaccess) {
663       if(space->paged) {
664         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
665
666         sym->aop = aop = newAsmop (AOP_PAGED);
667         aop->aopu.aop_dir = sym->rname ;
668         aop->size = getSize(sym->type);
669         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
670         pic16_allocDirReg( IC_LEFT(ic) );
671         return aop;
672       }
673       assert( 0 );
674     }
675 #endif
676     
677 #if 1
678     /* assign depending on the storage class */
679     /* if it is on the stack or indirectly addressable */
680     /* space we need to assign either r0 or r1 to it   */    
681     if (sym->onStack)   // || sym->iaccess)
682     {
683       pCodeOp *pcop[4];
684       int i;
685       
686         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
687                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
688         
689         /* acquire a temporary register -- it is saved in function */
690
691         sym->aop = aop = newAsmop(AOP_STA);
692         aop->aopu.stk.stk = sym->stack;
693         aop->size = getSize(sym->type);
694
695
696         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
697         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
698           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
699 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
700           
701           for(i=0;i<aop->size;i++)
702             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
703             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
704         } else
705         if(1 && ic->op == SEND) {
706
707           /* if SEND do the send here */
708           _G.resDirect = 1;
709         } else {
710 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
711           for(i=0;i<aop->size;i++) {
712             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
713             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
714           }
715         }
716
717
718 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
719
720 #if 1
721         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
722
723         // we do not need to load the value if it is to be defined...
724         if (result) return aop;
725
726         if(_G.accInUse) {
727                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
728         }
729         
730         for(i=0;i<aop->size;i++) {
731
732           /* initialise for stack access via frame pointer */
733           // operands on stack are accessible via "{FRAME POINTER} + index" with index
734           // starting at 2 for arguments and growing from 0 downwards for
735           // local variables (index == 0 is not assigned so we add one here)
736           {
737             int soffs = sym->stack;
738             if (soffs <= 0) {
739               assert (soffs < 0);
740               soffs++;
741             } // if
742
743             if(1 && ic->op == SEND) {
744               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
745               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
746                     pic16_popCopyReg( pic16_frame_plusw ),
747                     pic16_popCopyReg(pic16_stack_postdec )));
748             } else {
749               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
750               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
751                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
752             }
753           }
754         }
755         
756         if(_G.accInUse) {
757                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
758         }
759         
760         return (aop);
761 #endif
762
763 #if 0
764         /* now assign the address of the variable to 
765         the pointer register */
766         if (aop->type != AOP_STK) {
767
768             if (sym->onStack) {
769                     if ( _G.accInUse )
770                         pic16_emitcode("push","acc");
771
772                     pic16_emitcode("mov","a,_bp");
773                     pic16_emitcode("add","a,#0x%02x",
774                              ((sym->stack < 0) ?
775                               ((char)(sym->stack - _G.nRegsSaved )) :
776                               ((char)sym->stack)) & 0xff);
777                     pic16_emitcode("mov","%s,a",
778                              aop->aopu.aop_ptr->name);
779
780                     if ( _G.accInUse )
781                         pic16_emitcode("pop","acc");
782             } else
783                 pic16_emitcode("mov","%s,#%s",
784                          aop->aopu.aop_ptr->name,
785                          sym->rname);
786             aop->paged = space->paged;
787         } else
788             aop->aopu.aop_stk = sym->stack;
789         return aop;
790 #endif
791
792     }
793 #endif
794
795 #if 0
796     if (sym->onStack && options.stack10bit)
797     {
798         /* It's on the 10 bit stack, which is located in
799          * far data space.
800          */
801          
802       //DEBUGpic16_emitcode(";","%d",__LINE__);
803
804         if ( _G.accInUse )
805                 pic16_emitcode("push","acc");
806
807         pic16_emitcode("mov","a,_bp");
808         pic16_emitcode("add","a,#0x%02x",
809                  ((sym->stack < 0) ?
810                    ((char)(sym->stack - _G.nRegsSaved )) :
811                    ((char)sym->stack)) & 0xff);
812         
813         genSetDPTR(1);
814         pic16_emitcode ("mov","dpx1,#0x40");
815         pic16_emitcode ("mov","dph1,#0x00");
816         pic16_emitcode ("mov","dpl1, a");
817         genSetDPTR(0);
818         
819         if ( _G.accInUse )
820             pic16_emitcode("pop","acc");
821             
822         sym->aop = aop = newAsmop(AOP_DPTR2);
823         aop->size = getSize(sym->type); 
824         return aop;
825     }
826 #endif
827
828 #if 1
829     /* special case for a function */
830     if (IS_FUNC(sym->type)) {   
831         sym->aop = aop = newAsmop(AOP_PCODE);
832         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
833         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
834         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
835         PCOI(aop->aopu.pcop)->index = 0;
836         aop->size = FPTRSIZE; 
837         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
838         return aop;
839     }
840 #endif
841
842
843
844     //DEBUGpic16_emitcode(";","%d",__LINE__);
845     /* if in bit space */
846     if (IN_BITSPACE(space)) {
847         sym->aop = aop = newAsmop (AOP_CRY);
848         aop->aopu.aop_dir = sym->rname ;
849         aop->size = getSize(sym->type);
850         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
851         return aop;
852     }
853     /* if it is in direct space */
854     if (IN_DIRSPACE(space)) {
855                 if(!strcmp(sym->rname, "_WREG")) {
856                         sym->aop = aop = newAsmop (AOP_ACC);
857                         aop->size = getSize(sym->type);         /* should always be 1 */
858                         assert(aop->size == 1);
859                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
860                         return (aop);
861                 } else {
862                         sym->aop = aop = newAsmop (AOP_DIR);
863                 aop->aopu.aop_dir = sym->rname ;
864             aop->size = getSize(sym->type);
865                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
866                         pic16_allocDirReg( IC_LEFT(ic) );
867                         return (aop);
868                 }
869         }
870
871     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
872         sym->aop = aop = newAsmop (AOP_DIR);
873         aop->aopu.aop_dir = sym->rname ;
874         aop->size = getSize(sym->type);
875         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
876         pic16_allocDirReg( IC_LEFT(ic) );
877         return aop;
878     }
879
880
881     /* only remaining is far space */
882     sym->aop = aop = newAsmop(AOP_PCODE);
883
884 /* change the next if to 1 to revert to good old immediate code */
885         if(IN_CODESPACE(space)) {
886                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
887                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
888                 PCOI(aop->aopu.pcop)->index = 0;
889         } else {
890                 /* try to allocate via direct register */
891                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
892 //              aop->size = getSize( sym->type );
893         }
894
895         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
896                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
897
898 #if 0
899         if(!pic16_allocDirReg (IC_LEFT(ic)))
900                 return NULL;
901 #endif
902
903         if(IN_DIRSPACE( space ))
904                 aop->size = PTRSIZE;
905         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
906                 aop->size = FPTRSIZE;
907         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
908         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
909         else if(sym->onStack) {
910                 aop->size = PTRSIZE;
911         } else {
912           if(SPEC_SCLS(sym->etype) == S_PDATA) {
913             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
914             aop->size = FPTRSIZE;
915           } else
916                 assert( 0 );
917         }
918
919     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
920
921     /* if it is in code space */
922     if (IN_CODESPACE(space))
923         aop->code = 1;
924
925     return aop;     
926 }
927
928 /*-----------------------------------------------------------------*/
929 /* aopForRemat - rematerialzes an object                           */
930 /*-----------------------------------------------------------------*/
931 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
932 {
933   symbol *sym = OP_SYMBOL(op);
934   operand *refop;
935   iCode *ic = NULL, *oldic;
936   asmop *aop = newAsmop(AOP_PCODE);
937   int val = 0;
938   int offset = 0;
939   int viaimmd=0;
940
941     FENTRY2;
942     
943         ic = sym->rematiCode;
944
945         if(IS_OP_POINTER(op)) {
946                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
947         }
948
949 //    if(!result)               /* fixme-vr */
950         for (;;) {
951                 oldic = ic;
952
953 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
954         
955                 if (ic->op == '+') {
956                         val += (int) operandLitValue(IC_RIGHT(ic));
957                 } else if (ic->op == '-') {
958                         val -= (int) operandLitValue(IC_RIGHT(ic));
959                 } else
960                         break;
961                 
962                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
963         }
964
965         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
966         refop = IC_LEFT(ic);
967
968         if(!op->isaddr)viaimmd++; else viaimmd=0;
969                 
970 /* set the following if to 1 to revert to good old immediate code */
971         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
972                 || viaimmd) {
973
974                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
975
976                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
977
978 #if 0
979                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
980 #else
981                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
982 #endif
983
984                 PCOI(aop->aopu.pcop)->index = val;
985                 
986                 aop->size = getSize( sym->type );
987         } else {
988                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
989
990                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
991                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
992
993                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
994         }
995
996
997         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
998                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
999 #if 0
1000                 val, IS_PTR_CONST(operandType(op)));
1001 #else
1002                 val, IS_CODEPTR(operandType(op)));
1003 #endif
1004
1005 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1006
1007         pic16_allocDirReg (IC_LEFT(ic));
1008
1009         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1010                 aop->code = 1;
1011
1012   return aop;        
1013 }
1014
1015 #if 0
1016 static int aopIdx (asmop *aop, int offset)
1017 {
1018   if(!aop)
1019     return -1;
1020
1021   if(aop->type !=  AOP_REG)
1022     return -2;
1023         
1024   return aop->aopu.aop_reg[offset]->rIdx;
1025
1026 }
1027 #endif
1028
1029 /*-----------------------------------------------------------------*/
1030 /* regsInCommon - two operands have some registers in common       */
1031 /*-----------------------------------------------------------------*/
1032 static bool regsInCommon (operand *op1, operand *op2)
1033 {
1034     symbol *sym1, *sym2;
1035     int i;
1036
1037     /* if they have registers in common */
1038     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1039         return FALSE ;
1040
1041     sym1 = OP_SYMBOL(op1);
1042     sym2 = OP_SYMBOL(op2);
1043
1044     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1045         return FALSE ;
1046
1047     for (i = 0 ; i < sym1->nRegs ; i++) {
1048         int j;
1049         if (!sym1->regs[i])
1050             continue ;
1051
1052         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1053             if (!sym2->regs[j])
1054                 continue ;
1055
1056             if (sym2->regs[j] == sym1->regs[i])
1057                 return TRUE ;
1058         }
1059     }
1060
1061     return FALSE ;
1062 }
1063
1064 /*-----------------------------------------------------------------*/
1065 /* operandsEqu - equivalent                                        */
1066 /*-----------------------------------------------------------------*/
1067 static bool operandsEqu ( operand *op1, operand *op2)
1068 {
1069     symbol *sym1, *sym2;
1070
1071     /* if they not symbols */
1072     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1073         return FALSE;
1074
1075     sym1 = OP_SYMBOL(op1);
1076     sym2 = OP_SYMBOL(op2);
1077
1078     /* if both are itemps & one is spilt
1079        and the other is not then false */
1080     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1081         sym1->isspilt != sym2->isspilt )
1082         return FALSE ;
1083
1084     /* if they are the same */
1085     if (sym1 == sym2)
1086         return TRUE ;
1087
1088     if (sym1->rname[0] && sym2->rname[0]
1089         && strcmp (sym1->rname, sym2->rname) == 0)
1090         return TRUE;
1091
1092
1093     /* if left is a tmp & right is not */
1094     if (IS_ITEMP(op1)  && 
1095         !IS_ITEMP(op2) &&
1096         sym1->isspilt  &&
1097         (sym1->usl.spillLoc == sym2))
1098         return TRUE;
1099
1100     if (IS_ITEMP(op2)  && 
1101         !IS_ITEMP(op1) &&
1102         sym2->isspilt  &&
1103         sym1->level > 0 &&
1104         (sym2->usl.spillLoc == sym1))
1105         return TRUE ;
1106
1107     return FALSE ;
1108 }
1109
1110 /*-----------------------------------------------------------------*/
1111 /* pic16_sameRegs - two asmops have the same registers                   */
1112 /*-----------------------------------------------------------------*/
1113 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1114 {
1115     int i;
1116
1117     if (aop1 == aop2)
1118         return TRUE ;
1119
1120     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1121                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1122
1123     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1124
1125     if (aop1->type != AOP_REG ||
1126         aop2->type != AOP_REG )
1127         return FALSE ;
1128
1129     /* This is a bit too restrictive if one is a subset of the other...
1130     if (aop1->size != aop2->size )
1131         return FALSE ;
1132     */
1133
1134     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1135 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1136
1137 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1138         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1139             return FALSE ;
1140     }
1141
1142     return TRUE ;
1143 }
1144
1145 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1146 {
1147     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1148                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1149
1150     if(aop1 == aop2)return TRUE;
1151     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1152       
1153       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1154     
1155   return TRUE;
1156 }
1157
1158
1159 /*-----------------------------------------------------------------*/
1160 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1161 /*-----------------------------------------------------------------*/
1162 void pic16_aopOp (operand *op, iCode *ic, bool result)
1163 {
1164     asmop *aop;
1165     symbol *sym;
1166     int i;
1167
1168     if (!op)
1169         return ;
1170
1171     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1172
1173     /* if this a literal */
1174     if (IS_OP_LITERAL(op)) {
1175         op->aop = aop = newAsmop(AOP_LIT);
1176         aop->aopu.aop_lit = op->operand.valOperand;
1177         aop->size = getSize(operandType(op));
1178         return;
1179     }
1180
1181     {
1182       sym_link *type = operandType(op);
1183 #if 0
1184       if(IS_PTR_CONST(type))
1185 #else
1186       if(IS_CODEPTR(type))
1187 #endif
1188         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1189     }
1190
1191     /* if already has a asmop then continue */
1192     if (op->aop)
1193         return ;
1194
1195     /* if the underlying symbol has a aop */
1196     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1197       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1198         op->aop = OP_SYMBOL(op)->aop;
1199         return;
1200     }
1201
1202     /* if this is a true symbol */
1203     if (IS_TRUE_SYMOP(op)) {    
1204         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1205       op->aop = aopForSym(ic, op, result);
1206       return ;
1207     }
1208
1209     /* this is a temporary : this has
1210     only four choices :
1211     a) register
1212     b) spillocation
1213     c) rematerialize 
1214     d) conditional   
1215     e) can be a return use only */
1216
1217     sym = OP_SYMBOL(op);
1218
1219     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1220     /* if the type is a conditional */
1221     if (sym->regType == REG_CND) {
1222         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1223         aop->size = 0;
1224         return;
1225     }
1226
1227     /* if it is spilt then two situations
1228     a) is rematerialize 
1229     b) has a spill location */
1230     if (sym->isspilt || sym->nRegs == 0) {
1231
1232 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1233       DEBUGpic16_emitcode(";","%d",__LINE__);
1234         /* rematerialize it NOW */
1235         if (sym->remat) {
1236
1237             sym->aop = op->aop = aop = aopForRemat (op, result);
1238 //            aop->size = getSize(sym->type);
1239 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1240             return;
1241         }
1242
1243 #if 1
1244         if (sym->accuse) {
1245             int i;
1246             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1247             aop->size = getSize(sym->type);
1248             for ( i = 0 ; i < 1 ; i++ ) {
1249                 aop->aopu.aop_str[i] = accUse[i];
1250 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1251             }
1252             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1253             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1254             return;  
1255         }
1256 #endif
1257
1258 #if 1
1259         if (sym->ruonly) {
1260           /*
1261           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1262           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1263           //pic16_allocDirReg (IC_LEFT(ic));
1264           aop->size = getSize(sym->type);
1265           */
1266
1267           unsigned i;
1268
1269           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1270           aop->size = getSize(sym->type);
1271           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1272             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1273
1274           DEBUGpic16_emitcode(";","%d",__LINE__);
1275           return;
1276         }
1277 #endif
1278         /* else spill location  */
1279         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1280             /* force a new aop if sizes differ */
1281             sym->usl.spillLoc->aop = NULL;
1282         }
1283
1284 #if 0
1285         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1286                             __FUNCTION__,__LINE__,
1287                             sym->usl.spillLoc->rname,
1288                             sym->rname, sym->usl.spillLoc->offset);
1289 #endif
1290
1291         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1292         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1293           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1294           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1295                                                   getSize(sym->type), 
1296                                                   sym->usl.spillLoc->offset, op);
1297         } else if (getSize(sym->type) <= 1) {
1298           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1299           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1300           assert (getSize(sym->type) <= 1);
1301           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1302           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1303         } else {
1304           /* We need some kind of dummy area for getSize(sym->type) byte,
1305            * use WREG for all storage locations.
1306            * XXX: This only works if we are implementing a `dummy read',
1307            *      the stored value will not be retrievable...
1308            *      See #1503234 for a case requiring this. */
1309           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1310           aop->size = getSize(sym->type);
1311           for ( i = 0 ; i < aop->size ;i++)
1312             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1313         }
1314         aop->size = getSize(sym->type);
1315
1316         return;
1317     }
1318
1319     {
1320       sym_link *type = operandType(op);
1321 #if 0
1322       if(IS_PTR_CONST(type)) 
1323 #else
1324       if(IS_CODEPTR(type)) 
1325 #endif
1326         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1327     }
1328
1329     /* must be in a register */
1330     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1331     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1332     aop->size = sym->nRegs;
1333     for ( i = 0 ; i < sym->nRegs ;i++)
1334         aop->aopu.aop_reg[i] = sym->regs[i];
1335 }
1336
1337 /*-----------------------------------------------------------------*/
1338 /* pic16_freeAsmop - free up the asmop given to an operand               */
1339 /*----------------------------------------------------------------*/
1340 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1341 {   
1342     asmop *aop ;
1343
1344     if (!op)
1345         aop = aaop;
1346     else 
1347         aop = op->aop;
1348
1349     if (!aop)
1350         return ;
1351
1352     if (aop->freed)
1353         goto dealloc; 
1354
1355     aop->freed = 1;
1356
1357     /* depending on the asmop type only three cases need work AOP_RO
1358        , AOP_R1 && AOP_STK */
1359 #if 1
1360     switch (aop->type) {
1361         case AOP_FSR0 :
1362             if (_G.fsr0Pushed ) {
1363                 if (pop) {
1364                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1365                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1366 //                    pic16_emitcode ("pop","ar0");
1367                     _G.fsr0Pushed--;
1368                 }
1369             }
1370             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1371             break;
1372
1373         case AOP_FSR2 :
1374             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1375             break;
1376
1377         case AOP_R0 :
1378             if (_G.r0Pushed ) {
1379                 if (pop) {
1380                     pic16_emitcode ("pop","ar0");     
1381                     _G.r0Pushed--;
1382                 }
1383             }
1384             bitVectUnSetBit(ic->rUsed,R0_IDX);
1385             break;
1386
1387         case AOP_R1 :
1388             if (_G.r1Pushed ) {
1389                 if (pop) {
1390                     pic16_emitcode ("pop","ar1");
1391                     _G.r1Pushed--;
1392                 }
1393             }
1394             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1395             break;
1396
1397         case AOP_STA:
1398           {
1399             int i;
1400
1401               /* we must store the result on stack */
1402               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1403                 // operands on stack are accessible via "FSR2 + index" with index
1404                 // starting at 2 for arguments and growing from 0 downwards for
1405                 // local variables (index == 0 is not assigned so we add one here)
1406                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1407                 if (soffs <= 0) {
1408                   assert (soffs < 0);
1409                   soffs++;
1410                 } // if
1411                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1412                 for(i=0;i<aop->size;i++) {
1413                   /* initialise for stack access via frame pointer */
1414                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1415                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1416                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1417                 }
1418         
1419                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1420               }
1421
1422               if(!_G.resDirect) {
1423                 for(i=0;i<aop->size;i++) {
1424                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1425
1426                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1427                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1428 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1429                   }
1430                 }
1431                 
1432                 {
1433                   regs *sr;
1434                   
1435                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1436                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1437                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1438                       deleteSetItem( &_G.sregsAllocSet, sr );
1439                     }
1440                 }
1441               }
1442               _G.resDirect = 0;
1443           }
1444           break;
1445 #if 0
1446         case AOP_STK :
1447         {
1448             int sz = aop->size;    
1449             int stk = aop->aopu.aop_stk + aop->size;
1450             bitVectUnSetBit(ic->rUsed,R0_IDX);
1451             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1452
1453             getFreePtr(ic,&aop,FALSE);
1454             
1455             if (options.stack10bit)
1456             {
1457                 /* I'm not sure what to do here yet... */
1458                 /* #STUB */
1459                 fprintf(stderr, 
1460                         "*** Warning: probably generating bad code for "
1461                         "10 bit stack mode.\n");
1462             }
1463             
1464             if (stk) {
1465                 pic16_emitcode ("mov","a,_bp");
1466                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1467                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1468             } else {
1469                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1470             }
1471
1472             while (sz--) {
1473                 pic16_emitcode("pop","acc");
1474                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1475                 if (!sz) break;
1476                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1477             }
1478             op->aop = aop;
1479             pic16_freeAsmop(op,NULL,ic,TRUE);
1480             if (_G.r0Pushed) {
1481                 pic16_emitcode("pop","ar0");
1482                 _G.r0Pushed--;
1483             }
1484
1485             if (_G.r1Pushed) {
1486                 pic16_emitcode("pop","ar1");
1487                 _G.r1Pushed--;
1488             }       
1489         }
1490 #endif
1491
1492     }
1493 #endif
1494
1495 dealloc:
1496     /* all other cases just dealloc */
1497     if (op ) {
1498         op->aop = NULL;
1499         if (IS_SYMOP(op)) {
1500             OP_SYMBOL(op)->aop = NULL;    
1501             /* if the symbol has a spill */
1502             if (SPIL_LOC(op))
1503                 SPIL_LOC(op)->aop = NULL;
1504         }
1505     }
1506 }
1507
1508 /*-----------------------------------------------------------------*/
1509 /* pic16_aopGet - for fetching value of the aop                          */
1510 /*-----------------------------------------------------------------*/
1511 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1512 {
1513     char *s = buffer ;
1514     char *rs;
1515
1516     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1517
1518     /* offset is greater than size then zero */
1519     if (offset > (aop->size - 1) &&
1520         aop->type != AOP_LIT)
1521         return zero;
1522
1523     /* depending on type */
1524     switch (aop->type) {
1525
1526     case AOP_FSR0:
1527     case AOP_FSR2:
1528       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1529       rs = Safe_calloc(1, strlen(s)+1);
1530       strcpy(rs, s);
1531       return (rs);
1532       
1533 #if 0
1534       /* if we need to increment it */
1535       while (offset > aop->coff)
1536         {
1537           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1538           aop->coff++;
1539         }
1540
1541       while (offset < aop->coff)
1542         {
1543           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1544           aop->coff--;
1545         }
1546       aop->coff = offset;
1547       if (aop->paged)
1548         {
1549           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1550           return (dname ? "acc" : "a");
1551         }
1552       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1553       rs = Safe_calloc (1, strlen (s) + 1);
1554       strcpy (rs, s);
1555       return rs;
1556 #endif
1557
1558         
1559     case AOP_IMMD:
1560         if (bit16) 
1561             sprintf (s,"%s",aop->aopu.aop_immd);
1562         else
1563             if (offset) 
1564                 sprintf(s,"(%s >> %d)",
1565                         aop->aopu.aop_immd,
1566                         offset*8);
1567             else
1568                 sprintf(s,"%s",
1569                         aop->aopu.aop_immd);
1570         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1571         rs = Safe_calloc(1,strlen(s)+1);
1572         strcpy(rs,s);   
1573         return rs;
1574         
1575     case AOP_DIR:
1576       if (offset) {
1577         sprintf(s,"(%s + %d)",
1578                 aop->aopu.aop_dir,
1579                 offset);
1580         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1581       } else
1582             sprintf(s,"%s",aop->aopu.aop_dir);
1583         rs = Safe_calloc(1,strlen(s)+1);
1584         strcpy(rs,s);   
1585         return rs;
1586         
1587     case AOP_REG:
1588       return aop->aopu.aop_reg[offset]->name;
1589         
1590     case AOP_CRY:
1591       return aop->aopu.aop_dir;
1592         
1593     case AOP_ACC:
1594         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1595 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1596 //        assert( 0 );
1597 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1598         rs = Safe_strdup("WREG");
1599         return (rs);
1600
1601     case AOP_LIT:
1602         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1603         rs = Safe_calloc(1,strlen(s)+1);
1604         strcpy(rs,s);   
1605         return rs;
1606         
1607     case AOP_STR:
1608         aop->coff = offset ;
1609
1610 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1611 //          dname)
1612 //          return "acc";
1613         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1614           aop->type = AOP_ACC;
1615           return Safe_strdup("_WREG");
1616         }
1617         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1618         
1619         return aop->aopu.aop_str[offset];
1620         
1621     case AOP_PCODE:
1622       {
1623         pCodeOp *pcop = aop->aopu.pcop;
1624         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1625         if(pcop->name) {
1626           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1627           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1628           if (offset) {
1629             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1630           } else {
1631             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1632           }
1633         } else
1634           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1635
1636       }
1637       rs = Safe_calloc(1,strlen(s)+1);
1638       strcpy(rs,s);   
1639       return rs;
1640
1641 #if 0
1642     case AOP_PAGED:
1643       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1644       if (offset) {
1645         sprintf(s,"(%s + %d)",
1646                 aop->aopu.aop_dir,
1647                 offset);
1648       } else
1649             sprintf(s,"%s",aop->aopu.aop_dir);
1650       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1651       rs = Safe_calloc(1,strlen(s)+1);
1652       strcpy(rs,s);   
1653       return rs;
1654 #endif
1655
1656     case AOP_STA:
1657         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1658         return (rs);
1659         
1660     case AOP_STK:
1661 //        pCodeOp *pcop = aop->aop
1662         break;
1663
1664     }
1665
1666     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1667     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1668            "aopget got unsupported aop->type");
1669     exit(0);
1670 }
1671
1672
1673
1674 /* lock has the following meaning: When allocating temporary registers
1675  * for stack variables storage, the value of the temporary register is
1676  * saved on stack. Its value is restored at the end. This procedure is
1677  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1678  * a possibility that before a call to pic16_aopOp, a temporary register
1679  * is allocated for a while and it is freed after some time, this will
1680  * mess the stack and values will not be restored properly. So use lock=1
1681  * to allocate temporary registers used internally by the programmer, and
1682  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1683  * to inform the compiler developer about a possible bug. This is an internal
1684  * feature for developing the compiler -- VR */
1685  
1686 int _TempReg_lock = 0;
1687 /*-----------------------------------------------------------------*/
1688 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1689 /*-----------------------------------------------------------------*/
1690 pCodeOp *pic16_popGetTempReg(int lock)
1691 {
1692   pCodeOp *pcop=NULL;
1693   symbol *cfunc;
1694
1695 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1696     if(_TempReg_lock) {
1697 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1698     }
1699     
1700     _TempReg_lock += lock;
1701     
1702     cfunc = currFunc;
1703     currFunc = NULL;
1704
1705 #if 0
1706         {
1707           regs *rr;
1708           int i;
1709
1710                 /* this code might seem better but it does the *same* job with
1711                  * the old code, it all depends on ralloc.c to get a free/unused
1712                  * register */
1713          
1714                 i=0;
1715                 while(i < pic16_nRegs) {
1716                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1717                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1718                         if((!rr || (rr && rr->isFree))
1719                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1720                                 pcop = pic16_newpCodeOpReg( i );
1721                                 PCOR(pcop)->r->wasUsed = 1;
1722                                 PCOR(pcop)->r->isFree = 0;
1723                                 break;
1724                         }
1725                         i++;
1726                 }
1727
1728                 if(pcop) {
1729                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1730                 }
1731         }
1732 #else
1733     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1734     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1735       PCOR(pcop)->r->wasUsed=1;
1736       PCOR(pcop)->r->isFree=0;
1737
1738       /* push value on stack */
1739       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1740     }
1741 #endif
1742
1743     currFunc = cfunc;
1744
1745   return pcop;
1746 }
1747
1748 /*-----------------------------------------------------------------*/
1749 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1750 /*                           is not part of f, but don't save if   */
1751 /*                           inside v                              */
1752 /*-----------------------------------------------------------------*/
1753 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1754 {
1755   pCodeOp *pcop=NULL;
1756   symbol *cfunc;
1757   int i;
1758
1759 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1760
1761     if(_TempReg_lock) {
1762 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1763     }
1764
1765     _TempReg_lock += lock;
1766
1767     cfunc = currFunc;
1768     currFunc = NULL;
1769
1770     i = bitVectFirstBit(f);
1771     while(i < 128) {
1772
1773       /* bypass registers that are used by function */
1774       if(!bitVectBitValue(f, i)) {
1775       
1776         /* bypass registers that are already allocated for stack access */
1777         if(!bitVectBitValue(v, i))  {
1778         
1779 //          debugf("getting register rIdx = %d\n", i);
1780           /* ok, get the operand */
1781           pcop = pic16_newpCodeOpReg( i );
1782     
1783           /* should never by NULL */
1784           assert( pcop != NULL );
1785
1786           
1787           /* sanity check */
1788           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1789             int found=0;
1790             
1791               PCOR(pcop)->r->wasUsed=1;
1792               PCOR(pcop)->r->isFree=0;
1793
1794
1795               {
1796                 regs *sr;
1797               
1798                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1799
1800                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1801                       /* already used in previous steps, break */
1802                       found=1;          
1803                       break;
1804                     }
1805                   }
1806               }
1807
1808               /* caller takes care of the following */
1809 //              bitVectSetBit(v, i);
1810
1811               if(!found) {
1812                 /* push value on stack */
1813                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1814                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1815               }
1816           
1817             break;
1818           }
1819         }
1820       }
1821       i++;
1822     }
1823
1824     currFunc = cfunc;
1825
1826   return pcop;
1827 }
1828
1829
1830 /*-----------------------------------------------------------------*/
1831 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1832 /*-----------------------------------------------------------------*/
1833 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1834 {
1835   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1836
1837   _TempReg_lock -= lock;
1838
1839   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1840     PCOR(pcop)->r->isFree = 1;
1841
1842     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1843   }
1844 }
1845 /*-----------------------------------------------------------------*/
1846 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1847 /*-----------------------------------------------------------------*/
1848 pCodeOp *pic16_popGetLabel(int key)
1849 {
1850
1851   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1852
1853   if(key>max_key)
1854     max_key = key;
1855
1856   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1857 }
1858
1859 /*-----------------------------------------------------------------*/
1860 /* pic16_popCopyReg - copy a pcode operator                              */
1861 /*-----------------------------------------------------------------*/
1862 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1863 {
1864   pCodeOpReg *pcor;
1865
1866   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1867   memcpy (pcor, pc, sizeof (pCodeOpReg));
1868   pcor->r->wasUsed = 1;
1869   
1870   //pcor->pcop.type = pc->pcop.type;
1871   if(pc->pcop.name) {
1872     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1873       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1874   } else
1875     pcor->pcop.name = NULL;
1876
1877   //pcor->r = pc->r;
1878   //pcor->rIdx = pc->rIdx;
1879   //pcor->r->wasUsed=1;
1880   //pcor->instance = pc->instance;
1881
1882 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1883
1884   return PCOP(pcor);
1885 }
1886
1887 /*-----------------------------------------------------------------*/
1888 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1889 /*-----------------------------------------------------------------*/
1890 pCodeOp *pic16_popGetLit(int lit)
1891 {
1892   return pic16_newpCodeOpLit(lit);
1893 }
1894
1895 /* Allow for 12 bit literals (LFSR x, <here!>). */
1896 pCodeOp *pic16_popGetLit12(int lit)
1897 {
1898   return pic16_newpCodeOpLit12(lit);
1899 }
1900
1901 /*-----------------------------------------------------------------*/
1902 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1903 /*-----------------------------------------------------------------*/
1904 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1905 {
1906   return pic16_newpCodeOpLit2(lit, arg2);
1907 }
1908
1909
1910 /*-----------------------------------------------------------------*/
1911 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1912 /*-----------------------------------------------------------------*/
1913 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1914 {
1915   return pic16_newpCodeOpImmd(name, offset,index, 0);
1916 }
1917
1918
1919 /*-----------------------------------------------------------------*/
1920 /* pic16_popGet - asm operator to pcode operator conversion              */
1921 /*-----------------------------------------------------------------*/
1922 pCodeOp *pic16_popGetWithString(char *str)
1923 {
1924   pCodeOp *pcop;
1925
1926
1927   if(!str) {
1928     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1929     exit (1);
1930   }
1931
1932   pcop = pic16_newpCodeOp(str,PO_STR);
1933
1934   return pcop;
1935 }
1936
1937 /*-----------------------------------------------------------------*/
1938 /* pic16_popRegFromString -                                        */
1939 /*-----------------------------------------------------------------*/
1940 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1941 {
1942
1943   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1944   pcop->type = PO_DIR;
1945
1946   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1947   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1948
1949   if(!str)
1950     str = "BAD_STRING";
1951
1952   pcop->name = Safe_calloc(1,strlen(str)+1);
1953   strcpy(pcop->name,str);
1954
1955   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1956
1957   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1958 //  PCOR(pcop)->r->wasUsed = 1;
1959
1960   /* make sure that register doesn't exist,
1961    * and operand isn't NULL
1962    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1963   if((PCOR(pcop)->r == NULL) 
1964     && (op)
1965     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1966 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1967 //              __FUNCTION__, __LINE__, str, size, offset);
1968
1969     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1970     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1971
1972   }
1973   PCOR(pcop)->instance = offset;
1974
1975   return pcop;
1976 }
1977
1978 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1979 {
1980   pCodeOp *pcop;
1981
1982 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1983 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1984         
1985         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1986         PCOR(pcop)->rIdx = rIdx;
1987         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1988         if(!PCOR(pcop)->r)
1989                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1990                 
1991         PCOR(pcop)->r->isFree = 0;
1992         PCOR(pcop)->r->wasUsed = 1;
1993
1994         pcop->type = PCOR(pcop)->r->pc_type;
1995
1996   return pcop;
1997 }
1998
1999 /*---------------------------------------------------------------------------------*/
2000 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2001 /*                 VR 030601                                                       */
2002 /*---------------------------------------------------------------------------------*/
2003 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2004 {
2005   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2006         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2007   return PCOP(pcop2);
2008 }
2009
2010
2011
2012 /*--------------------------------------------------------------------------------.-*/
2013 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2014 /*                  VR 030601 , adapted by Hans Dorn                                */
2015 /*--------------------------------------------------------------------------------.-*/
2016 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2017 {
2018   pCodeOp2 *pcop2;
2019   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2020   return PCOP(pcop2);
2021 }
2022
2023 /*---------------------------------------------------------------------------------*/
2024 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2025 /*                     movff instruction                                           */
2026 /*---------------------------------------------------------------------------------*/
2027 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2028 {
2029   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2030         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2031
2032   return PCOP(pcop2);
2033 }
2034
2035
2036 /*-----------------------------------------------------------------*/
2037 /* pic16_popGet - asm operator to pcode operator conversion              */
2038 /*-----------------------------------------------------------------*/
2039 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2040 {
2041 //  char *s = buffer ;
2042 //  char *rs;
2043   pCodeOp *pcop;
2044
2045         FENTRY2;
2046                 /* offset is greater than
2047                  * size then zero */
2048
2049 //    if (offset > (aop->size - 1) &&
2050 //        aop->type != AOP_LIT)
2051 //      return NULL;  //zero;
2052
2053     /* depending on type */
2054     switch (aop->type) {
2055                 case AOP_R0:
2056                 case AOP_R1:
2057                 case AOP_DPTR:
2058                 case AOP_DPTR2:
2059                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2060                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2061                         assert( 0 );
2062                         return NULL;
2063
2064                 case AOP_FSR0:
2065                 case AOP_FSR2:
2066                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2067                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2068                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2069                         PCOR(pcop)->r->wasUsed = 1;
2070                         PCOR(pcop)->r->isFree = 0;
2071       
2072                         PCOR(pcop)->instance = offset;
2073                         pcop->type = PCOR(pcop)->r->pc_type;
2074                         return (pcop);
2075
2076                 case AOP_IMMD:
2077                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2078                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2079
2080                 case AOP_STA:
2081                         /* pCodeOp is already allocated from aopForSym */
2082                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2083                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2084                         return (pcop);
2085       
2086                 case AOP_ACC:
2087                         {
2088                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2089
2090                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2091
2092                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2093         
2094                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2095                                 PCOR(pcop)->rIdx = rIdx;
2096                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2097                                 PCOR(pcop)->r->wasUsed=1;
2098                                 PCOR(pcop)->r->isFree=0;
2099
2100                                 PCOR(pcop)->instance = offset;
2101                                 pcop->type = PCOR(pcop)->r->pc_type;
2102 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2103                                 return pcop;
2104
2105
2106 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2107 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2108
2109 //      assert( 0 );
2110                         }
2111         
2112     case AOP_DIR:
2113       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2114       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2115         
2116 #if 0
2117     case AOP_PAGED:
2118       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2119       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2120 #endif
2121
2122     case AOP_REG:
2123       {
2124         int rIdx;
2125         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2126         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2127
2128         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2129         
2130         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2131 //      pcop->type = PO_GPR_REGISTER;
2132         PCOR(pcop)->rIdx = rIdx;
2133         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2134         PCOR(pcop)->r->wasUsed=1;
2135         PCOR(pcop)->r->isFree=0;
2136
2137         PCOR(pcop)->instance = offset;
2138         pcop->type = PCOR(pcop)->r->pc_type;
2139         
2140         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2141 //      rs = aop->aopu.aop_reg[offset]->name;
2142 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2143         return pcop;
2144       }
2145
2146     case AOP_CRY:
2147         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2148
2149       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2150       PCOR(pcop)->instance = offset;
2151       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2152       //if(PCOR(pcop)->r == NULL)
2153       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2154       return pcop;
2155         
2156     case AOP_LIT:
2157         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2158       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2159
2160     case AOP_STR:
2161       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2162       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2163
2164       /*
2165       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2166       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2167       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2168       pcop->type = PCOR(pcop)->r->pc_type;
2169       pcop->name = PCOR(pcop)->r->name;
2170
2171       return pcop;
2172       */
2173
2174     case AOP_PCODE:
2175       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2176                           __LINE__, 
2177                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2178       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2179       switch( aop->aopu.pcop->type ) {
2180         case PO_DIR: PCOR(pcop)->instance += offset; break;
2181         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2182         case PO_WREG:
2183             assert (offset==0);
2184             break;
2185         default:
2186           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2187           assert( 0 );  /* should never reach here */;
2188       }
2189       return pcop;
2190     }
2191
2192     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2193            "pic16_popGet got unsupported aop->type");
2194     exit(0);
2195 }
2196 /*-----------------------------------------------------------------*/
2197 /* pic16_aopPut - puts a string for a aop                                */
2198 /*-----------------------------------------------------------------*/
2199 void pic16_aopPut (asmop *aop, char *s, int offset)
2200 {
2201     char *d = buffer ;
2202     symbol *lbl ;
2203
2204     return;
2205
2206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2207
2208     if (aop->size && offset > ( aop->size - 1)) {
2209         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2210                "pic16_aopPut got offset > aop->size");
2211         exit(0);
2212     }
2213
2214     /* will assign value to value */
2215     /* depending on where it is ofcourse */
2216     switch (aop->type) {
2217     case AOP_DIR:
2218       if (offset) {
2219         sprintf(d,"(%s + %d)",
2220                 aop->aopu.aop_dir,offset);
2221         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2222
2223       } else
2224             sprintf(d,"%s",aop->aopu.aop_dir);
2225         
2226         if (strcmp(d,s)) {
2227           DEBUGpic16_emitcode(";","%d",__LINE__);
2228           if(strcmp(s,"W"))
2229             pic16_emitcode("movf","%s,w",s);
2230           pic16_emitcode("movwf","%s",d);
2231
2232           if(strcmp(s,"W")) {
2233             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2234             if(offset >= aop->size) {
2235               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2236               break;
2237             } else
2238               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2239           }
2240
2241           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2242
2243
2244         }
2245         break;
2246         
2247     case AOP_REG:
2248       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2249         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2250           /*
2251             if (*s == '@'           ||
2252                 strcmp(s,"r0") == 0 ||
2253                 strcmp(s,"r1") == 0 ||
2254                 strcmp(s,"r2") == 0 ||
2255                 strcmp(s,"r3") == 0 ||
2256                 strcmp(s,"r4") == 0 ||
2257                 strcmp(s,"r5") == 0 ||
2258                 strcmp(s,"r6") == 0 || 
2259                 strcmp(s,"r7") == 0 )
2260                 pic16_emitcode("mov","%s,%s  ; %d",
2261                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2262             else
2263           */
2264
2265           if(strcmp(s,"W")==0 )
2266             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2267
2268           pic16_emitcode("movwf","%s",
2269                    aop->aopu.aop_reg[offset]->name);
2270
2271           if(strcmp(s,zero)==0) {
2272             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2273
2274           } else if(strcmp(s,"W")==0) {
2275             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2276             pcop->type = PO_GPR_REGISTER;
2277
2278             PCOR(pcop)->rIdx = -1;
2279             PCOR(pcop)->r = NULL;
2280
2281             DEBUGpic16_emitcode(";","%d",__LINE__);
2282             pcop->name = Safe_strdup(s);
2283             pic16_emitpcode(POC_MOVFW,pcop);
2284             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2285           } else if(strcmp(s,one)==0) {
2286             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2287             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2288           } else {
2289             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2290           }
2291         }
2292         break;
2293         
2294     case AOP_DPTR:
2295     case AOP_DPTR2:
2296     
2297     if (aop->type == AOP_DPTR2)
2298     {
2299         genSetDPTR(1);
2300     }
2301     
2302         if (aop->code) {
2303             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2304                    "pic16_aopPut writting to code space");
2305             exit(0);
2306         }
2307         
2308         while (offset > aop->coff) {
2309             aop->coff++;
2310             pic16_emitcode ("inc","dptr");
2311         }
2312         
2313         while (offset < aop->coff) {
2314             aop->coff-- ;
2315             pic16_emitcode("lcall","__decdptr");
2316         }
2317         
2318         aop->coff = offset;
2319         
2320         /* if not in accumulater */
2321         MOVA(s);        
2322         
2323         pic16_emitcode ("movx","@dptr,a");
2324         
2325     if (aop->type == AOP_DPTR2)
2326     {
2327         genSetDPTR(0);
2328     }
2329         break;
2330         
2331     case AOP_R0:
2332     case AOP_R1:
2333         while (offset > aop->coff) {
2334             aop->coff++;
2335             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2336         }
2337         while (offset < aop->coff) {
2338             aop->coff-- ;
2339             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2340         }
2341         aop->coff = offset;
2342         
2343         if (aop->paged) {
2344             MOVA(s);           
2345             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2346             
2347         } else
2348             if (*s == '@') {
2349                 MOVA(s);
2350                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2351             } else
2352                 if (strcmp(s,"r0") == 0 ||
2353                     strcmp(s,"r1") == 0 ||
2354                     strcmp(s,"r2") == 0 ||
2355                     strcmp(s,"r3") == 0 ||
2356                     strcmp(s,"r4") == 0 ||
2357                     strcmp(s,"r5") == 0 ||
2358                     strcmp(s,"r6") == 0 || 
2359                     strcmp(s,"r7") == 0 ) {
2360                     char buffer[10];
2361                     sprintf(buffer,"a%s",s);
2362                     pic16_emitcode("mov","@%s,%s",
2363                              aop->aopu.aop_ptr->name,buffer);
2364                 } else
2365                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2366         
2367         break;
2368         
2369     case AOP_STK:
2370         if (strcmp(s,"a") == 0)
2371             pic16_emitcode("push","acc");
2372         else
2373             pic16_emitcode("push","%s",s);
2374         
2375         break;
2376         
2377     case AOP_CRY:
2378         /* if bit variable */
2379         if (!aop->aopu.aop_dir) {
2380             pic16_emitcode("clr","a");
2381             pic16_emitcode("rlc","a");
2382         } else {
2383             if (s == zero) 
2384                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2385             else
2386                 if (s == one)
2387                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2388                 else
2389                     if (!strcmp(s,"c"))
2390                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2391                     else {
2392                         lbl = newiTempLabel(NULL);
2393                         
2394                         if (strcmp(s,"a")) {
2395                             MOVA(s);
2396                         }
2397                         pic16_emitcode("clr","c");
2398                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2399                         pic16_emitcode("cpl","c");
2400                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2401                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2402                     }
2403         }
2404         break;
2405         
2406     case AOP_STR:
2407         aop->coff = offset;
2408         if (strcmp(aop->aopu.aop_str[offset],s))
2409             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2410         break;
2411         
2412     case AOP_ACC:
2413         aop->coff = offset;
2414         if (!offset && (strcmp(s,"acc") == 0))
2415             break;
2416         
2417         if (strcmp(aop->aopu.aop_str[offset],s))
2418             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2419         break;
2420
2421     default :
2422         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2423 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2424 //             "pic16_aopPut got unsupported aop->type");
2425 //      exit(0);    
2426     }    
2427
2428 }
2429
2430 /*-----------------------------------------------------------------*/
2431 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2432 /*-----------------------------------------------------------------*/
2433 void pic16_mov2w (asmop *aop, int offset)
2434 {
2435   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2436
2437   if(is_LitAOp(aop))
2438     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2439   else
2440     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2441 }
2442
2443 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2444 {
2445   if(is_LitAOp(src)) {
2446     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2447     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2448   } else {
2449     if(pic16_sameRegsOfs(src, dst, offset))return;
2450     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2451                       pic16_popGet(dst, offset)));
2452   }
2453 }
2454
2455 static void pic16_movLit2f(pCodeOp *pc, int lit)
2456 {
2457   if (0 == (lit & 0x00ff))
2458   {
2459     pic16_emitpcode (POC_CLRF, pc);
2460   } else if (0xff == (lit & 0x00ff))
2461   {
2462     pic16_emitpcode (POC_SETF, pc);
2463   } else {
2464     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2465     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2466   }
2467 }
2468
2469 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2470 {
2471   if(is_LitAOp(src)) {
2472     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2473     pic16_emitpcode(POC_MOVWF, dst);
2474   } else {
2475     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2476   }
2477 }
2478
2479 void pic16_testStackOverflow(void)
2480 {
2481 #define GSTACK_TEST_NAME        "_gstack_test"
2482
2483   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2484   
2485   {
2486     symbol *sym;
2487
2488       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2489       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2490 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2491       checkAddSym(&externs, sym);
2492   }
2493
2494 }
2495
2496 /* push pcop into stack */
2497 void pic16_pushpCodeOp(pCodeOp *pcop)
2498 {
2499 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2500   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2501   if(pic16_options.gstack)
2502     pic16_testStackOverflow();
2503     
2504 }
2505
2506 /* pop pcop from stack */
2507 void pic16_poppCodeOp(pCodeOp *pcop)
2508 {
2509   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2510   if(pic16_options.gstack)
2511     pic16_testStackOverflow();
2512 }
2513
2514
2515 /*-----------------------------------------------------------------*/
2516 /* pushw - pushes wreg to stack                                    */
2517 /*-----------------------------------------------------------------*/
2518 void pushw(void)
2519 {
2520   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2521   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2522   if(pic16_options.gstack)
2523     pic16_testStackOverflow();
2524 }
2525
2526                 
2527 /*-----------------------------------------------------------------*/
2528 /* pushaop - pushes aop to stack                                   */
2529 /*-----------------------------------------------------------------*/
2530 void pushaop(asmop *aop, int offset)
2531 {
2532   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2533
2534   if(_G.resDirect)return;
2535   
2536   if(is_LitAOp(aop)) {
2537     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2538     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2539   } else {
2540     pic16_emitpcode(POC_MOVFF,
2541       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2542   }
2543
2544   if(pic16_options.gstack)
2545     pic16_testStackOverflow();
2546 }
2547
2548 /*-----------------------------------------------------------------*/
2549 /* popaop - pops aop from stack                                    */
2550 /*-----------------------------------------------------------------*/
2551 void popaop(asmop *aop, int offset)
2552 {
2553   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2554   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2555   if(pic16_options.gstack)
2556     pic16_testStackOverflow();
2557 }
2558
2559 void popaopidx(asmop *aop, int offset, int index)
2560 {
2561   int ofs=1;
2562
2563     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2564
2565     if(STACK_MODEL_LARGE)ofs++;
2566
2567     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2568     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2569     if(pic16_options.gstack)
2570       pic16_testStackOverflow();
2571 }
2572
2573 #if !(USE_GENERIC_SIGNED_SHIFT)
2574 /*-----------------------------------------------------------------*/
2575 /* reAdjustPreg - points a register back to where it should        */
2576 /*-----------------------------------------------------------------*/
2577 static void reAdjustPreg (asmop *aop)
2578 {
2579     int size ;
2580
2581     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2582     aop->coff = 0;
2583     if ((size = aop->size) <= 1)
2584         return ;
2585     size-- ;
2586     switch (aop->type) {
2587         case AOP_R0 :
2588         case AOP_R1 :
2589             while (size--)
2590                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2591             break;          
2592         case AOP_DPTR :
2593         case AOP_DPTR2:
2594             if (aop->type == AOP_DPTR2)
2595             {
2596                 genSetDPTR(1);
2597             } 
2598             while (size--)
2599             {
2600                 pic16_emitcode("lcall","__decdptr");
2601             }
2602                 
2603             if (aop->type == AOP_DPTR2)
2604             {
2605                 genSetDPTR(0);
2606             }                
2607             break;  
2608
2609     }   
2610
2611 }
2612 #endif
2613
2614 #if 0
2615 /*-----------------------------------------------------------------*/
2616 /* opIsGptr: returns non-zero if the passed operand is             */   
2617 /* a generic pointer type.                                         */
2618 /*-----------------------------------------------------------------*/ 
2619 static int opIsGptr(operand *op)
2620 {
2621     sym_link *type = operandType(op);
2622     
2623     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2624     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2625     {
2626         return 1;
2627     }
2628     return 0;        
2629 }
2630 #endif
2631
2632 /*-----------------------------------------------------------------*/
2633 /* pic16_getDataSize - get the operand data size                         */
2634 /*-----------------------------------------------------------------*/
2635 int pic16_getDataSize(operand *op)
2636 {
2637     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2638
2639
2640     return AOP_SIZE(op);
2641
2642     // tsd- in the pic port, the genptr size is 1, so this code here
2643     // fails. ( in the 8051 port, the size was 4).
2644 #if 0
2645     int size;
2646     size = AOP_SIZE(op);
2647     if (size == GPTRSIZE)
2648     {
2649         sym_link *type = operandType(op);
2650         if (IS_GENPTR(type))
2651         {
2652             /* generic pointer; arithmetic operations
2653              * should ignore the high byte (pointer type).
2654              */
2655             size--;
2656     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2657         }
2658     }
2659     return size;
2660 #endif
2661 }
2662
2663 /*-----------------------------------------------------------------*/
2664 /* pic16_outAcc - output Acc                                             */
2665 /*-----------------------------------------------------------------*/
2666 void pic16_outAcc(operand *result)
2667 {
2668   int size,offset;
2669   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2670   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2671
2672
2673   size = pic16_getDataSize(result);
2674   if(size){
2675     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2676     size--;
2677     offset = 1;
2678     /* unsigned or positive */
2679     while(size--)
2680       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2681   }
2682
2683 }
2684
2685 /*-----------------------------------------------------------------*/
2686 /* pic16_outBitC - output a bit C                                  */
2687 /*                 Move to result the value of Carry flag -- VR    */
2688 /*-----------------------------------------------------------------*/
2689 void pic16_outBitC(operand *result)
2690 {
2691   int i;
2692
2693     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2694
2695     /* if the result is bit */
2696     if (AOP_TYPE(result) == AOP_CRY) {
2697         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2698         pic16_aopPut(AOP(result),"c",0);
2699     } else {
2700
2701         i = AOP_SIZE(result);
2702         while(i--) {
2703                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2704         }
2705         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2706     }
2707 }
2708
2709 /*-----------------------------------------------------------------*/
2710 /* pic16_outBitOp - output a bit from Op                           */
2711 /*                 Move to result the value of set/clr op -- VR    */
2712 /*-----------------------------------------------------------------*/
2713 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2714 {
2715   int i;
2716
2717     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2718
2719     /* if the result is bit */
2720     if (AOP_TYPE(result) == AOP_CRY) {
2721         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2722         pic16_aopPut(AOP(result),"c",0);
2723     } else {
2724
2725         i = AOP_SIZE(result);
2726         while(i--) {
2727                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2728         }
2729         pic16_emitpcode(POC_RRCF, pcop);          
2730         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2731     }
2732 }
2733
2734 /*-----------------------------------------------------------------*/
2735 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2736 /*-----------------------------------------------------------------*/
2737 void pic16_toBoolean(operand *oper)
2738 {
2739     int size = AOP_SIZE(oper) - 1;
2740     int offset = 1;
2741
2742     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2743
2744     if ( AOP_TYPE(oper) != AOP_ACC) {
2745       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2746     }
2747     while (size--) {
2748       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2749     }
2750 }
2751
2752 /*-----------------------------------------------------------------*/
2753 /* genUminusFloat - unary minus for floating points                */
2754 /*-----------------------------------------------------------------*/
2755 static void genUminusFloat(operand *op,operand *result)
2756 {
2757   int size ,offset =0 ;
2758   
2759     FENTRY;
2760     /* for this we just need to flip the 
2761     first it then copy the rest in place */
2762     size = AOP_SIZE(op);
2763     assert( size == AOP_SIZE(result) );
2764
2765     while(size--) {
2766       pic16_mov2f(AOP(result), AOP(op), offset);
2767       offset++;
2768     }
2769     
2770     /* toggle the MSB's highest bit */
2771     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2772 }
2773
2774 /*-----------------------------------------------------------------*/
2775 /* genUminus - unary minus code generation                         */
2776 /*-----------------------------------------------------------------*/
2777 static void genUminus (iCode *ic)
2778 {
2779   int size, i;
2780   sym_link *optype, *rtype;
2781   symbol *label;
2782   int needLabel=0;
2783
2784     FENTRY;     
2785     
2786     /* assign asmops */
2787     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2788     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2789
2790     /* if both in bit space then special case */
2791     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2792       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2793         
2794         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2795         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2796         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2797         goto release; 
2798     } 
2799
2800     optype = operandType(IC_LEFT(ic));
2801     rtype = operandType(IC_RESULT(ic));
2802
2803
2804     /* if float then do float stuff */
2805     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2806       if(IS_FIXED(optype))
2807         debugf("implement fixed16x16 type\n", 0);
2808         
2809         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2810         goto release;
2811     }
2812
2813     /* otherwise subtract from zero by taking the 2's complement */
2814     size = AOP_SIZE(IC_LEFT(ic));
2815     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2816     label = newiTempLabel ( NULL );
2817     
2818     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2819       for (i=size-1; i > 0; i--) {
2820         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2821       } // for
2822       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2823       for (i=1; i < size; i++) {
2824         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2825         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2826       } // for
2827     } else {
2828       for (i=size-1; i >= 0; i--) {
2829         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2830         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2831       } // for
2832       if (size > 1) {
2833         for (i=0; i < size-2; i++) {
2834           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2835           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2836         } // for
2837         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2838       } // if
2839       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2840     }
2841     if (needLabel)
2842       pic16_emitpLabel (label->key);
2843
2844 release:
2845     /* release the aops */
2846     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2847     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2848 }
2849
2850 #if 0
2851 /*-----------------------------------------------------------------*/
2852 /* saveRegisters - will look for a call and save the registers     */
2853 /*-----------------------------------------------------------------*/
2854 static void saveRegisters(iCode *lic) 
2855 {
2856     int i;
2857     iCode *ic;
2858     bitVect *rsave;
2859     sym_link *dtype;
2860
2861     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2862     /* look for call */
2863     for (ic = lic ; ic ; ic = ic->next) 
2864         if (ic->op == CALL || ic->op == PCALL)
2865             break;
2866
2867     if (!ic) {
2868         fprintf(stderr,"found parameter push with no function call\n");
2869         return ;
2870     }
2871
2872     /* if the registers have been saved already then
2873     do nothing */
2874     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2875         return ;
2876
2877     /* find the registers in use at this time 
2878     and push them away to safety */
2879     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2880                           ic->rUsed);
2881
2882     ic->regsSaved = 1;
2883     if (options.useXstack) {
2884         if (bitVectBitValue(rsave,R0_IDX))
2885             pic16_emitcode("mov","b,r0");
2886         pic16_emitcode("mov","r0,%s",spname);
2887         for (i = 0 ; i < pic16_nRegs ; i++) {
2888             if (bitVectBitValue(rsave,i)) {
2889                 if (i == R0_IDX)
2890                     pic16_emitcode("mov","a,b");
2891                 else
2892                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2893                 pic16_emitcode("movx","@r0,a");
2894                 pic16_emitcode("inc","r0");
2895             }
2896         }
2897         pic16_emitcode("mov","%s,r0",spname);
2898         if (bitVectBitValue(rsave,R0_IDX))
2899             pic16_emitcode("mov","r0,b");           
2900     }// else
2901     //for (i = 0 ; i < pic16_nRegs ; i++) {
2902     //    if (bitVectBitValue(rsave,i))
2903     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2904     //}
2905
2906     dtype = operandType(IC_LEFT(ic));
2907     if (currFunc && dtype && 
2908         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2909         IFFUNC_ISISR(currFunc->type) &&
2910         !ic->bankSaved) 
2911
2912         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2913
2914 }
2915 /*-----------------------------------------------------------------*/
2916 /* unsaveRegisters - pop the pushed registers                      */
2917 /*-----------------------------------------------------------------*/
2918 static void unsaveRegisters (iCode *ic)
2919 {
2920     int i;
2921     bitVect *rsave;
2922
2923     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2924     /* find the registers in use at this time 
2925     and push them away to safety */
2926     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2927                           ic->rUsed);
2928     
2929     if (options.useXstack) {
2930         pic16_emitcode("mov","r0,%s",spname);   
2931         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2932             if (bitVectBitValue(rsave,i)) {
2933                 pic16_emitcode("dec","r0");
2934                 pic16_emitcode("movx","a,@r0");
2935                 if (i == R0_IDX)
2936                     pic16_emitcode("mov","b,a");
2937                 else
2938                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2939             }       
2940
2941         }
2942         pic16_emitcode("mov","%s,r0",spname);
2943         if (bitVectBitValue(rsave,R0_IDX))
2944             pic16_emitcode("mov","r0,b");
2945     } //else
2946     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2947     //    if (bitVectBitValue(rsave,i))
2948     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2949     //}
2950
2951 }  
2952 #endif
2953
2954 #if 0  // patch 14
2955 /*-----------------------------------------------------------------*/
2956 /* pushSide -                                                      */
2957 /*-----------------------------------------------------------------*/
2958 static void pushSide(operand * oper, int size)
2959 {
2960         int offset = 0;
2961     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2962         while (size--) {
2963                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2964                 if (AOP_TYPE(oper) != AOP_REG &&
2965                     AOP_TYPE(oper) != AOP_DIR &&
2966                     strcmp(l,"a") ) {
2967                         pic16_emitcode("mov","a,%s",l);
2968                         pic16_emitcode("push","acc");
2969                 } else
2970                         pic16_emitcode("push","%s",l);
2971         }
2972 }
2973 #endif // patch 14
2974
2975 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2976 {
2977   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2978     pic16_emitpcode(POC_MOVFW, src);
2979     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2980   } else {
2981     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2982         src, pic16_popGet(AOP(op), offset)));
2983   }
2984 }
2985
2986
2987 /*-----------------------------------------------------------------*/
2988 /* assignResultValue - assign results to oper, rescall==1 is       */
2989 /*                     called from genCall() or genPcall()         */
2990 /*-----------------------------------------------------------------*/
2991 static void assignResultValue(operand * oper, int rescall)
2992 {
2993   int size = AOP_SIZE(oper);
2994   int offset=0;
2995   
2996     FENTRY2;
2997 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2998     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2999
3000     if(rescall) {
3001       /* assign result from a call/pcall function() */
3002                 
3003       /* function results are stored in a special order,
3004        * see top of file with Function return policy, or manual */
3005
3006       if(size <= 4) {
3007         /* 8-bits, result in WREG */
3008         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3009                         
3010         if(size>1) {
3011           /* 16-bits, result in PRODL:WREG */
3012           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3013         }
3014                         
3015         if(size>2) {
3016           /* 24-bits, result in PRODH:PRODL:WREG */
3017           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3018         }
3019                         
3020         if(size>3) {
3021           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3022           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3023         }
3024       
3025       } else {
3026         /* >32-bits, result on stack, and FSR0 points to beginning.
3027          * Fix stack when done */
3028         /* FIXME FIXME */
3029 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3030         while (size--) {
3031 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3032 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3033                 
3034           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3035           GpsuedoStkPtr++;
3036         }
3037                         
3038         /* fix stack */
3039         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3040         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3041         if(STACK_MODEL_LARGE) {
3042           emitSKPNC;
3043           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3044         }
3045       }                 
3046     } else {
3047       int areg = 0;             /* matching argument register */
3048       
3049 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3050       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3051
3052
3053       /* its called from genReceive (probably) -- VR */
3054       /* I hope this code will not be called from somewhere else in the future! 
3055        * We manually set the pseudo stack pointer in genReceive. - dw
3056        */
3057       if(!GpsuedoStkPtr && _G.useWreg) {
3058 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3059
3060         /* The last byte in the assignment is in W */
3061         if(areg <= GpsuedoStkPtr) {
3062           size--;
3063           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3064           offset++;
3065 //          debugf("receive from WREG\n", 0);
3066         }
3067         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3068       }
3069 //      GpsuedoStkPtr++;
3070       _G.stack_lat = AOP_SIZE(oper)-1;
3071
3072       while (size) {
3073         size--;
3074         GpsuedoStkPtr++;
3075         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3076 //        debugf("receive from STACK\n", 0);
3077         offset++;
3078       }
3079     }
3080 }
3081
3082
3083 /*-----------------------------------------------------------------*/
3084 /* genIpush - generate code for pushing this gets a little complex */
3085 /*-----------------------------------------------------------------*/
3086 static void genIpush (iCode *ic)
3087 {
3088 //  int size, offset=0;
3089
3090   FENTRY;
3091   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3092
3093   if(ic->parmPush) {
3094     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3095
3096     /* send to stack as normal */
3097     addSet(&_G.sendSet,ic);
3098 //    addSetHead(&_G.sendSet,ic);
3099     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3100   }
3101
3102         
3103 #if 0
3104     int size, offset = 0 ;
3105     char *l;
3106
3107
3108     /* if this is not a parm push : ie. it is spill push 
3109     and spill push is always done on the local stack */
3110     if (!ic->parmPush) {
3111
3112         /* and the item is spilt then do nothing */
3113         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3114             return ;
3115
3116         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3117         size = AOP_SIZE(IC_LEFT(ic));
3118         /* push it on the stack */
3119         while(size--) {
3120             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3121             if (*l == '#') {
3122                 MOVA(l);
3123                 l = "acc";
3124             }
3125             pic16_emitcode("push","%s",l);
3126         }
3127         return ;        
3128     }
3129
3130     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3131 #endif
3132 }
3133
3134 /*-----------------------------------------------------------------*/
3135 /* genIpop - recover the registers: can happen only for spilling   */
3136 /*-----------------------------------------------------------------*/
3137 static void genIpop (iCode *ic)
3138 {
3139   FENTRY;
3140   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3141 #if 0
3142     int size,offset ;
3143
3144
3145     /* if the temp was not pushed then */
3146     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3147         return ;
3148
3149     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3150     size = AOP_SIZE(IC_LEFT(ic));
3151     offset = (size-1);
3152     while (size--) 
3153         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3154                                    FALSE,TRUE));
3155
3156     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3157 #endif
3158 }
3159
3160 #if 0
3161 /*-----------------------------------------------------------------*/
3162 /* unsaverbank - restores the resgister bank from stack            */
3163 /*-----------------------------------------------------------------*/
3164 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3165 {
3166   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3167 #if 0
3168     int i;
3169     asmop *aop ;
3170     regs *r = NULL;
3171
3172     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3173     if (popPsw) {
3174         if (options.useXstack) {
3175             aop = newAsmop(0);
3176             r = getFreePtr(ic,&aop,FALSE);
3177             
3178             
3179             pic16_emitcode("mov","%s,_spx",r->name);
3180             pic16_emitcode("movx","a,@%s",r->name);
3181             pic16_emitcode("mov","psw,a");
3182             pic16_emitcode("dec","%s",r->name);
3183             
3184         }else
3185             pic16_emitcode ("pop","psw");
3186     }
3187
3188     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3189         if (options.useXstack) {       
3190             pic16_emitcode("movx","a,@%s",r->name);
3191             //pic16_emitcode("mov","(%s+%d),a",
3192             //       regspic16[i].base,8*bank+regspic16[i].offset);
3193             pic16_emitcode("dec","%s",r->name);
3194
3195         } else 
3196           pic16_emitcode("pop",""); //"(%s+%d)",
3197         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3198     }
3199
3200     if (options.useXstack) {
3201
3202         pic16_emitcode("mov","_spx,%s",r->name);
3203         pic16_freeAsmop(NULL,aop,ic,TRUE);
3204
3205     }
3206 #endif 
3207 }
3208
3209 /*-----------------------------------------------------------------*/
3210 /* saverbank - saves an entire register bank on the stack          */
3211 /*-----------------------------------------------------------------*/
3212 static void saverbank (int bank, iCode *ic, bool pushPsw)
3213 {
3214   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3215 #if 0
3216     int i;
3217     asmop *aop ;
3218     regs *r = NULL;
3219
3220     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3221     if (options.useXstack) {
3222
3223         aop = newAsmop(0);
3224         r = getFreePtr(ic,&aop,FALSE);  
3225         pic16_emitcode("mov","%s,_spx",r->name);
3226
3227     }
3228
3229     for (i = 0 ; i < pic16_nRegs ;i++) {
3230         if (options.useXstack) {
3231             pic16_emitcode("inc","%s",r->name);
3232             //pic16_emitcode("mov","a,(%s+%d)",
3233             //         regspic16[i].base,8*bank+regspic16[i].offset);
3234             pic16_emitcode("movx","@%s,a",r->name);           
3235         } else 
3236           pic16_emitcode("push","");// "(%s+%d)",
3237                      //regspic16[i].base,8*bank+regspic16[i].offset);
3238     }
3239     
3240     if (pushPsw) {
3241         if (options.useXstack) {
3242             pic16_emitcode("mov","a,psw");
3243             pic16_emitcode("movx","@%s,a",r->name);     
3244             pic16_emitcode("inc","%s",r->name);
3245             pic16_emitcode("mov","_spx,%s",r->name);       
3246             pic16_freeAsmop (NULL,aop,ic,TRUE);
3247             
3248         } else
3249             pic16_emitcode("push","psw");
3250         
3251         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3252     }
3253     ic->bankSaved = 1;
3254 #endif
3255 }
3256 #endif  /* 0 */
3257
3258
3259 static int wparamCmp(void *p1, void *p2)
3260 {
3261   return (!strcmp((char *)p1, (char *)p2));
3262 }
3263
3264 int inWparamList(char *s)
3265 {
3266   return isinSetWith(wparamList, s, wparamCmp);
3267
3268
3269
3270 /*-----------------------------------------------------------------*/
3271 /* genCall - generates a call statement                            */
3272 /*-----------------------------------------------------------------*/
3273 static void genCall (iCode *ic)
3274 {
3275   sym_link *ftype;   
3276   int stackParms=0;
3277   int use_wreg=0;
3278   int inwparam=0;
3279   char *fname;
3280   
3281     FENTRY;
3282
3283     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3284     /* if caller saves & we have not saved then */
3285 //    if (!ic->regsSaved)
3286 //      saveRegisters(ic);
3287
3288         /* initialise stackParms for IPUSH pushes */
3289 //      stackParms = psuedoStkPtr;
3290 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3291     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3292     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3293
3294 #if 0
3295     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3296 #endif
3297
3298     /* if send set is not empty the assign */
3299     if (_G.sendSet) {
3300       iCode *sic;
3301       int psuedoStkPtr=-1; 
3302       int firstTimeThruLoop = 1;
3303
3304
3305         /* reverse sendSet if function is not reentrant */
3306         if(!IFFUNC_ISREENT(ftype))
3307           _G.sendSet = reverseSet(_G.sendSet);
3308
3309         /* First figure how many parameters are getting passed */
3310         stackParms = 0;
3311         use_wreg = 0;
3312         
3313         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3314           int size;
3315 //          int offset = 0;
3316
3317             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3318             size = AOP_SIZE(IC_LEFT(sic));
3319
3320             stackParms += size;
3321
3322             /* pass the last byte through WREG */
3323             if(inwparam) {
3324
3325               while (size--) {
3326                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3327                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3328                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3329
3330                 if(!firstTimeThruLoop) {
3331                   /* If this is not the first time we've been through the loop
3332                    * then we need to save the parameter in a temporary
3333                    * register. The last byte of the last parameter is
3334                    * passed in W. */
3335
3336                   pushw();
3337 //                  --psuedoStkPtr;             // sanity check
3338                   use_wreg = 1;
3339                 }
3340                 
3341                 firstTimeThruLoop=0;
3342
3343                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3344
3345 //                offset++;
3346               }
3347             } else {
3348               /* all arguments are passed via stack */
3349               use_wreg = 0;
3350
3351               while (size--) {
3352                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3353                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3354                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3355
3356 //                pushaop(AOP(IC_LEFT(sic)), size);
3357                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3358                                 
3359                 if(!_G.resDirect)
3360                   pushw();
3361               }
3362             }
3363
3364             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3365           }
3366
3367           if(inwparam) {
3368             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3369               pushw();  /* save last parameter to stack if functions has varargs */
3370               use_wreg = 0;
3371             } else
3372               use_wreg = 1;
3373           } else use_wreg = 0;
3374
3375           _G.stackRegSet = _G.sendSet;
3376           _G.sendSet = NULL;
3377     }
3378
3379     /* make the call */
3380     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3381
3382     GpsuedoStkPtr=0;
3383     
3384     /* if we need to assign a result value */
3385     if ((IS_ITEMP(IC_RESULT(ic))
3386           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3387               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3388         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3389
3390       _G.accInUse++;
3391       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3392       _G.accInUse--;
3393
3394       assignResultValue(IC_RESULT(ic), 1);
3395
3396       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3397                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3398                 
3399       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3400     }
3401
3402     if(!stackParms && ic->parmBytes) {
3403       stackParms = ic->parmBytes;
3404     }
3405       
3406     stackParms -= use_wreg;
3407     
3408     if(stackParms>0) {
3409       if(stackParms == 1) {
3410         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3411       } else {
3412         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3413         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3414       }
3415       if(STACK_MODEL_LARGE) {
3416         emitSKPNC;
3417         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3418       }
3419     }
3420
3421 #if 0
3422     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3423 #endif
3424
3425     /* adjust the stack for parameters if required */
3426 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3427
3428 #if 0
3429       /* if register bank was saved then pop them */
3430       if (ic->bankSaved)
3431         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3432
3433       /* if we hade saved some registers then unsave them */
3434       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3435         unsaveRegisters (ic);
3436 #endif
3437 }
3438
3439
3440
3441 /*-----------------------------------------------------------------*/
3442 /* genPcall - generates a call by pointer statement                */
3443 /*            new version, created from genCall - HJD              */
3444 /*-----------------------------------------------------------------*/
3445 static void genPcall (iCode *ic)
3446 {
3447   sym_link *fntype;
3448   int stackParms=0;
3449   symbol *retlbl = newiTempLabel(NULL);
3450   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3451   
3452     FENTRY;
3453
3454     fntype = operandType( IC_LEFT(ic) )->next;
3455
3456     /* if send set is not empty the assign */
3457     if (_G.sendSet) {
3458       iCode *sic;
3459       int psuedoStkPtr=-1; 
3460
3461       /* reverse sendSet if function is not reentrant */
3462       if(!IFFUNC_ISREENT(fntype))
3463         _G.sendSet = reverseSet(_G.sendSet);
3464
3465       stackParms = 0;
3466       
3467       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3468         int size;
3469
3470           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3471           size = AOP_SIZE(IC_LEFT(sic));
3472           stackParms += size;
3473
3474           /* all parameters are passed via stack, since WREG is clobbered
3475            * by the calling sequence */
3476           while (size--) {
3477             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3478             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3479             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3480
3481             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3482             pushw();
3483           }
3484
3485           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3486       }
3487
3488       _G.stackRegSet = _G.sendSet;
3489       _G.sendSet = NULL;
3490     }
3491
3492     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3493
3494     // push return address
3495     // push $ on return stack, then replace with retlbl
3496
3497     /* Thanks to Thorsten Klose for pointing out that the following
3498      * snippet should be interrupt safe */
3499     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3500     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3501
3502     pic16_emitpcodeNULLop(POC_PUSH);
3503
3504     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3505     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3506     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3507     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3508     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3509     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3510
3511
3512     /* restore interrupt control register */
3513     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3514     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3515
3516     /* make the call by writing the pointer into pc */
3517     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3518     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3519
3520     // note: MOVFF to PCL not allowed
3521     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3522     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3523
3524
3525     /* return address is here: (X) */
3526     pic16_emitpLabelFORCE(retlbl->key);
3527
3528     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3529
3530     GpsuedoStkPtr=0;
3531     /* if we need assign a result value */
3532     if ((IS_ITEMP(IC_RESULT(ic))
3533           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3534               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3535         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3536
3537       _G.accInUse++;
3538       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3539       _G.accInUse--;
3540
3541       assignResultValue(IC_RESULT(ic), 1);
3542
3543       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3544               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3545                 
3546       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3547     }
3548
3549 //    stackParms -= use_wreg;
3550     
3551     if(stackParms>0) {
3552       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3553       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3554       if(STACK_MODEL_LARGE) {
3555         emitSKPNC;
3556         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3557       }
3558     }
3559 }
3560
3561 /*-----------------------------------------------------------------*/
3562 /* resultRemat - result  is rematerializable                       */
3563 /*-----------------------------------------------------------------*/
3564 static int resultRemat (iCode *ic)
3565 {
3566   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3567   if (SKIP_IC(ic) || ic->op == IFX)
3568     return 0;
3569
3570   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3571     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3572     if (sym->remat && !POINTER_SET(ic)) 
3573       return 1;
3574   }
3575
3576   return 0;
3577 }
3578
3579 #if defined(__BORLANDC__) || defined(_MSC_VER)
3580 #define STRCASECMP stricmp
3581 #else
3582 #define STRCASECMP strcasecmp
3583 #endif
3584
3585 #if 0
3586 /*-----------------------------------------------------------------*/
3587 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3588 /*-----------------------------------------------------------------*/
3589 static bool inExcludeList(char *s)
3590 {
3591   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3592     int i =0;
3593     
3594     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3595     if (options.excludeRegs[i] &&
3596     STRCASECMP(options.excludeRegs[i],"none") == 0)
3597         return FALSE ;
3598
3599     for ( i = 0 ; options.excludeRegs[i]; i++) {
3600         if (options.excludeRegs[i] &&
3601         STRCASECMP(s,options.excludeRegs[i]) == 0)
3602             return TRUE;
3603     }
3604     return FALSE ;
3605 }
3606 #endif
3607
3608 /*-----------------------------------------------------------------*/
3609 /* genFunction - generated code for function entry                 */
3610 /*-----------------------------------------------------------------*/
3611 static void genFunction (iCode *ic)
3612 {
3613   symbol *sym;
3614   sym_link *ftype;
3615   
3616     FENTRY;
3617     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3618
3619     pic16_labelOffset += (max_key+4);
3620     max_key=0;
3621     GpsuedoStkPtr=0;
3622     _G.nRegsSaved = 0;
3623         
3624     ftype = operandType(IC_LEFT(ic));
3625     sym = OP_SYMBOL(IC_LEFT(ic));
3626
3627     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3628       /* create an absolute section at the interrupt vector:
3629        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3630       symbol *asym;
3631       char asymname[128];
3632       pBlock *apb;
3633
3634 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3635
3636         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3637           sprintf(asymname, "ivec_%s", sym->name);
3638         else
3639           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3640   
3641         /* when an interrupt is declared as naked, do not emit the special
3642          * wrapper segment at vector address. The user should take care for
3643          * this instead. -- VR */
3644
3645         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3646           asym = newSymbol(asymname, 0);
3647           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3648           pic16_addpBlock( apb );
3649
3650           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3651           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3652           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3653           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3654           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3655                 
3656           /* mark the end of this tiny function */
3657           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3658         } else {
3659           sprintf(asymname, "%s", sym->rname);
3660         }
3661
3662         {
3663           absSym *abSym;
3664
3665             abSym = Safe_calloc(1, sizeof(absSym));
3666             strcpy(abSym->name, asymname);
3667
3668             switch( FUNC_INTNO(sym->type) ) {
3669               case 0: abSym->address = 0x000000; break;
3670               case 1: abSym->address = 0x000008; break;
3671               case 2: abSym->address = 0x000018; break;
3672               
3673               default:
3674 //                fprintf(stderr, "no interrupt number is given\n");
3675                 abSym->address = -1; break;
3676             }
3677
3678             /* relocate interrupt vectors if needed */
3679             if(abSym->address != -1)
3680               abSym->address += pic16_options.ivt_loc;
3681
3682             addSet(&absSymSet, abSym);
3683         }
3684     }
3685
3686     /* create the function header */
3687     pic16_emitcode(";","-----------------------------------------");
3688     pic16_emitcode(";"," function %s",sym->name);
3689     pic16_emitcode(";","-----------------------------------------");
3690
3691     pic16_emitcode("","%s:",sym->rname);
3692     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3693
3694     {
3695       absSym *ab;
3696
3697         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3698           if(!strcmp(ab->name, sym->rname)) {
3699             pic16_pBlockConvert2Absolute(pb);
3700             break;
3701           }
3702         }
3703     }
3704
3705     if(IFFUNC_ISNAKED(ftype)) {
3706       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3707       return;
3708     }
3709         
3710     /* if critical function then turn interrupts off */
3711     if (IFFUNC_ISCRITICAL(ftype)) {
3712       //pic16_emitcode("clr","ea");
3713     }
3714
3715     currFunc = sym;             /* update the currFunc symbol */
3716     _G.fregsUsed = sym->regsUsed;
3717     _G.sregsAlloc = newBitVect(128);
3718     
3719
3720     /* if this is an interrupt service routine then
3721      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3722     if (IFFUNC_ISISR(sym->type)) {
3723         _G.usefastretfie = 1;   /* use shadow registers by default */
3724         
3725         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3726         if(!FUNC_ISSHADOWREGS(sym->type)) {
3727           /* do not save WREG,STATUS,BSR for high priority interrupts
3728            * because they are stored in the hardware shadow registers already */
3729           _G.usefastretfie = 0;
3730           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3731           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3732           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3733         }
3734
3735         /* these should really be optimized somehow, because not all
3736          * interrupt handlers modify them */
3737         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3738         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3739         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3740         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3741         
3742 //        pic16_pBlockConvert2ISR(pb);
3743     }
3744
3745     /* emit code to setup stack frame if user enabled,
3746      * and function is not main() */
3747     
3748 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3749     if(strcmp(sym->name, "main")) {
3750       if(0 
3751         || !options.ommitFramePtr 
3752 //        || sym->regsUsed
3753         || IFFUNC_ARGS(sym->type)
3754         || FUNC_HASSTACKPARM(sym->etype)
3755         ) {
3756         /* setup the stack frame */
3757         if(STACK_MODEL_LARGE)
3758           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3759         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3760
3761         if(STACK_MODEL_LARGE)
3762           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3763         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3764       }
3765     }
3766
3767     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3768           && sym->stack) {
3769
3770       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3771
3772       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3773       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3774       emitSKPC;
3775       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3776     }
3777           
3778     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3779       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3780         _G.useWreg = 0;
3781       else
3782         _G.useWreg = 1;
3783     } else
3784       _G.useWreg = 0;
3785
3786     /* if callee-save to be used for this function
3787      * then save the registers being used in this function */
3788 //    if (IFFUNC_CALLEESAVES(sym->type))
3789     if(strcmp(sym->name, "main")) {
3790       int i;
3791
3792         /* if any registers used */
3793         if (sym->regsUsed) {
3794                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3795
3796           if(!xinst) {
3797             /* save the registers used */
3798             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3799             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3800               if (bitVectBitValue(sym->regsUsed,i)) {
3801 #if 0
3802                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3803 #endif
3804                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3805                 _G.nRegsSaved++;
3806
3807                 if(!pic16_regWithIdx(i)->wasUsed) {
3808                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3809                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3810                   pic16_regWithIdx(i)->wasUsed = 1;
3811                 }
3812               }
3813             }
3814           } else {
3815             
3816             /* xinst */
3817             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3818             for(i=0;i<sym->regsUsed->size;i++) {
3819               if(bitVectBitValue(sym->regsUsed, i)) {
3820                 _G.nRegsSaved++;
3821               }
3822             }
3823                         
3824 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3825           }
3826
3827           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3828
3829         }
3830     }
3831         
3832     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3833 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3834 }
3835
3836 /*-----------------------------------------------------------------*/
3837 /* genEndFunction - generates epilogue for functions               */
3838 /*-----------------------------------------------------------------*/
3839 static void genEndFunction (iCode *ic)
3840 {
3841   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3842
3843     FENTRY;
3844
3845     if(IFFUNC_ISNAKED(sym->type)) {
3846       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3847       return;
3848     }
3849
3850     _G.stack_lat = 0;
3851
3852     /* add code for ISCRITICAL */
3853     if(IFFUNC_ISCRITICAL(sym->type)) {
3854       /* if critical function, turn on interrupts */
3855       
3856       /* TODO: add code here -- VR */
3857     }
3858     
3859 //    sym->regsUsed = _G.fregsUsed;
3860     
3861     /* now we need to restore the registers */
3862     /* if any registers used */
3863
3864     /* first restore registers that might be used for stack access */
3865     if(_G.sregsAllocSet) {
3866     regs *sr;
3867     
3868       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3869       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3870         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3871       }
3872     }
3873
3874     if (strcmp(sym->name, "main") && sym->regsUsed) {
3875       int i;
3876
3877         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3878         /* restore registers used */
3879         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3880         for ( i = sym->regsUsed->size; i >= 0; i--) {
3881           if (bitVectBitValue(sym->regsUsed,i)) {
3882             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3883             _G.nRegsSaved--;
3884           }
3885         }
3886         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3887     }
3888
3889       
3890
3891     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3892           && sym->stack) {
3893       if (sym->stack == 1) {
3894         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3895         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3896       } else {
3897         // we have to add more than one...
3898         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3899         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3900         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3901         emitSKPNC;
3902         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3903         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3904         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3905       }
3906     }
3907
3908     if(strcmp(sym->name, "main")) {
3909       if(0
3910         || !options.ommitFramePtr
3911 //        || sym->regsUsed
3912         || IFFUNC_ARGS(sym->type)
3913         || FUNC_HASSTACKPARM(sym->etype)
3914         ) {
3915         /* restore stack frame */
3916         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3917         if(STACK_MODEL_LARGE)
3918           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3919       }
3920     }
3921
3922     _G.useWreg = 0;
3923
3924     if (IFFUNC_ISISR(sym->type)) {
3925       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3926       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3927       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3928       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3929
3930       if(!FUNC_ISSHADOWREGS(sym->type)) {
3931         /* do not restore interrupt vector for WREG,STATUS,BSR
3932          * for high priority interrupt, see genFunction */
3933         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3934         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3935         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3936       }
3937 //      _G.interruptvector = 0;         /* sanity check */
3938
3939
3940       /* if debug then send end of function */
3941 /*      if (options.debug && currFunc)  */
3942       if (currFunc) {
3943         debugFile->writeEndFunction (currFunc, ic, 1);
3944       }
3945         
3946       if(_G.usefastretfie)
3947         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3948       else
3949         pic16_emitpcodeNULLop(POC_RETFIE);
3950
3951       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3952       
3953       _G.usefastretfie = 0;
3954       return;
3955     }
3956
3957     if (IFFUNC_ISCRITICAL(sym->type)) {
3958       pic16_emitcode("setb","ea");
3959     }
3960
3961     /* if debug then send end of function */
3962     if (currFunc) {
3963       debugFile->writeEndFunction (currFunc, ic, 1);
3964     }
3965
3966     /* insert code to restore stack frame, if user enabled it
3967      * and function is not main() */
3968          
3969
3970     pic16_emitpcodeNULLop(POC_RETURN);
3971
3972     /* Mark the end of a function */
3973     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3974 }
3975
3976
3977 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3978 {
3979   unsigned long lit=1;
3980   operand *op;
3981
3982     op = IC_LEFT(ic);
3983   
3984     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3985     if(AOP_TYPE(op) == AOP_LIT) {
3986       if(!IS_FLOAT(operandType( op ))) {
3987         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3988       } else {
3989         union {
3990           unsigned long lit_int;
3991           float lit_float;
3992         } info;
3993         
3994         /* take care if literal is a float */
3995         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3996         lit = info.lit_int;
3997       }
3998     }
3999
4000     if (AOP_TYPE(op) == AOP_LIT) {
4001       /* FIXME: broken for
4002        *   char __at(0x456) foo;
4003        *   return &foo;
4004        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4005       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4006     } else if (AOP_TYPE(op) == AOP_PCODE
4007                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4008       /* char *s= "aaa"; return s; */
4009       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4010        *      that the generic pointer is interpreted correctly
4011        *      as referring to __code space, but this is fragile! */
4012       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4013       /* XXX: should check that dest != WREG */
4014       pic16_emitpcode(POC_MOVWF, dest);
4015     } else {
4016       if(dest->type == PO_WREG && (offset == 0)) {
4017         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4018         return;
4019       }
4020       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4021     }
4022 }
4023
4024 /*-----------------------------------------------------------------*/
4025 /* genRet - generate code for return statement                     */
4026 /*-----------------------------------------------------------------*/
4027 static void genRet (iCode *ic)
4028 {
4029   int size;
4030   operand *left;
4031
4032     FENTRY;
4033         /* if we have no return value then
4034          * just generate the "ret" */
4035         
4036         if (!IC_LEFT(ic)) 
4037                 goto jumpret;       
4038     
4039         /* we have something to return then
4040          * move the return value into place */
4041         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4042         size = AOP_SIZE(IC_LEFT(ic));
4043
4044         if(size <= 4) {
4045           if(size>3)
4046             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4047           
4048           if(size>2)
4049             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4050
4051           if(size>1)
4052             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4053           
4054           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4055
4056         } else {
4057                 /* >32-bits, setup stack and FSR0 */
4058                 while (size--) {
4059 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4060 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4061
4062                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4063
4064 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4065                         GpsuedoStkPtr++;
4066                 }
4067                         
4068                 /* setup FSR0 */
4069                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4070                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4071
4072                 if(STACK_MODEL_LARGE) {
4073                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4074                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4075                 } else {
4076                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4077                 }
4078         }
4079                                 
4080 #if 0
4081         /* old code, left here for reference -- VR */    
4082         while (size--) {
4083           char *l ;
4084
4085                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4086                         /* #NOCHANGE */
4087                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4088                         pic16_emitpcomment("push %s",l);
4089                         pushed++;
4090                 } else {
4091                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4092                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4093                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4094                         
4095                         if (strcmp(fReturn[offset],l)) {
4096                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4097                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4098                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4099                                 } else {
4100                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4101                                 }
4102                                 
4103                                 if(size) {
4104                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4105                                 }
4106                                 offset++;
4107                         }
4108                 }
4109         }    
4110
4111         if (pushed) {
4112                 while(pushed) {
4113                         pushed--;
4114                         if (strcmp(fReturn[pushed],"a"))
4115                                 pic16_emitcode("pop",fReturn[pushed]);
4116                         else
4117                                 pic16_emitcode("pop","acc");
4118                 }
4119         }
4120 #endif
4121
4122
4123         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4124     
4125 jumpret:
4126         /* generate a jump to the return label
4127          * if the next is not the return statement */
4128         if (!(ic->next && ic->next->op == LABEL
4129                 && IC_LABEL(ic->next) == returnLabel)) {
4130         
4131                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4132                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4133         }
4134 }
4135
4136 /*-----------------------------------------------------------------*/
4137 /* genLabel - generates a label                                    */
4138 /*-----------------------------------------------------------------*/
4139 static void genLabel (iCode *ic)
4140 {
4141   FENTRY;
4142
4143   /* special case never generate */
4144   if (IC_LABEL(ic) == entryLabel)
4145     return ;
4146
4147   pic16_emitpLabel(IC_LABEL(ic)->key);
4148 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4149 }
4150
4151 /*-----------------------------------------------------------------*/
4152 /* genGoto - generates a goto                                      */
4153 /*-----------------------------------------------------------------*/
4154 //tsd
4155 static void genGoto (iCode *ic)
4156 {
4157   FENTRY;
4158   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4159 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4160 }
4161
4162
4163 /*-----------------------------------------------------------------*/
4164 /* genMultbits :- multiplication of bits                           */
4165 /*-----------------------------------------------------------------*/
4166 static void genMultbits (operand *left, 
4167                          operand *right, 
4168                          operand *result)
4169 {
4170   FENTRY;
4171
4172   if(!pic16_sameRegs(AOP(result),AOP(right)))
4173     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4174
4175   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4176   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4177   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4178
4179 }
4180
4181
4182 /*-----------------------------------------------------------------*/
4183 /* genMultOneByte : 8 bit multiplication & division                */
4184 /*-----------------------------------------------------------------*/
4185 static void genMultOneByte (operand *left,
4186                             operand *right,
4187                             operand *result)
4188 {
4189
4190   FENTRY;
4191   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4192   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4193
4194   /* (if two literals, the value is computed before) */
4195   /* if one literal, literal on the right */
4196   if (AOP_TYPE(left) == AOP_LIT){
4197     operand *t = right;
4198     right = left;
4199     left = t;
4200   }
4201
4202         /* size is already checked in genMult == 1 */
4203 //      size = AOP_SIZE(result);
4204
4205         if (AOP_TYPE(right) == AOP_LIT){
4206                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4207                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4208                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4209                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4210         } else {
4211                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4212                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4213                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4214                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4215         }
4216         
4217         pic16_genMult8X8_8 (left, right,result);
4218 }
4219
4220 /*-----------------------------------------------------------------*/
4221 /* genMultOneWord : 16 bit multiplication                          */
4222 /*-----------------------------------------------------------------*/
4223 static void genMultOneWord (operand *left,
4224                             operand *right,
4225                             operand *result)
4226 {
4227   FENTRY;
4228   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4229   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4230
4231   /* (if two literals, the value is computed before)
4232    * if one literal, literal on the right */
4233   if (AOP_TYPE(left) == AOP_LIT){
4234     operand *t = right;
4235     right = left;
4236     left = t;
4237   }
4238
4239   /* size is checked already == 2 */
4240 //  size = AOP_SIZE(result);
4241
4242   if (AOP_TYPE(right) == AOP_LIT) {
4243     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4244       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4245       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4246       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4247   } else {
4248     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4249       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4250       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4251       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4252   }
4253         
4254   pic16_genMult16X16_16(left, right,result);
4255 }
4256
4257 /*-----------------------------------------------------------------*/
4258 /* genMultOneLong : 32 bit multiplication                          */
4259 /*-----------------------------------------------------------------*/
4260 static void genMultOneLong (operand *left,
4261                             operand *right,
4262                             operand *result)
4263 {
4264   FENTRY;
4265   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4266   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4267
4268   /* (if two literals, the value is computed before)
4269    * if one literal, literal on the right */
4270   if (AOP_TYPE(left) == AOP_LIT){
4271     operand *t = right;
4272     right = left;
4273     left = t;
4274   }
4275
4276   /* size is checked already == 4 */
4277 //  size = AOP_SIZE(result);
4278
4279   if (AOP_TYPE(right) == AOP_LIT) {
4280     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4281         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4282         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4283         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4284   } else {
4285     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4286         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4287         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4288         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4289   }
4290         
4291   pic16_genMult32X32_32(left, right,result);
4292 }
4293
4294
4295
4296 /*-----------------------------------------------------------------*/
4297 /* genMult - generates code for multiplication                     */
4298 /*-----------------------------------------------------------------*/
4299 static void genMult (iCode *ic)
4300 {
4301   operand *left = IC_LEFT(ic);
4302   operand *right = IC_RIGHT(ic);
4303   operand *result= IC_RESULT(ic);   
4304
4305     FENTRY;
4306         /* assign the amsops */
4307         pic16_aopOp (left,ic,FALSE);
4308         pic16_aopOp (right,ic,FALSE);
4309         pic16_aopOp (result,ic,TRUE);
4310
4311         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4312
4313         /* special cases first *
4314         * both are bits */
4315         if (AOP_TYPE(left) == AOP_CRY
4316                 && AOP_TYPE(right)== AOP_CRY) {
4317                 genMultbits(left,right,result);
4318           goto release ;
4319         }
4320
4321         /* if both are of size == 1 */
4322         if(AOP_SIZE(left) == 1
4323                 && AOP_SIZE(right) == 1) {
4324                 genMultOneByte(left,right,result);
4325           goto release ;
4326         }
4327
4328         /* if both are of size == 2 */
4329         if(AOP_SIZE(left) == 2
4330                 && AOP_SIZE(right) == 2) {
4331                 genMultOneWord(left, right, result);
4332           goto release;
4333         }
4334         
4335         /* if both are of size == 4 */
4336         if(AOP_SIZE(left) == 4
4337                 && AOP_SIZE(right) == 4) {
4338                 genMultOneLong(left, right, result);
4339           goto release;
4340         }
4341         
4342         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4343
4344
4345         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4346         /* should have been converted to function call */
4347         assert(0) ;
4348
4349 release :
4350         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4351         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4352         pic16_freeAsmop(result,NULL,ic,TRUE); 
4353 }
4354
4355 /*-----------------------------------------------------------------*/
4356 /* genDivbits :- division of bits                                  */
4357 /*-----------------------------------------------------------------*/
4358 static void genDivbits (operand *left, 
4359                         operand *right, 
4360                         operand *result)
4361 {
4362   char *l;
4363
4364     FENTRY;
4365     /* the result must be bit */    
4366     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4367     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4368
4369     MOVA(l);    
4370
4371     pic16_emitcode("div","ab");
4372     pic16_emitcode("rrc","a");
4373     pic16_aopPut(AOP(result),"c",0);
4374 }
4375
4376 /*-----------------------------------------------------------------*/
4377 /* genDivOneByte : 8 bit division                                  */
4378 /*-----------------------------------------------------------------*/
4379 static void genDivOneByte (operand *left,
4380                            operand *right,
4381                            operand *result)
4382 {
4383   sym_link *opetype = operandType(result);
4384   char *l ;
4385   symbol *lbl ;
4386   int size,offset;
4387
4388         /* result = divident / divisor
4389          * - divident may be a register or a literal,
4390          * - divisor may be a register or a literal,
4391          * so there are 3 cases (literal / literal is optimized
4392          * by the front-end) to handle.
4393          * In addition we must handle signed and unsigned, which
4394          * result in 6 final different cases -- VR */
4395
4396     FENTRY;
4397     
4398     size = AOP_SIZE(result) - 1;
4399     offset = 1;
4400     /* signed or unsigned */
4401     if (SPEC_USIGN(opetype)) {
4402       pCodeOp *pct1,    /* count */
4403                 *pct2,  /* reste */
4404                 *pct3;  /* temp */
4405       symbol *label1, *label2, *label3;;
4406
4407
4408         /* unsigned is easy */
4409
4410         pct1 = pic16_popGetTempReg(1);
4411         pct2 = pic16_popGetTempReg(1);
4412         pct3 = pic16_popGetTempReg(1);
4413         
4414         label1 = newiTempLabel(NULL);
4415         label2 = newiTempLabel(NULL);
4416         label3 = newiTempLabel(NULL);
4417
4418         /* the following algorithm is extracted from divuint.c */
4419
4420         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4421         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4422         
4423         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4424
4425         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4426         
4427         pic16_emitpLabel(label1->key);
4428         
4429         emitCLRC;
4430         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4431
4432
4433         emitCLRC;
4434         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4435         
4436
4437         emitSKPNC;
4438         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4439         
4440         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4441         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4442         
4443         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4444         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4445         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4446         
4447         pic16_emitpLabel( label3->key );
4448         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4449         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4450         
4451         
4452
4453         pic16_emitpLabel(label2->key);
4454         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4455         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4456         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4457         
4458         /* result is in wreg */
4459         if(AOP_TYPE(result) != AOP_ACC)
4460                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4461
4462         pic16_popReleaseTempReg( pct3, 1);
4463         pic16_popReleaseTempReg( pct2, 1);
4464         pic16_popReleaseTempReg( pct1, 1);
4465
4466         return ;
4467     }
4468
4469     /* signed is a little bit more difficult */
4470
4471     /* save the signs of the operands */
4472     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4473     MOVA(l);    
4474     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4475     pic16_emitcode("push","acc"); /* save it on the stack */
4476
4477     /* now sign adjust for both left & right */
4478     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4479     MOVA(l);       
4480     lbl = newiTempLabel(NULL);
4481     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4482     pic16_emitcode("cpl","a");   
4483     pic16_emitcode("inc","a");
4484     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4485     pic16_emitcode("mov","b,a");
4486
4487     /* sign adjust left side */
4488     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4489     MOVA(l);
4490
4491     lbl = newiTempLabel(NULL);
4492     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4493     pic16_emitcode("cpl","a");
4494     pic16_emitcode("inc","a");
4495     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4496
4497     /* now the division */
4498     pic16_emitcode("div","ab");
4499     /* we are interested in the lower order
4500     only */
4501     pic16_emitcode("mov","b,a");
4502     lbl = newiTempLabel(NULL);
4503     pic16_emitcode("pop","acc");   
4504     /* if there was an over flow we don't 
4505     adjust the sign of the result */
4506     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4507     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4508     CLRC;
4509     pic16_emitcode("clr","a");
4510     pic16_emitcode("subb","a,b");
4511     pic16_emitcode("mov","b,a");
4512     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4513
4514     /* now we are done */
4515     pic16_aopPut(AOP(result),"b",0);
4516     if(size > 0){
4517         pic16_emitcode("mov","c,b.7");
4518         pic16_emitcode("subb","a,acc");   
4519     }
4520     while (size--)
4521         pic16_aopPut(AOP(result),"a",offset++);
4522
4523 }
4524
4525 /*-----------------------------------------------------------------*/
4526 /* genDiv - generates code for division                            */
4527 /*-----------------------------------------------------------------*/
4528 static void genDiv (iCode *ic)
4529 {
4530     operand *left = IC_LEFT(ic);
4531     operand *right = IC_RIGHT(ic);
4532     operand *result= IC_RESULT(ic);   
4533
4534
4535         /* Division is a very lengthy algorithm, so it is better
4536          * to call support routines than inlining algorithm.
4537          * Division functions written here just in case someone
4538          * wants to inline and not use the support libraries -- VR */
4539
4540     FENTRY;
4541     
4542     /* assign the amsops */
4543     pic16_aopOp (left,ic,FALSE);
4544     pic16_aopOp (right,ic,FALSE);
4545     pic16_aopOp (result,ic,TRUE);
4546
4547     /* special cases first */
4548     /* both are bits */
4549     if (AOP_TYPE(left) == AOP_CRY &&
4550         AOP_TYPE(right)== AOP_CRY) {
4551         genDivbits(left,right,result);
4552         goto release ;
4553     }
4554
4555     /* if both are of size == 1 */
4556     if (AOP_SIZE(left) == 1 &&
4557         AOP_SIZE(right) == 1 ) {
4558         genDivOneByte(left,right,result);
4559         goto release ;
4560     }
4561
4562     /* should have been converted to function call */
4563     assert(0);
4564 release :
4565     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4566     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4567     pic16_freeAsmop(result,NULL,ic,TRUE); 
4568 }
4569
4570 /*-----------------------------------------------------------------*/
4571 /* genModbits :- modulus of bits                                   */
4572 /*-----------------------------------------------------------------*/
4573 static void genModbits (operand *left, 
4574                         operand *right, 
4575                         operand *result)
4576 {
4577   char *l;
4578
4579     FENTRY;  
4580     
4581     werror(W_POSSBUG2, __FILE__, __LINE__);
4582     /* the result must be bit */    
4583     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4584     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4585
4586     MOVA(l);       
4587
4588     pic16_emitcode("div","ab");
4589     pic16_emitcode("mov","a,b");
4590     pic16_emitcode("rrc","a");
4591     pic16_aopPut(AOP(result),"c",0);
4592 }
4593
4594 /*-----------------------------------------------------------------*/
4595 /* genModOneByte : 8 bit modulus                                   */
4596 /*-----------------------------------------------------------------*/
4597 static void genModOneByte (operand *left,
4598                            operand *right,
4599                            operand *result)
4600 {
4601   sym_link *opetype = operandType(result);
4602   char *l ;
4603   symbol *lbl ;
4604
4605     FENTRY;
4606     werror(W_POSSBUG2, __FILE__, __LINE__);
4607
4608     /* signed or unsigned */
4609     if (SPEC_USIGN(opetype)) {
4610         /* unsigned is easy */
4611         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4612         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4613         MOVA(l);    
4614         pic16_emitcode("div","ab");
4615         pic16_aopPut(AOP(result),"b",0);
4616         return ;
4617     }
4618
4619     /* signed is a little bit more difficult */
4620
4621     /* save the signs of the operands */
4622     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4623     MOVA(l);
4624
4625     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4626     pic16_emitcode("push","acc"); /* save it on the stack */
4627
4628     /* now sign adjust for both left & right */
4629     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4630     MOVA(l);
4631
4632     lbl = newiTempLabel(NULL);
4633     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4634     pic16_emitcode("cpl","a");   
4635     pic16_emitcode("inc","a");
4636     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4637     pic16_emitcode("mov","b,a"); 
4638
4639     /* sign adjust left side */
4640     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4641     MOVA(l);
4642
4643     lbl = newiTempLabel(NULL);
4644     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4645     pic16_emitcode("cpl","a");   
4646     pic16_emitcode("inc","a");
4647     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4648
4649     /* now the multiplication */
4650     pic16_emitcode("div","ab");
4651     /* we are interested in the lower order
4652     only */
4653     lbl = newiTempLabel(NULL);
4654     pic16_emitcode("pop","acc");   
4655     /* if there was an over flow we don't 
4656     adjust the sign of the result */
4657     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4658     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4659     CLRC ;
4660     pic16_emitcode("clr","a");
4661     pic16_emitcode("subb","a,b");
4662     pic16_emitcode("mov","b,a");
4663     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4664
4665     /* now we are done */
4666     pic16_aopPut(AOP(result),"b",0);
4667
4668 }
4669
4670 /*-----------------------------------------------------------------*/
4671 /* genMod - generates code for division                            */
4672 /*-----------------------------------------------------------------*/
4673 static void genMod (iCode *ic)
4674 {
4675   operand *left = IC_LEFT(ic);
4676   operand *right = IC_RIGHT(ic);
4677   operand *result= IC_RESULT(ic);  
4678
4679     FENTRY;
4680     
4681     /* assign the amsops */
4682     pic16_aopOp (left,ic,FALSE);
4683     pic16_aopOp (right,ic,FALSE);
4684     pic16_aopOp (result,ic,TRUE);
4685
4686     /* special cases first */
4687     /* both are bits */
4688     if (AOP_TYPE(left) == AOP_CRY &&
4689         AOP_TYPE(right)== AOP_CRY) {
4690         genModbits(left,right,result);
4691         goto release ;
4692     }
4693
4694     /* if both are of size == 1 */
4695     if (AOP_SIZE(left) == 1 &&
4696         AOP_SIZE(right) == 1 ) {
4697         genModOneByte(left,right,result);
4698         goto release ;
4699     }
4700
4701     /* should have been converted to function call */
4702     assert(0);
4703
4704 release :
4705     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4706     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4707     pic16_freeAsmop(result,NULL,ic,TRUE); 
4708 }
4709
4710 /*-----------------------------------------------------------------*/
4711 /* genIfxJump :- will create a jump depending on the ifx           */
4712 /*-----------------------------------------------------------------*/
4713 /*
4714   note: May need to add parameter to indicate when a variable is in bit space.
4715 */
4716 static void genIfxJump (iCode *ic, char *jval)
4717 {
4718   FENTRY;
4719   
4720     /* if true label then we jump if condition
4721     supplied is true */
4722     if ( IC_TRUE(ic) ) {
4723
4724         if(strcmp(jval,"a") == 0)
4725           emitSKPZ;
4726         else if (strcmp(jval,"c") == 0)
4727           emitSKPNC;
4728         else {
4729           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4730           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4731         }
4732
4733         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4734         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4735
4736     }
4737     else {
4738         /* false label is present */
4739         if(strcmp(jval,"a") == 0)
4740           emitSKPNZ;
4741         else if (strcmp(jval,"c") == 0)
4742           emitSKPC;
4743         else {
4744           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4745           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4746         }
4747
4748         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4749         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4750
4751     }
4752
4753
4754     /* mark the icode as generated */
4755     ic->generated = 1;
4756 }
4757
4758 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4759 {
4760   FENTRY;
4761   
4762     /* if true label then we jump if condition
4763     supplied is true */
4764     if ( IC_TRUE(ic) ) {
4765       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4766       pic16_emitpcode(POC_BTFSC, jop);
4767
4768       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4769       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4770
4771     } else {
4772       /* false label is present */
4773       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4774       pic16_emitpcode(POC_BTFSS, jop);
4775           
4776       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4777       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4778     }
4779
4780
4781     /* mark the icode as generated */
4782     ic->generated = 1;
4783 }
4784
4785 #if 0
4786 // not needed ATM
4787
4788 /*-----------------------------------------------------------------*/
4789 /* genSkip                                                         */
4790 /*-----------------------------------------------------------------*/
4791 static void genSkip(iCode *ifx,int status_bit)
4792 {
4793   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4794   if(!ifx)
4795     return;
4796
4797   if ( IC_TRUE(ifx) ) {
4798     switch(status_bit) {
4799     case 'z':
4800       emitSKPNZ;
4801       break;
4802
4803     case 'c':
4804       emitSKPNC;
4805       break;
4806
4807     case 'd':
4808       emitSKPDC;
4809       break;
4810
4811     }
4812
4813     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4814     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4815
4816   } else {
4817
4818     switch(status_bit) {
4819
4820     case 'z':
4821       emitSKPZ;
4822       break;
4823
4824     case 'c':
4825       emitSKPC;
4826       break;
4827
4828     case 'd':
4829       emitSKPDC;
4830       break;
4831     }
4832     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4833     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4834
4835   }
4836
4837 }
4838 #endif
4839
4840 /*-----------------------------------------------------------------*/
4841 /* genSkipc                                                        */
4842 /*-----------------------------------------------------------------*/
4843 static void genSkipc(resolvedIfx *rifx)
4844 {
4845   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4846   
4847   if(!rifx)
4848     return;
4849
4850   if(rifx->condition)
4851     emitSKPNC;
4852   else
4853     emitSKPC;
4854
4855   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4856   rifx->generated = 1;
4857 }
4858
4859 #if !(USE_SIMPLE_GENCMP)
4860 /*-----------------------------------------------------------------*/
4861 /* genSkipz2                                                       */
4862 /*-----------------------------------------------------------------*/
4863 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4864 {
4865   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4866   
4867   if(!rifx)
4868     return;
4869
4870   if( (rifx->condition ^ invert_condition) & 1)
4871     emitSKPZ;
4872   else
4873     emitSKPNZ;
4874
4875   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4876   rifx->generated = 1;
4877 }
4878 #endif
4879
4880 #if 0
4881 /*-----------------------------------------------------------------*/
4882 /* genSkipz                                                        */
4883 /*-----------------------------------------------------------------*/
4884 static void genSkipz(iCode *ifx, int condition)
4885 {
4886   if(!ifx)
4887     return;
4888
4889   if(condition)
4890     emitSKPNZ;
4891   else
4892     emitSKPZ;
4893
4894   if ( IC_TRUE(ifx) )
4895     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4896   else
4897     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4898
4899   if ( IC_TRUE(ifx) )
4900     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4901   else
4902     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4903
4904 }
4905 #endif
4906
4907 #if !(USE_SIMPLE_GENCMP)
4908 /*-----------------------------------------------------------------*/
4909 /* genSkipCond                                                     */
4910 /*-----------------------------------------------------------------*/
4911 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4912 {
4913   if(!rifx)
4914     return;
4915
4916   if(rifx->condition)
4917     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4918   else
4919     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4920
4921
4922   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4923   rifx->generated = 1;
4924 }
4925 #endif
4926
4927 #if 0
4928 /*-----------------------------------------------------------------*/
4929 /* genChkZeroes :- greater or less than comparison                 */
4930 /*     For each byte in a literal that is zero, inclusive or the   */
4931 /*     the corresponding byte in the operand with W                */
4932 /*     returns true if any of the bytes are zero                   */
4933 /*-----------------------------------------------------------------*/
4934 static int genChkZeroes(operand *op, int lit,  int size)
4935 {
4936
4937   int i;
4938   int flag =1;
4939
4940   while(size--) {
4941     i = (lit >> (size*8)) & 0xff;
4942
4943     if(i==0) {
4944       if(flag) 
4945         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4946       else
4947         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4948       flag = 0;
4949     }
4950   }
4951
4952   return (flag==0);
4953 }
4954 #endif
4955
4956
4957 /*-----------------------------------------------------------------*/
4958 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4959 /*                  aop (if it's NOT a literal) or from lit (if    */
4960 /*                  aop is a literal)                              */
4961 /*-----------------------------------------------------------------*/
4962 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4963   if (aop->type == AOP_LIT) {
4964     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4965   } else {
4966     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4967   }
4968 }
4969
4970 /*-----------------------------------------------------------------*/
4971 /* genCmp :- greater or less than comparison                       */
4972 /*-----------------------------------------------------------------*/
4973
4974 #if USE_SIMPLE_GENCMP           /* { */
4975
4976 /* genCmp performs a left < right comparison, stores
4977  * the outcome in result (if != NULL) and generates
4978  * control flow code for the ifx (if != NULL).
4979  *
4980  * This version leaves in sequences like
4981  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4982  * which should be optmized by the peephole
4983  * optimizer - RN 2005-01-01 */
4984 static void genCmp (operand *left,operand *right,
4985                     operand *result, iCode *ifx, int sign)
4986 {
4987   resolvedIfx rIfx;
4988   int size;
4989   int offs;
4990   symbol *templbl;
4991   operand *dummy;
4992   unsigned long lit;
4993   unsigned long mask;
4994   int performedLt;
4995
4996   FENTRY;
4997   
4998   assert (left && right);
4999   assert (AOP_SIZE(left) == AOP_SIZE(right));
5000
5001   size = AOP_SIZE(right) - 1;
5002   mask = (0x100UL << (size*8)) - 1;
5003   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5004   performedLt = 1;
5005   templbl = NULL;
5006   lit = 0;
5007   
5008   resolveIfx (&rIfx, ifx);
5009
5010   /* handle for special cases */
5011   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5012       return;
5013
5014   /**********************************************************************
5015    * handle bits - bit compares are promoted to int compares seemingly! *
5016    **********************************************************************/
5017 #if 0
5018   // THIS IS COMPLETELY UNTESTED!
5019   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5020     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5021     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5022     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5023
5024     emitSETC;
5025     // 1 < {0,1} is false --> clear C by skipping the next instruction
5026     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5027     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5028     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5029     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5030     emitCLRC; // only skipped for left=0 && right=1
5031
5032     goto correct_result_in_carry;
5033   } // if
5034 #endif
5035
5036   /*************************************************
5037    * make sure that left is register (or the like) *
5038    *************************************************/
5039   if (!isAOP_REGlike(left)) {
5040     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5041     assert (isAOP_LIT(left));
5042     assert (isAOP_REGlike(right));
5043     // swap left and right
5044     // left < right <==> right > left <==> (right >= left + 1)
5045     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5046
5047     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5048       // MAXVALUE < right? always false
5049       if (performedLt) emitCLRC; else emitSETC;
5050       goto correct_result_in_carry;
5051     } // if
5052
5053     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5054     // that's why we handled it above.
5055     lit++;
5056
5057     dummy = left;
5058     left = right;
5059     right = dummy;
5060
5061     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5062   } else if (isAOP_LIT(right)) {
5063     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5064   } // if
5065
5066   assert (isAOP_REGlike(left)); // left must be register or the like
5067   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5068
5069   /*************************************************
5070    * special cases go here                         *
5071    *************************************************/
5072
5073   if (isAOP_LIT(right)) {
5074     if (!sign) {
5075       // unsigned comparison to a literal
5076       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5077       if (lit == 0) {
5078         // unsigned left < 0? always false
5079         if (performedLt) emitCLRC; else emitSETC;
5080         goto correct_result_in_carry;
5081       }
5082     } else {
5083       // signed comparison to a literal
5084       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5085       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5086         // signed left < 0x80000000? always false
5087         if (performedLt) emitCLRC; else emitSETC;
5088         goto correct_result_in_carry;
5089       } else if (lit == 0) {
5090         // compare left < 0; set CARRY if SIGNBIT(left) is set
5091         if (performedLt) emitSETC; else emitCLRC;
5092         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5093         if (performedLt) emitCLRC; else emitSETC;
5094         goto correct_result_in_carry;
5095       }
5096     } // if (!sign)
5097   } // right is literal
5098
5099   /*************************************************
5100    * perform a general case comparison             *
5101    * make sure we get CARRY==1 <==> left >= right  *
5102    *************************************************/
5103   // compare most significant bytes
5104   //DEBUGpc ("comparing bytes at offset %d", size);
5105   if (!sign) {
5106     // unsigned comparison
5107     mov2w_regOrLit (AOP(right), lit, size);
5108     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5109   } else {
5110     // signed comparison
5111     // (add 2^n to both operands then perform an unsigned comparison)
5112     if (isAOP_LIT(right)) {
5113       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5114       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5115
5116       if (litbyte == 0x80) {
5117         // left >= 0x80 -- always true, but more bytes to come
5118         pic16_mov2w (AOP(left), size);
5119         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5120         emitSETC;
5121       } else {
5122         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5123         pic16_mov2w (AOP(left), size);
5124         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5125         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5126       } // if
5127     } else {
5128       /* using PRODL as a temporary register here */
5129       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5130       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5131       pic16_mov2w (AOP(left), size);
5132       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5133       pic16_emitpcode (POC_MOVWF, pctemp);
5134       pic16_mov2w (AOP(right), size);
5135       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5136       pic16_emitpcode (POC_SUBFW, pctemp);
5137       //pic16_popReleaseTempReg(pctemp, 1);
5138     }
5139   } // if (!sign)
5140
5141   // compare remaining bytes (treat as unsigned case from above)
5142   templbl = newiTempLabel ( NULL );
5143   offs = size;
5144   while (offs--) {
5145     //DEBUGpc ("comparing bytes at offset %d", offs);
5146     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5147     mov2w_regOrLit (AOP(right), lit, offs);
5148     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5149   } // while (offs)
5150   pic16_emitpLabel (templbl->key);
5151   goto result_in_carry;
5152
5153 result_in_carry:
5154   
5155   /****************************************************
5156    * now CARRY contains the result of the comparison: *
5157    * SUBWF sets CARRY iff                             *
5158    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5159    * (F=left, W=right)                                *
5160    ****************************************************/
5161
5162   if (performedLt) {
5163     if (result && AOP_TYPE(result) != AOP_CRY) {
5164       // value will be stored
5165       emitTOGC;
5166     } else {
5167       // value wil only be used in the following genSkipc()
5168       rIfx.condition ^= 1;
5169     }
5170   } // if
5171
5172 correct_result_in_carry:
5173
5174   // assign result to variable (if neccessary)
5175   if (result && AOP_TYPE(result) != AOP_CRY) {
5176     //DEBUGpc ("assign result");
5177     size = AOP_SIZE(result);
5178     while (size--) {
5179       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5180     } // while
5181     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5182   } // if (result)
5183
5184   // perform conditional jump
5185   if (ifx) {
5186     //DEBUGpc ("generate control flow");
5187     genSkipc (&rIfx);
5188     ifx->generated = 1;
5189   } // if
5190 }
5191
5192 #elif 1         /* } */
5193                 /* { */
5194       /* original code */
5195 static void genCmp (operand *left,operand *right,
5196                     operand *result, iCode *ifx, int sign)
5197 {
5198   int size; //, offset = 0 ;
5199   unsigned long lit = 0L,i = 0;
5200   resolvedIfx rFalseIfx;
5201   //  resolvedIfx rTrueIfx;
5202   symbol *truelbl;
5203   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5204 /*
5205   if(ifx) {
5206     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5207     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5208   }
5209 */
5210
5211   FENTRY;
5212   
5213   resolveIfx(&rFalseIfx,ifx);
5214   truelbl  = newiTempLabel(NULL);
5215   size = max(AOP_SIZE(left),AOP_SIZE(right));
5216
5217   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5218
5219 #define _swapp
5220
5221   /* if literal is on the right then swap with left */
5222   if ((AOP_TYPE(right) == AOP_LIT)) {
5223     operand *tmp = right ;
5224     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5225     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5226 #ifdef _swapp
5227
5228     lit = (lit - 1) & mask;
5229     right = left;
5230     left = tmp;
5231     rFalseIfx.condition ^= 1;
5232 #endif
5233
5234   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5235     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5236   }
5237
5238
5239   //if(IC_TRUE(ifx) == NULL)
5240   /* if left & right are bit variables */
5241   if (AOP_TYPE(left) == AOP_CRY &&
5242       AOP_TYPE(right) == AOP_CRY ) {
5243     assert (0 && "bit variables used in genCmp");
5244     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5245     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5246   } else {
5247     /* subtract right from left if at the
5248        end the carry flag is set then we know that
5249        left is greater than right */
5250
5251     symbol *lbl  = newiTempLabel(NULL);
5252
5253 #if 0
5254         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5255                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5256 #endif
5257
5258 #ifndef _swapp
5259     if(AOP_TYPE(right) == AOP_LIT) {
5260
5261       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5262
5263       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5264
5265       /* special cases */
5266
5267       if(lit == 0) {
5268
5269         if(sign != 0) 
5270           genSkipCond(&rFalseIfx,left,size-1,7);
5271         else 
5272           /* no need to compare to 0...*/
5273           /* NOTE: this is a de-generate compare that most certainly 
5274            *       creates some dead code. */
5275           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5276
5277         if(ifx) ifx->generated = 1;
5278         return;
5279
5280       }
5281       size--;
5282
5283       if(size == 0) {
5284         //i = (lit >> (size*8)) & 0xff;
5285         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5286         
5287         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5288
5289         i = ((0-lit) & 0xff);
5290         if(sign) {
5291           if( i == 0x81) { 
5292             /* lit is 0x7f, all signed chars are less than
5293              * this except for 0x7f itself */
5294             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5295             genSkipz2(&rFalseIfx,0);
5296           } else {
5297             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5298             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5299             genSkipc(&rFalseIfx);
5300           }
5301
5302         } else {
5303           if(lit == 1) {
5304             genSkipz2(&rFalseIfx,1);
5305           } else {
5306             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5307             genSkipc(&rFalseIfx);
5308           }
5309         }
5310
5311         if(ifx) ifx->generated = 1;
5312         return;
5313       }
5314
5315       /* chars are out of the way. now do ints and longs */
5316
5317
5318       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5319         
5320       /* special cases */
5321
5322       if(sign) {
5323
5324         if(lit == 0) {
5325           genSkipCond(&rFalseIfx,left,size,7);
5326           if(ifx) ifx->generated = 1;
5327           return;
5328         }
5329
5330         if(lit <0x100) {
5331           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5332
5333           //rFalseIfx.condition ^= 1;
5334           //genSkipCond(&rFalseIfx,left,size,7);
5335           //rFalseIfx.condition ^= 1;
5336
5337           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5338           if(rFalseIfx.condition)
5339             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5340           else
5341             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5342
5343           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5344           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5345           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5346
5347           while(size > 1)
5348             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5349
5350           if(rFalseIfx.condition) {
5351             emitSKPZ;
5352             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5353
5354           } else {
5355             emitSKPNZ;
5356           }
5357
5358           genSkipc(&rFalseIfx);
5359           pic16_emitpLabel(truelbl->key);
5360           if(ifx) ifx->generated = 1;
5361           return;
5362
5363         }
5364
5365         if(size == 1) {
5366
5367           if( (lit & 0xff) == 0) {
5368             /* lower byte is zero */
5369             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5370             i = ((lit >> 8) & 0xff) ^0x80;
5371             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5372             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5373             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5374             genSkipc(&rFalseIfx);
5375
5376
5377             if(ifx) ifx->generated = 1;
5378             return;
5379
5380           }
5381         } else {
5382           /* Special cases for signed longs */
5383           if( (lit & 0xffffff) == 0) {
5384             /* lower byte is zero */
5385             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5386             i = ((lit >> 8*3) & 0xff) ^0x80;
5387             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5388             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5389             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5390             genSkipc(&rFalseIfx);
5391
5392
5393             if(ifx) ifx->generated = 1;
5394             return;
5395
5396           }
5397
5398         }
5399
5400
5401         if(lit & (0x80 << (size*8))) {
5402           /* lit is negative */
5403           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5404
5405           //genSkipCond(&rFalseIfx,left,size,7);
5406
5407           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5408
5409           if(rFalseIfx.condition)
5410             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5411           else
5412             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5413
5414
5415         } else {
5416           /* lit is positive */
5417           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5418           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5419           if(rFalseIfx.condition)
5420             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5421           else
5422             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5423
5424         }
5425
5426         /*
5427           This works, but is only good for ints.
5428           It also requires a "known zero" register.
5429           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5430           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5431           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5432           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5433           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5434           genSkipc(&rFalseIfx);
5435
5436           pic16_emitpLabel(truelbl->key);
5437           if(ifx) ifx->generated = 1;
5438           return;
5439         **/
5440           
5441         /* There are no more special cases, so perform a general compare */
5442   
5443         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5444         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5445
5446         while(size--) {
5447
5448           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5449           emitSKPNZ;
5450           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5451         }
5452         //rFalseIfx.condition ^= 1;
5453         genSkipc(&rFalseIfx);
5454
5455         pic16_emitpLabel(truelbl->key);
5456
5457         if(ifx) ifx->generated = 1;
5458         return;
5459
5460
5461       }
5462
5463
5464       /* sign is out of the way. So now do an unsigned compare */
5465       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5466
5467
5468       /* General case - compare to an unsigned literal on the right.*/
5469
5470       i = (lit >> (size*8)) & 0xff;
5471       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5472       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5473       while(size--) {
5474         i = (lit >> (size*8)) & 0xff;
5475
5476         if(i) {
5477           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5478           emitSKPNZ;
5479           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5480         } else {
5481           /* this byte of the lit is zero, 
5482            *if it's not the last then OR in the variable */
5483           if(size)
5484             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5485         }
5486       }
5487
5488
5489       pic16_emitpLabel(lbl->key);
5490 //      pic16_emitpLabel(truelbl->key);
5491       //if(emitFinalCheck)
5492       genSkipc(&rFalseIfx);
5493       if(sign)
5494         pic16_emitpLabel(truelbl->key);
5495
5496       if(ifx) ifx->generated = 1;
5497       return;
5498
5499
5500     }
5501 #endif  // _swapp
5502
5503     if(AOP_TYPE(left) == AOP_LIT) {
5504       //symbol *lbl = newiTempLabel(NULL);
5505
5506       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5507
5508
5509       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5510
5511       /* Special cases */
5512       if((lit == 0) && (sign == 0)){
5513
5514         size--;
5515         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5516         while(size) 
5517           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5518
5519         genSkipz2(&rFalseIfx,0);
5520         if(ifx) ifx->generated = 1;
5521         return;
5522       }
5523
5524       if(size==1) {
5525         /* Special cases */
5526         lit &= 0xff;
5527         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5528           /* degenerate compare can never be true */
5529           if(rFalseIfx.condition == 0)
5530             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5531
5532           if(ifx) ifx->generated = 1;
5533           return;
5534         }
5535
5536         if(sign) {
5537           /* signed comparisons to a literal byte */
5538
5539           int lp1 = (lit+1) & 0xff;
5540
5541           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5542           switch (lp1) {
5543           case 0:
5544             rFalseIfx.condition ^= 1;
5545             genSkipCond(&rFalseIfx,right,0,7);
5546             break;
5547           case 0x7f:
5548             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5549             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5550             genSkipz2(&rFalseIfx,1);
5551             break;
5552           default:
5553             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5554             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5555             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5556             rFalseIfx.condition ^= 1;
5557             genSkipc(&rFalseIfx);
5558             break;
5559           }
5560         } else {
5561           /* unsigned comparisons to a literal byte */
5562
5563           switch(lit & 0xff ) {
5564           case 0:
5565             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5566             genSkipz2(&rFalseIfx,0);
5567             break;
5568           case 0x7f:
5569             rFalseIfx.condition ^= 1;
5570             genSkipCond(&rFalseIfx,right,0,7);
5571             break;
5572
5573           default:
5574             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5575             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5576             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5577             rFalseIfx.condition ^= 1;
5578             if (AOP_TYPE(result) == AOP_CRY)
5579               genSkipc(&rFalseIfx);
5580             else {
5581               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5582               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5583             }         
5584             break;
5585           }
5586         }
5587
5588         if(ifx) ifx->generated = 1;
5589         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5590                 goto check_carry;
5591         return;
5592
5593       } else {
5594
5595         /* Size is greater than 1 */
5596
5597         if(sign) {
5598           int lp1 = lit+1;
5599
5600           size--;
5601
5602           if(lp1 == 0) {
5603             /* this means lit = 0xffffffff, or -1 */
5604
5605
5606             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5607             rFalseIfx.condition ^= 1;
5608             genSkipCond(&rFalseIfx,right,size,7);
5609             if(ifx) ifx->generated = 1;
5610
5611             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5612               goto check_carry;
5613
5614             return;
5615           }
5616
5617           if(lit == 0) {
5618             int s = size;
5619
5620             if(rFalseIfx.condition) {
5621               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5622               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5623             }
5624
5625             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5626             while(size--)
5627               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5628
5629
5630             emitSKPZ;
5631             if(rFalseIfx.condition) {
5632               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5633               pic16_emitpLabel(truelbl->key);
5634             }else {
5635               rFalseIfx.condition ^= 1;
5636               genSkipCond(&rFalseIfx,right,s,7);
5637             }
5638
5639             if(ifx) ifx->generated = 1;
5640
5641             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5642               goto check_carry;
5643
5644             return;
5645           }
5646
5647           if((size == 1) &&  (0 == (lp1&0xff))) {
5648             /* lower byte of signed word is zero */
5649             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5650             i = ((lp1 >> 8) & 0xff) ^0x80;
5651             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5652             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5653             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5654
5655             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5656               emitTOGC;
5657               if(ifx) ifx->generated = 1;
5658               goto check_carry;
5659             } else {
5660               rFalseIfx.condition ^= 1;
5661               genSkipc(&rFalseIfx);
5662               if(ifx) ifx->generated = 1;
5663             }
5664
5665             return;
5666           }
5667
5668           if(lit & (0x80 << (size*8))) {
5669             /* Lit is less than zero */
5670             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5671             //rFalseIfx.condition ^= 1;
5672             //genSkipCond(&rFalseIfx,left,size,7);
5673             //rFalseIfx.condition ^= 1;
5674             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5675             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5676
5677             if(rFalseIfx.condition)
5678               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5679             else
5680               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5681
5682
5683           } else {
5684             /* Lit is greater than or equal to zero */
5685             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5686             //rFalseIfx.condition ^= 1;
5687             //genSkipCond(&rFalseIfx,right,size,7);
5688             //rFalseIfx.condition ^= 1;
5689
5690             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5691             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5692
5693             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5694             if(rFalseIfx.condition)
5695               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5696             else
5697               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5698
5699           }
5700
5701           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5702           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5703
5704           while(size--) {
5705
5706             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5707             emitSKPNZ;
5708             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5709           }
5710           rFalseIfx.condition ^= 1;
5711           //rFalseIfx.condition = 1;
5712           genSkipc(&rFalseIfx);
5713
5714           pic16_emitpLabel(truelbl->key);
5715
5716           if(ifx) ifx->generated = 1;
5717
5718
5719           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5720             goto check_carry;
5721
5722           return;
5723           // end of if (sign)
5724         } else {
5725
5726           /* compare word or long to an unsigned literal on the right.*/
5727
5728
5729           size--;
5730           if(lit < 0xff) {
5731             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5732             switch (lit) {
5733             case 0:
5734               break; /* handled above */
5735 /*
5736             case 0xff:
5737               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5738               while(size--)
5739                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5740               genSkipz2(&rFalseIfx,0);
5741               break;
5742 */
5743             default:
5744               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5745               while(--size)
5746                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5747
5748               emitSKPZ;
5749               if(rFalseIfx.condition)
5750                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5751               else
5752                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5753
5754
5755               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5756               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5757
5758               rFalseIfx.condition ^= 1;
5759               genSkipc(&rFalseIfx);
5760             }
5761
5762             pic16_emitpLabel(truelbl->key);
5763
5764             if(ifx) ifx->generated = 1;
5765
5766             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5767               goto check_carry;
5768
5769             return;
5770           }
5771
5772
5773           lit++;
5774           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5775           i = (lit >> (size*8)) & 0xff;
5776
5777           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5778           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5779
5780           while(size--) {
5781             i = (lit >> (size*8)) & 0xff;
5782
5783             if(i) {
5784               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5785               emitSKPNZ;
5786               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5787             } else {
5788               /* this byte of the lit is zero, 
5789                * if it's not the last then OR in the variable */
5790               if(size)
5791                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5792             }
5793           }
5794
5795
5796           pic16_emitpLabel(lbl->key);
5797
5798           rFalseIfx.condition ^= 1;
5799
5800           genSkipc(&rFalseIfx);
5801         }
5802
5803         if(sign)
5804           pic16_emitpLabel(truelbl->key);
5805         if(ifx) ifx->generated = 1;
5806
5807             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5808               goto check_carry;
5809
5810         return;
5811       }
5812     }
5813     /* Compare two variables */
5814
5815     DEBUGpic16_emitcode(";sign","%d",sign);
5816
5817     size--;
5818     if(sign) {
5819       /* Sigh. thus sucks... */
5820       if(size) {
5821         pCodeOp *pctemp;
5822         
5823         pctemp = pic16_popGetTempReg(1);
5824         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5825         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5826         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5827         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5829         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5830         pic16_popReleaseTempReg(pctemp, 1);
5831       } else {
5832         /* Signed char comparison */
5833         /* Special thanks to Nikolai Golovchenko for this snippet */
5834         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5835         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5836         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5837         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5838         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5839         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5840
5841         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5842         genSkipc(&rFalseIfx);
5843           
5844         if(ifx) ifx->generated = 1;
5845
5846             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5847               goto check_carry;
5848
5849         return;
5850       }
5851
5852     } else {
5853
5854       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5855       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5856     }
5857
5858
5859     /* The rest of the bytes of a multi-byte compare */
5860     while (size) {
5861
5862       emitSKPZ;
5863       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5864       size--;
5865
5866       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5867       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5868
5869
5870     }
5871
5872     pic16_emitpLabel(lbl->key);
5873
5874     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5875     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5876         (AOP_TYPE(result) == AOP_REG)) {
5877       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5878       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5879     } else {
5880       genSkipc(&rFalseIfx);
5881     }         
5882     //genSkipc(&rFalseIfx);
5883     if(ifx) ifx->generated = 1;
5884
5885
5886             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5887               goto check_carry;
5888
5889     return;
5890
5891   }
5892
5893 check_carry:
5894   if ((AOP_TYPE(result) != AOP_CRY) 
5895         && AOP_SIZE(result)) {
5896     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5897
5898     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5899
5900     pic16_outBitC(result);
5901   } else {
5902     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5903     /* if the result is used in the next
5904        ifx conditional branch then generate
5905        code a little differently */
5906     if (ifx )
5907       genIfxJump (ifx,"c");
5908     else
5909       pic16_outBitC(result);
5910     /* leave the result in acc */
5911   }
5912
5913 }
5914
5915 #elif 0 /* VR version of genCmp() */    /* } else { */
5916
5917 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5918 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5919         operand *result, int offset, int invert_op)
5920 {
5921   /* add code here */
5922   
5923   /* check condition, > or < ?? */
5924   if(rIfx->condition != 0)invert_op ^= 1;
5925   
5926   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5927
5928   if(!ifx)invert_op ^= 1;
5929
5930   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5931       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5932   
5933   /* do selection */
5934   if(!invert_op)return POC_CPFSGT;
5935   else return POC_CPFSLT;
5936 }
5937
5938 static int compareAopfirstpass=1;
5939
5940 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5941             operand *oper, int offset, operand *result,
5942             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5943             symbol *tlbl)
5944 {
5945   int op;
5946   symbol *truelbl;
5947
5948   /* invert if there is a result to be loaded, in order to fit,
5949    * SETC/CLRC sequence */
5950   if(AOP_SIZE(result))invert_op ^= 1;
5951
5952 //  if(sign && !offset)invert_op ^= 1;
5953   
5954 //  if(sign)invert_op ^= 1;
5955   
5956   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5957
5958   if(AOP_SIZE(result) && compareAopfirstpass) {
5959     if(!ifx) {
5960       if(pcop2)
5961         pic16_emitpcode(POC_SETF, pcop2);
5962       else
5963         emitSETC;
5964     } else {
5965       if(pcop2)
5966         pic16_emitpcode(POC_CLRF, pcop2);
5967       else
5968         emitCLRC;
5969     }
5970   }
5971
5972   compareAopfirstpass = 0;
5973
5974       /* there is a bug when comparing operands with size > 1,
5975        * because higher bytes can be equal and test should be performed
5976        * to the next lower byte, current algorithm, considers operands
5977        * inequal in these cases! -- VR 20041107 */
5978
5979     
5980   if(pcop)
5981     pic16_emitpcode(op, pcop);
5982   else
5983     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5984
5985
5986   if((!sign || !offset) && AOP_SIZE(result)) {
5987     if(!ifx) {
5988       if(pcop2)
5989         pic16_emitpcode(POC_CLRF, pcop2);
5990         else
5991         emitCLRC;
5992     } else {
5993       if(pcop2)
5994         pic16_emitpcode(POC_SETF, pcop2);
5995       else
5996         emitSETC;
5997     }
5998     
5999     /* don't emit final branch (offset == 0) */
6000     if(offset) {
6001
6002       if(pcop2)
6003         pic16_emitpcode(POC_RRCF, pcop2);
6004
6005       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6006     }
6007   } else {
6008     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6009       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6010             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6011
6012       truelbl = newiTempLabel( NULL );
6013       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6014       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6015         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6016       else
6017         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6018       pic16_emitpLabel(truelbl->key);
6019     } else {
6020       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6021     }
6022   }
6023 }
6024
6025 static void genCmp (operand *left, operand *right,
6026                     operand *result, iCode *ifx, int sign)
6027 {
6028   int size, cmpop=1;
6029   long lit = 0L;
6030   resolvedIfx rFalseIfx;
6031   symbol *falselbl, *tlbl;
6032
6033     FENTRY;
6034     
6035     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6036
6037     resolveIfx(&rFalseIfx, ifx);
6038     size = max(AOP_SIZE(left), AOP_SIZE(right));
6039     
6040     /* if left & right are bit variables */
6041     if(AOP_TYPE(left) == AOP_CRY
6042       && AOP_TYPE(right) == AOP_CRY ) {
6043
6044         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6045         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6046         
6047         werror(W_POSSBUG2, __FILE__, __LINE__);
6048         exit(-1);
6049     }
6050     
6051     /* if literal is on the right then swap with left */
6052     if((AOP_TYPE(right) == AOP_LIT)) {
6053       operand *tmp = right ;
6054 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6055
6056         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6057
6058 //      lit = (lit - 1) & mask;
6059         right = left;
6060         left = tmp;
6061         rFalseIfx.condition ^= 1;               /* reverse compare */
6062     } else
6063     if ((AOP_TYPE(left) == AOP_LIT)) {
6064       /* float compares are handled by support functions */
6065       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6066     }
6067
6068     /* actual comparing algorithm */
6069 //    size = AOP_SIZE( right );
6070
6071     falselbl = newiTempLabel( NULL );
6072     if(AOP_TYPE(left) == AOP_LIT) {
6073       /* compare to literal */
6074       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6075       
6076       if(sign) {
6077         pCodeOp *pct, *pct2;
6078         symbol *tlbl1;
6079
6080         /* signed compare */
6081         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6082
6083         /* using PRODL:PRODH as a temporary register here */
6084         pct = pic16_popCopyReg(&pic16_pc_prodl);
6085         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6086         tlbl = newiTempLabel( NULL );
6087         
6088         /* first compare signs:
6089          *  a. if both are positive, compare just like unsigned
6090          *  b. if both are negative, invert cmpop, compare just like unsigned
6091          *  c. if different signs, determine the result directly */
6092
6093         size--;
6094
6095 #if 1
6096         /* { */
6097         tlbl1 = newiTempLabel( NULL );
6098 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6099
6100         if(lit > 0) {
6101
6102           /* literal is zero or positive:
6103            *  a. if carry is zero, too, continue compare,
6104            *  b. if carry is set, then continue depending on cmpop ^ condition:
6105            *    1. '<' return false (literal < variable),
6106            *    2. '>' return true (literal > variable) */
6107 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6108           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6109           
6110           
6111           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6112           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6113         } else 
6114         if(lit < 0) {
6115           
6116           /* literal is negative:
6117            *  a. if carry is set, too, continue compare,
6118            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6119            *    1. '<' return true (literal < variable),
6120            *    2. '>' return false (literal > variable) */
6121 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6122           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6123           
6124           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6125           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6126         }
6127 #if 1
6128         else {
6129           /* lit == 0 */
6130           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6131           
6132           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6133           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6134         }
6135 #endif
6136         
6137         
6138         pic16_emitpLabel( tlbl1->key );
6139 #endif  /* } */
6140
6141         compareAopfirstpass=1;
6142 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6143 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6144 //        pic16_emitpcode(POC_MOVWF, pct);
6145
6146 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6147         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6148 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6149         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6150
6151         /* generic case */        
6152           while( size-- ) {
6153 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6154 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6155 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6156 //            pic16_emitpcode(POC_MOVWF, pct);
6157
6158 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6159             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6160             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6161 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6162 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6163           }
6164         
6165         if(ifx)ifx->generated = 1;
6166
6167         if(AOP_SIZE(result)) {
6168           pic16_emitpLabel(tlbl->key);
6169           pic16_emitpLabel(falselbl->key);
6170           pic16_outBitOp( result, pct2 );
6171         } else {
6172           pic16_emitpLabel(tlbl->key);
6173         }
6174       } else {
6175
6176         /* unsigned compare */      
6177         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6178     
6179         compareAopfirstpass=1;
6180         while(size--) {
6181           
6182           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6183           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6184
6185         }
6186         if(ifx)ifx->generated = 1;
6187
6188         if(AOP_SIZE(result)) {
6189           pic16_emitpLabel(falselbl->key);
6190           pic16_outBitC( result );
6191         }
6192
6193       }
6194     } else {
6195       /* compare registers */
6196       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6197
6198
6199       if(sign) {
6200         pCodeOp *pct, *pct2;
6201         
6202         /* signed compare */
6203         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6204
6205         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6206         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6207         tlbl = newiTempLabel( NULL );
6208         
6209         compareAopfirstpass=1;
6210
6211         size--;
6212         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6213 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6214         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6215         pic16_emitpcode(POC_MOVWF, pct);
6216
6217         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6218 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6219         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6220
6221         /* WREG already holds left + 0x80 */
6222         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6223         
6224         while( size-- ) {
6225           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6226 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6227           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6228           pic16_emitpcode(POC_MOVWF, pct);
6229                 
6230           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6231 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6232           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6233
6234           /* WREG already holds left + 0x80 */
6235           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6236 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6237         }
6238         
6239         if(ifx)ifx->generated = 1;
6240
6241         if(AOP_SIZE(result)) {
6242           pic16_emitpLabel(tlbl->key);
6243           pic16_emitpLabel(falselbl->key);
6244           pic16_outBitOp( result, pct2 );
6245         } else {
6246           pic16_emitpLabel(tlbl->key);
6247         }
6248
6249       } else {
6250         /* unsigned compare */      
6251         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6252
6253         compareAopfirstpass=1;
6254         while(size--) {
6255           
6256           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6257           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6258
6259         }
6260
6261         if(ifx)ifx->generated = 1;
6262         if(AOP_SIZE(result)) {
6263
6264           pic16_emitpLabel(falselbl->key);
6265           pic16_outBitC( result );
6266         }
6267
6268       }
6269     }
6270 }
6271
6272 #endif  /* } */
6273
6274
6275
6276 /*-----------------------------------------------------------------*/
6277 /* genCmpGt :- greater than comparison                             */
6278 /*-----------------------------------------------------------------*/
6279 static void genCmpGt (iCode *ic, iCode *ifx)
6280 {
6281   operand *left, *right, *result;
6282   sym_link *letype , *retype;
6283   int sign ;
6284
6285     FENTRY;
6286     
6287     left = IC_LEFT(ic);
6288     right= IC_RIGHT(ic);
6289     result = IC_RESULT(ic);
6290
6291     letype = getSpec(operandType(left));
6292     retype =getSpec(operandType(right));
6293     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6294     /* assign the amsops */
6295     pic16_aopOp (left,ic,FALSE);
6296     pic16_aopOp (right,ic,FALSE);
6297     pic16_aopOp (result,ic,TRUE);
6298
6299     genCmp(right, left, result, ifx, sign);
6300
6301     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6302     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6303     pic16_freeAsmop(result,NULL,ic,TRUE); 
6304 }
6305
6306 /*-----------------------------------------------------------------*/
6307 /* genCmpLt - less than comparisons                                */
6308 /*-----------------------------------------------------------------*/
6309 static void genCmpLt (iCode *ic, iCode *ifx)
6310 {
6311   operand *left, *right, *result;
6312   sym_link *letype , *retype;
6313   int sign ;
6314
6315     FENTRY;
6316
6317     left = IC_LEFT(ic);
6318     right= IC_RIGHT(ic);
6319     result = IC_RESULT(ic);
6320
6321     letype = getSpec(operandType(left));
6322     retype =getSpec(operandType(right));
6323     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6324
6325     /* assign the amsops */
6326     pic16_aopOp (left,ic,FALSE);
6327     pic16_aopOp (right,ic,FALSE);
6328     pic16_aopOp (result,ic,TRUE);
6329
6330     genCmp(left, right, result, ifx, sign);
6331
6332     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6333     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6334     pic16_freeAsmop(result,NULL,ic,TRUE); 
6335 }
6336
6337 #if 0
6338 // not needed ATM
6339 // FIXME reenable literal optimisation when the pic16 port is stable
6340
6341 /*-----------------------------------------------------------------*/
6342 /* genc16bit2lit - compare a 16 bit value to a literal             */
6343 /*-----------------------------------------------------------------*/
6344 static void genc16bit2lit(operand *op, int lit, int offset)
6345 {
6346   int i;
6347
6348   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6349   if( (lit&0xff) == 0) 
6350     i=1;
6351   else
6352     i=0;
6353
6354   switch( BYTEofLONG(lit,i)) { 
6355   case 0:
6356     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6357     break;
6358   case 1:
6359     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6360     break;
6361   case 0xff:
6362     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6363     break;
6364   default:
6365     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6366     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6367   }
6368
6369   i ^= 1;
6370
6371   switch( BYTEofLONG(lit,i)) { 
6372   case 0:
6373     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6374     break;
6375   case 1:
6376     emitSKPNZ;
6377     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6378     break;
6379   case 0xff:
6380     emitSKPNZ;
6381     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6382     break;
6383   default:
6384     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6385     emitSKPNZ;
6386     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6387
6388   }
6389
6390 }
6391 #endif
6392
6393 #if 0
6394 // not needed ATM
6395 /*-----------------------------------------------------------------*/
6396 /* gencjneshort - compare and jump if not equal                    */
6397 /*-----------------------------------------------------------------*/
6398 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6399 {
6400   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6401   int offset = 0;
6402   int res_offset = 0;  /* the result may be a different size then left or right */
6403   int res_size = AOP_SIZE(result);
6404   resolvedIfx rIfx;
6405   symbol *lbl, *lbl_done;
6406
6407   unsigned long lit = 0L;
6408   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6409
6410   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6411   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6412   if(result)
6413     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6414   resolveIfx(&rIfx,ifx);
6415   lbl =  newiTempLabel(NULL);
6416   lbl_done =  newiTempLabel(NULL);
6417
6418
6419   /* if the left side is a literal or 
6420      if the right is in a pointer register and left 
6421      is not */
6422   if ((AOP_TYPE(left) == AOP_LIT) || 
6423       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6424     operand *t = right;
6425     right = left;
6426     left = t;
6427   }
6428   if(AOP_TYPE(right) == AOP_LIT)
6429     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6430
6431   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6432     preserve_result = 1;
6433
6434   if(result && !preserve_result)
6435     {
6436       int i;
6437       for(i = 0; i < AOP_SIZE(result); i++)
6438         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6439     }
6440
6441
6442   /* if the right side is a literal then anything goes */
6443   if (AOP_TYPE(right) == AOP_LIT &&
6444       AOP_TYPE(left) != AOP_DIR ) {
6445     switch(size) {
6446     case 2:
6447       genc16bit2lit(left, lit, 0);
6448       emitSKPZ;
6449       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6450       break;
6451     default:
6452       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6453       while (size--) {
6454         if(lit & 0xff) {
6455           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6456           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6457         } else {
6458           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6459         }
6460
6461         emitSKPZ;
6462         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6463         offset++;
6464         if(res_offset < res_size-1)
6465           res_offset++;
6466         lit >>= 8;
6467       }
6468       break;
6469     }
6470   }
6471
6472   /* if the right side is in a register or in direct space or
6473      if the left is a pointer register & right is not */    
6474   else if (AOP_TYPE(right) == AOP_REG ||
6475            AOP_TYPE(right) == AOP_DIR || 
6476            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6477            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6478     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6479     int lbl_key = lbl->key;
6480
6481     if(result) {
6482       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6483       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6484     }else {
6485       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6486       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6487               __FUNCTION__,__LINE__);
6488       return;
6489     }
6490    
6491 /*     switch(size) { */
6492 /*     case 2: */
6493 /*       genc16bit2lit(left, lit, 0); */
6494 /*       emitSKPNZ; */
6495 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6496 /*       break; */
6497 /*     default: */
6498     while (size--) {
6499       int emit_skip=1;
6500       if((AOP_TYPE(left) == AOP_DIR) && 
6501          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6502
6503         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6504         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6505
6506       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6507             
6508         switch (lit & 0xff) {
6509         case 0:
6510           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6511           break;
6512         case 1:
6513           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6514           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6515           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6516           emit_skip=0;
6517           break;
6518         case 0xff:
6519           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6520           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6521           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6522           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6523           emit_skip=0;
6524           break;
6525         default:
6526           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6527           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6528         }
6529         lit >>= 8;
6530
6531       } else {
6532         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6533       }
6534       if(emit_skip) {
6535         if(AOP_TYPE(result) == AOP_CRY) {
6536           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6537           if(rIfx.condition)
6538             emitSKPNZ;
6539           else
6540             emitSKPZ;
6541           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6542         } else {
6543           /* fix me. probably need to check result size too */
6544           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6545           if(rIfx.condition)
6546             emitSKPZ;
6547           else
6548             emitSKPNZ;
6549           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6550           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6551         }
6552         if(ifx)
6553           ifx->generated=1;
6554       }
6555       emit_skip++;
6556       offset++;
6557       if(res_offset < res_size-1)
6558         res_offset++;
6559     }
6560 /*       break; */
6561 /*     } */
6562   } else if(AOP_TYPE(right) == AOP_REG &&
6563             AOP_TYPE(left) != AOP_DIR){
6564
6565     while(size--) {
6566       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6567       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6568       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6569       if(rIfx.condition)
6570         emitSKPNZ;
6571       else
6572         emitSKPZ;
6573       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6574       offset++;
6575       if(res_offset < res_size-1)
6576         res_offset++;
6577     }
6578       
6579   }else{
6580     /* right is a pointer reg need both a & b */
6581     while(size--) {
6582       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6583       if(strcmp(l,"b"))
6584         pic16_emitcode("mov","b,%s",l);
6585       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6586       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6587       offset++;
6588     }
6589   }
6590
6591   if(result && preserve_result)
6592     {
6593       int i;
6594       for(i = 0; i < AOP_SIZE(result); i++)
6595         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6596     }
6597
6598   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6599
6600   if(result && preserve_result)
6601     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6602
6603   if(!rIfx.condition)
6604     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6605
6606   pic16_emitpLabel(lbl->key);
6607
6608   if(result && preserve_result)
6609     {
6610       int i;
6611       for(i = 0; i < AOP_SIZE(result); i++)
6612         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6613
6614       pic16_emitpLabel(lbl_done->key);
6615    }
6616
6617   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6618
6619   if(ifx)
6620     ifx->generated = 1;
6621 }
6622 #endif
6623
6624 #if 0
6625 /*-----------------------------------------------------------------*/
6626 /* gencjne - compare and jump if not equal                         */
6627 /*-----------------------------------------------------------------*/
6628 static void gencjne(operand *left, operand *right, iCode *ifx)
6629 {
6630     symbol *tlbl  = newiTempLabel(NULL);
6631
6632     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6633     gencjneshort(left, right, lbl);
6634
6635     pic16_emitcode("mov","a,%s",one);
6636     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6637     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6638     pic16_emitcode("clr","a");
6639     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6640
6641     pic16_emitpLabel(lbl->key);
6642     pic16_emitpLabel(tlbl->key);
6643
6644 }
6645 #endif
6646
6647
6648 /*-----------------------------------------------------------------*/
6649 /* is_LitOp - check if operand has to be treated as literal        */
6650 /*-----------------------------------------------------------------*/
6651 static bool is_LitOp(operand *op)
6652 {
6653   return ((AOP_TYPE(op) == AOP_LIT)
6654       || ( (AOP_TYPE(op) == AOP_PCODE)
6655           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6656               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6657 }
6658
6659 /*-----------------------------------------------------------------*/
6660 /* is_LitAOp - check if operand has to be treated as literal        */
6661 /*-----------------------------------------------------------------*/
6662 static bool is_LitAOp(asmop *aop)
6663 {
6664   return ((aop->type == AOP_LIT)
6665       || ( (aop->type == AOP_PCODE)
6666           && ( (aop->aopu.pcop->type == PO_LITERAL)
6667               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6668 }
6669
6670
6671
6672 /*-----------------------------------------------------------------*/
6673 /* genCmpEq - generates code for equal to                          */
6674 /*-----------------------------------------------------------------*/
6675 static void genCmpEq (iCode *ic, iCode *ifx)
6676 {
6677   operand *left, *right, *result;
6678   symbol *falselbl = newiTempLabel(NULL);
6679   symbol *donelbl = newiTempLabel(NULL);
6680
6681   int preserve_result = 0;
6682   int generate_result = 0;
6683   int i=0;
6684   unsigned long lit = -1;
6685
6686   FENTRY;
6687   
6688   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6689   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6690   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6691  
6692   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6693
6694   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6695     {
6696       werror(W_POSSBUG2, __FILE__, __LINE__);
6697       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6698       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6699       goto release;
6700     }
6701
6702   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6703     {
6704       operand *tmp = right ;
6705       right = left;
6706       left = tmp;
6707     }
6708
6709   if (AOP_TYPE(right) == AOP_LIT) {
6710     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6711   }
6712
6713   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6714     preserve_result = 1;
6715
6716   if(result && AOP_SIZE(result))
6717     generate_result = 1;
6718
6719   if(generate_result && !preserve_result)
6720     {
6721       for(i = 0; i < AOP_SIZE(result); i++)
6722         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6723     }
6724
6725   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6726   for(i=0; i < AOP_SIZE(left); i++)
6727     {
6728       if(AOP_TYPE(left) != AOP_ACC)
6729         {
6730           if(is_LitOp(left))
6731             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6732           else
6733             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6734         }
6735       if(is_LitOp(right)) {
6736         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6737           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6738         }
6739       } else
6740         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6741
6742       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6743     }
6744
6745   // result == true
6746
6747   if(generate_result && preserve_result)
6748     {
6749       for(i = 0; i < AOP_SIZE(result); i++)
6750         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6751     }
6752
6753   if(generate_result)
6754     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6755
6756   if(generate_result && preserve_result)
6757     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6758
6759   if(ifx && IC_TRUE(ifx))
6760     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6761
6762   if(ifx && IC_FALSE(ifx))
6763     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6764
6765   pic16_emitpLabel(falselbl->key);
6766
6767   // result == false
6768
6769   if(ifx && IC_FALSE(ifx))
6770     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6771
6772   if(generate_result && preserve_result)
6773     {
6774       for(i = 0; i < AOP_SIZE(result); i++)
6775         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6776     }
6777
6778   pic16_emitpLabel(donelbl->key);
6779
6780   if(ifx)
6781     ifx->generated = 1;
6782
6783 release:
6784   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6785   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6786   pic16_freeAsmop(result,NULL,ic,TRUE);
6787
6788 }
6789
6790
6791 #if 0
6792 // old version kept for reference
6793
6794 /*-----------------------------------------------------------------*/
6795 /* genCmpEq - generates code for equal to                          */
6796 /*-----------------------------------------------------------------*/
6797 static void genCmpEq (iCode *ic, iCode *ifx)
6798 {
6799     operand *left, *right, *result;
6800     unsigned long lit = 0L;
6801     int size,offset=0;
6802     symbol *falselbl  = newiTempLabel(NULL);
6803
6804
6805     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6806
6807     if(ifx)
6808       DEBUGpic16_emitcode ("; ifx is non-null","");
6809     else
6810       DEBUGpic16_emitcode ("; ifx is null","");
6811
6812     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6813     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6814     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6815
6816     size = max(AOP_SIZE(left),AOP_SIZE(right));
6817
6818     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6819
6820     /* if literal, literal on the right or 
6821     if the right is in a pointer register and left 
6822     is not */
6823     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6824         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6825       operand *tmp = right ;
6826       right = left;
6827       left = tmp;
6828     }
6829
6830
6831     if(ifx && !AOP_SIZE(result)){
6832         symbol *tlbl;
6833         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6834         /* if they are both bit variables */
6835         if (AOP_TYPE(left) == AOP_CRY &&
6836             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6837                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6838             if(AOP_TYPE(right) == AOP_LIT){
6839                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6840                 if(lit == 0L){
6841                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6842                     pic16_emitcode("cpl","c");
6843                 } else if(lit == 1L) {
6844                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6845                 } else {
6846                     pic16_emitcode("clr","c");
6847                 }
6848                 /* AOP_TYPE(right) == AOP_CRY */
6849             } else {
6850                 symbol *lbl = newiTempLabel(NULL);
6851                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6852                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6853                 pic16_emitcode("cpl","c");
6854                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6855             }
6856             /* if true label then we jump if condition
6857             supplied is true */
6858             tlbl = newiTempLabel(NULL);
6859             if ( IC_TRUE(ifx) ) {
6860                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6861                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6862             } else {
6863                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6864                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6865             }
6866             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6867
6868                 {
6869                 /* left and right are both bit variables, result is carry */
6870                         resolvedIfx rIfx;
6871               
6872                         resolveIfx(&rIfx,ifx);
6873
6874                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6875                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6876                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6877                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6878                         genSkipz2(&rIfx,0);
6879                 }
6880         } else {
6881
6882                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6883
6884                         /* They're not both bit variables. Is the right a literal? */
6885                         if(AOP_TYPE(right) == AOP_LIT) {
6886                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6887             
6888                         switch(size) {
6889
6890                                 case 1:
6891                                         switch(lit & 0xff) {
6892                                                 case 1:
6893                                                                 if ( IC_TRUE(ifx) ) {
6894                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6895                                                                         emitSKPNZ;
6896                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6897                                                                 } else {
6898                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6899                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6900                                                                 }
6901                                                                 break;
6902                                                 case 0xff:
6903                                                                 if ( IC_TRUE(ifx) ) {
6904                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6905                                                                         emitSKPNZ;
6906                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6907                                                                 } else {
6908                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6909                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6910                                                                 }
6911                                                                 break;
6912                                                 default:
6913                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6914                                                                 if(lit)
6915                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6916                                                                 genSkip(ifx,'z');
6917                                         } // switch lit
6918
6919
6920                                         /* end of size == 1 */
6921                                         break;
6922               
6923                                 case 2:
6924                                         genc16bit2lit(left,lit,offset);
6925                                         genSkip(ifx,'z');
6926                                         break;
6927                                         /* end of size == 2 */
6928
6929                                 default:
6930                                         /* size is 4 */
6931                                         if(lit==0) {
6932                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6933                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6934                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6935                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6936                                                 genSkip(ifx,'z');
6937                                         } else {
6938                                                 /* search for patterns that can be optimized */
6939
6940                                                 genc16bit2lit(left,lit,0);
6941                                                 lit >>= 16;
6942                                                 if(lit) {
6943                                                                 if(IC_TRUE(ifx))
6944                                                                 emitSKPZ; // if hi word unequal
6945                                                                 else
6946                                                                 emitSKPNZ; // if hi word equal
6947                                                                 // fail early
6948                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6949                                                         genc16bit2lit(left,lit,2);
6950                                                         genSkip(ifx,'z');
6951                                                 } else {
6952                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6953                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6954                                                         genSkip(ifx,'z');
6955                                                 }
6956                                         }
6957                                                 pic16_emitpLabel(falselbl->key);
6958                                                 break;
6959
6960                         } // switch size
6961           
6962                         ifx->generated = 1;
6963                         goto release ;
6964             
6965
6966           } else if(AOP_TYPE(right) == AOP_CRY ) {
6967             /* we know the left is not a bit, but that the right is */
6968             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6969             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6970                       pic16_popGet(AOP(right),offset));
6971             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6972
6973             /* if the two are equal, then W will be 0 and the Z bit is set
6974              * we could test Z now, or go ahead and check the high order bytes if
6975              * the variable we're comparing is larger than a byte. */
6976
6977             while(--size)
6978               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6979
6980             if ( IC_TRUE(ifx) ) {
6981               emitSKPNZ;
6982               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6983               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6984             } else {
6985               emitSKPZ;
6986               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6987               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6988             }
6989
6990           } else {
6991             /* They're both variables that are larger than bits */
6992             int s = size;
6993
6994             tlbl = newiTempLabel(NULL);
6995
6996             while(size--) {
6997               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6998               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6999
7000               if ( IC_TRUE(ifx) ) {
7001                 if(size) {
7002                   emitSKPZ;
7003                 
7004                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7005
7006                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7007                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7008                 } else {
7009                   emitSKPNZ;
7010
7011                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7012
7013
7014                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7015                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7016                 }
7017               } else {
7018                 emitSKPZ;
7019
7020                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7021
7022                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7023                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7024               }
7025               offset++;
7026             }
7027             if(s>1 && IC_TRUE(ifx)) {
7028               pic16_emitpLabel(tlbl->key);
7029               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7030             }
7031           }
7032         }
7033         /* mark the icode as generated */
7034         ifx->generated = 1;
7035         goto release ;
7036     }
7037
7038     /* if they are both bit variables */
7039     if (AOP_TYPE(left) == AOP_CRY &&
7040         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7041         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7042         if(AOP_TYPE(right) == AOP_LIT){
7043             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7044             if(lit == 0L){
7045                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7046                 pic16_emitcode("cpl","c");
7047             } else if(lit == 1L) {
7048                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7049             } else {
7050                 pic16_emitcode("clr","c");
7051             }
7052             /* AOP_TYPE(right) == AOP_CRY */
7053         } else {
7054             symbol *lbl = newiTempLabel(NULL);
7055             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7056             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7057             pic16_emitcode("cpl","c");
7058             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7059         }
7060         /* c = 1 if egal */
7061         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7062             pic16_outBitC(result);
7063             goto release ;
7064         }
7065         if (ifx) {
7066             genIfxJump (ifx,"c");
7067             goto release ;
7068         }
7069         /* if the result is used in an arithmetic operation
7070         then put the result in place */
7071         pic16_outBitC(result);
7072     } else {
7073       
7074       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7075       gencjne(left,right,result,ifx);
7076 /*
7077       if(ifx) 
7078         gencjne(left,right,newiTempLabel(NULL));
7079       else {
7080         if(IC_TRUE(ifx)->key)
7081           gencjne(left,right,IC_TRUE(ifx)->key);
7082         else
7083           gencjne(left,right,IC_FALSE(ifx)->key);
7084         ifx->generated = 1;
7085         goto release ;
7086       }
7087       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7088         pic16_aopPut(AOP(result),"a",0);
7089         goto release ;
7090       }
7091
7092       if (ifx) {
7093         genIfxJump (ifx,"a");
7094         goto release ;
7095       }
7096 */
7097       /* if the result is used in an arithmetic operation
7098          then put the result in place */
7099 /*
7100       if (AOP_TYPE(result) != AOP_CRY) 
7101         pic16_outAcc(result);
7102 */
7103       /* leave the result in acc */
7104     }
7105
7106 release:
7107     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7108     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7109     pic16_freeAsmop(result,NULL,ic,TRUE);
7110 }
7111 #endif
7112
7113 /*-----------------------------------------------------------------*/
7114 /* ifxForOp - returns the icode containing the ifx for operand     */
7115 /*-----------------------------------------------------------------*/
7116 static iCode *ifxForOp ( operand *op, iCode *ic )
7117 {
7118   FENTRY2;
7119
7120     /* if true symbol then needs to be assigned */
7121     if (IS_TRUE_SYMOP(op))
7122         return NULL ;
7123
7124     /* if this has register type condition and
7125     the next instruction is ifx with the same operand
7126     and live to of the operand is upto the ifx only then */
7127     if (ic->next
7128         && ic->next->op == IFX
7129         && IC_COND(ic->next)->key == op->key
7130         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7131         ) {
7132                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7133           return ic->next;
7134     }
7135
7136     /*
7137     if (ic->next &&
7138         ic->next->op == IFX &&
7139         IC_COND(ic->next)->key == op->key) {
7140       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7141       return ic->next;
7142     }
7143     */
7144
7145     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7146     if (ic->next &&
7147         ic->next->op == IFX)
7148       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7149
7150     if (ic->next &&
7151         ic->next->op == IFX &&
7152         IC_COND(ic->next)->key == op->key) {
7153       DEBUGpic16_emitcode ("; "," key is okay");
7154       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7155                            OP_SYMBOL(op)->liveTo,
7156                            ic->next->seq);
7157     }
7158
7159 #if 0
7160     /* the code below is completely untested
7161      * it just allows ulong2fs.c compile -- VR */
7162          
7163     ic = ic->next;
7164     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7165                                         __FILE__, __FUNCTION__, __LINE__);
7166         
7167     /* if this has register type condition and
7168     the next instruction is ifx with the same operand
7169     and live to of the operand is upto the ifx only then */
7170     if (ic->next &&
7171         ic->next->op == IFX &&
7172         IC_COND(ic->next)->key == op->key &&
7173         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7174         return ic->next;
7175
7176     if (ic->next &&
7177         ic->next->op == IFX &&
7178         IC_COND(ic->next)->key == op->key) {
7179       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7180       return ic->next;
7181     }
7182
7183     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7184                                         __FILE__, __FUNCTION__, __LINE__);
7185
7186 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7187 #endif
7188
7189     return NULL;
7190 }
7191 /*-----------------------------------------------------------------*/
7192 /* genAndOp - for && operation                                     */
7193 /*-----------------------------------------------------------------*/
7194 static void genAndOp (iCode *ic)
7195 {
7196   operand *left,*right, *result;
7197 /*     symbol *tlbl; */
7198
7199     FENTRY;
7200
7201     /* note here that && operations that are in an
7202     if statement are taken away by backPatchLabels
7203     only those used in arthmetic operations remain */
7204     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7205     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7206     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7207
7208     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7209
7210     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7211     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7212     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7213
7214     /* if both are bit variables */
7215 /*     if (AOP_TYPE(left) == AOP_CRY && */
7216 /*         AOP_TYPE(right) == AOP_CRY ) { */
7217 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7218 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7219 /*         pic16_outBitC(result); */
7220 /*     } else { */
7221 /*         tlbl = newiTempLabel(NULL); */
7222 /*         pic16_toBoolean(left);     */
7223 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7224 /*         pic16_toBoolean(right); */
7225 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7226 /*         pic16_outBitAcc(result); */
7227 /*     } */
7228
7229     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7230     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7231     pic16_freeAsmop(result,NULL,ic,TRUE);
7232 }
7233
7234
7235 /*-----------------------------------------------------------------*/
7236 /* genOrOp - for || operation                                      */
7237 /*-----------------------------------------------------------------*/
7238 /*
7239   tsd pic port -
7240   modified this code, but it doesn't appear to ever get called
7241 */
7242
7243 static void genOrOp (iCode *ic)
7244 {
7245   operand *left,*right, *result;
7246   symbol *tlbl;
7247
7248     FENTRY;  
7249
7250   /* note here that || operations that are in an
7251     if statement are taken away by backPatchLabels
7252     only those used in arthmetic operations remain */
7253     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7254     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7255     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7256
7257     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7258
7259     /* if both are bit variables */
7260     if (AOP_TYPE(left) == AOP_CRY &&
7261         AOP_TYPE(right) == AOP_CRY ) {
7262       pic16_emitcode("clrc","");
7263       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7264                AOP(left)->aopu.aop_dir,
7265                AOP(left)->aopu.aop_dir);
7266       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7267                AOP(right)->aopu.aop_dir,
7268                AOP(right)->aopu.aop_dir);
7269       pic16_emitcode("setc","");
7270
7271     } else {
7272         tlbl = newiTempLabel(NULL);
7273         pic16_toBoolean(left);
7274         emitSKPZ;
7275         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7276         pic16_toBoolean(right);
7277         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7278
7279         pic16_outBitAcc(result);
7280     }
7281
7282     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7283     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7284     pic16_freeAsmop(result,NULL,ic,TRUE);            
7285 }
7286
7287 /*-----------------------------------------------------------------*/
7288 /* isLiteralBit - test if lit == 2^n                               */
7289 /*-----------------------------------------------------------------*/
7290 static int isLiteralBit(unsigned long lit)
7291 {
7292     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7293     0x100L,0x200L,0x400L,0x800L,
7294     0x1000L,0x2000L,0x4000L,0x8000L,
7295     0x10000L,0x20000L,0x40000L,0x80000L,
7296     0x100000L,0x200000L,0x400000L,0x800000L,
7297     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7298     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7299     int idx;
7300     
7301     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7302     for(idx = 0; idx < 32; idx++)
7303         if(lit == pw[idx])
7304             return idx+1;
7305     return 0;
7306 }
7307
7308 /*-----------------------------------------------------------------*/
7309 /* continueIfTrue -                                                */
7310 /*-----------------------------------------------------------------*/
7311 static void continueIfTrue (iCode *ic)
7312 {
7313   FENTRY;
7314   if(IC_TRUE(ic))
7315     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7316   ic->generated = 1;
7317 }
7318
7319 /*-----------------------------------------------------------------*/
7320 /* jmpIfTrue -                                                     */
7321 /*-----------------------------------------------------------------*/
7322 static void jumpIfTrue (iCode *ic)
7323 {
7324   FENTRY;
7325   if(!IC_TRUE(ic))
7326     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7327   ic->generated = 1;
7328 }
7329
7330 /*-----------------------------------------------------------------*/
7331 /* jmpTrueOrFalse -                                                */
7332 /*-----------------------------------------------------------------*/
7333 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7334 {
7335   // ugly but optimized by peephole
7336   FENTRY;
7337   if(IC_TRUE(ic)){
7338     symbol *nlbl = newiTempLabel(NULL);
7339       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7340       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7341       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7342       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7343   } else {
7344     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7345     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7346   }
7347   ic->generated = 1;
7348 }
7349
7350 /*-----------------------------------------------------------------*/
7351 /* genAnd  - code for and                                          */
7352 /*-----------------------------------------------------------------*/
7353 static void genAnd (iCode *ic, iCode *ifx)
7354 {
7355   operand *left, *right, *result;
7356   int size, offset=0;  
7357   unsigned long lit = 0L;
7358   int bytelit = 0;
7359   resolvedIfx rIfx;
7360
7361     FENTRY;
7362     
7363   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7364   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7365   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7366
7367   resolveIfx(&rIfx,ifx);
7368
7369   /* if left is a literal & right is not then exchange them */
7370   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7371       AOP_NEEDSACC(left)) {
7372     operand *tmp = right ;
7373     right = left;
7374     left = tmp;
7375   }
7376
7377   /* if result = right then exchange them */
7378   if(pic16_sameRegs(AOP(result),AOP(right))){
7379     operand *tmp = right ;
7380     right = left;
7381     left = tmp;
7382   }
7383
7384   /* if right is bit then exchange them */
7385   if (AOP_TYPE(right) == AOP_CRY &&
7386       AOP_TYPE(left) != AOP_CRY){
7387     operand *tmp = right ;
7388     right = left;
7389     left = tmp;
7390   }
7391   if(AOP_TYPE(right) == AOP_LIT)
7392     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7393
7394   size = AOP_SIZE(result);
7395
7396   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7397
7398   // if(bit & yy)
7399   // result = bit & yy;
7400   if (AOP_TYPE(left) == AOP_CRY){
7401     // c = bit & literal;
7402     if(AOP_TYPE(right) == AOP_LIT){
7403       if(lit & 1) {
7404         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7405           // no change
7406           goto release;
7407         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7408       } else {
7409         // bit(result) = 0;
7410         if(size && (AOP_TYPE(result) == AOP_CRY)){
7411           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7412           goto release;
7413         }
7414         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7415           jumpIfTrue(ifx);
7416           goto release;
7417         }
7418         pic16_emitcode("clr","c");
7419       }
7420     } else {
7421       if (AOP_TYPE(right) == AOP_CRY){
7422         // c = bit & bit;
7423         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7424         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7425       } else {
7426         // c = bit & val;
7427         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7428         // c = lsb
7429         pic16_emitcode("rrc","a");
7430         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7431       }
7432     }
7433     // bit = c
7434     // val = c
7435     if(size)
7436       pic16_outBitC(result);
7437     // if(bit & ...)
7438     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7439       genIfxJump(ifx, "c");           
7440     goto release ;
7441   }
7442
7443   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7444   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7445   if((AOP_TYPE(right) == AOP_LIT) &&
7446      (AOP_TYPE(result) == AOP_CRY) &&
7447      (AOP_TYPE(left) != AOP_CRY)){
7448     int posbit = isLiteralBit(lit);
7449     /* left &  2^n */
7450     if(posbit){
7451       posbit--;
7452       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7453       // bit = left & 2^n
7454       if(size)
7455         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7456       // if(left &  2^n)
7457       else{
7458         if(ifx){
7459 /*
7460           if(IC_TRUE(ifx)) {
7461             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7462             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7463           } else {
7464             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7465             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7466           }
7467 */
7468         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7469         size = AOP_SIZE(left);
7470
7471         {
7472           int bp = posbit, ofs=0;
7473           
7474             while(bp > 7) {
7475               bp -= 8;
7476               ofs++;
7477             }
7478
7479           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7480                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7481
7482         }
7483 /*
7484           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7485                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7486 */
7487           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7488           
7489           ifx->generated = 1;
7490         }
7491         goto release;
7492       }
7493     } else {
7494       symbol *tlbl = newiTempLabel(NULL);
7495       int sizel = AOP_SIZE(left);
7496
7497       if(size)
7498         emitSETC;
7499
7500       while(sizel--) {
7501         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7502
7503           /* patch provided by Aaron Colwell */
7504           if((posbit = isLiteralBit(bytelit)) != 0) {
7505               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7506                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7507                                                 (posbit-1),0, PO_GPR_REGISTER));
7508
7509               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7510 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7511           } else {
7512               if (bytelit == 0xff) {
7513                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7514                    * a peephole could optimize it out -- VR */
7515                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7516               } else {
7517                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7518                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7519               }
7520
7521               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7522                             pic16_popGetLabel(tlbl->key));
7523           }
7524         
7525 #if 0
7526           /* old code, left here for reference -- VR 09/2004 */
7527           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7528           // byte ==  2^n ?
7529           if((posbit = isLiteralBit(bytelit)) != 0)
7530             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7531           else{
7532             if(bytelit != 0x0FFL)
7533               pic16_emitcode("anl","a,%s",
7534                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7535             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7536           }
7537 #endif
7538         }
7539         offset++;
7540       }
7541       // bit = left & literal
7542       if(size) {
7543         emitCLRC;
7544         pic16_emitpLabel(tlbl->key);
7545       }
7546       // if(left & literal)
7547       else {
7548         if(ifx) {
7549           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7550           ifx->generated = 1;
7551         }
7552         pic16_emitpLabel(tlbl->key);
7553         goto release;
7554       }
7555     }
7556
7557     pic16_outBitC(result);
7558     goto release ;
7559   }
7560
7561   /* if left is same as result */
7562   if(pic16_sameRegs(AOP(result),AOP(left))){
7563     int know_W = -1;
7564     for(;size--; offset++,lit>>=8) {
7565       if(AOP_TYPE(right) == AOP_LIT){
7566         switch(lit & 0xff) {
7567         case 0x00:
7568           /*  and'ing with 0 has clears the result */
7569 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7570           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7571           break;
7572         case 0xff:
7573           /* and'ing with 0xff is a nop when the result and left are the same */
7574           break;
7575
7576         default:
7577           {
7578             int p = pic16_my_powof2( (~lit) & 0xff );
7579             if(p>=0) {
7580               /* only one bit is set in the literal, so use a bcf instruction */
7581 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7582               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7583
7584             } else {
7585               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7586               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7587               if(know_W != (lit&0xff))
7588                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7589               know_W = lit &0xff;
7590               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7591             }
7592           }    
7593         }
7594       } else {
7595         if (AOP_TYPE(left) == AOP_ACC) {
7596           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7597         } else {                    
7598           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7599           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7600
7601         }
7602       }
7603     }
7604
7605   } else {
7606     // left & result in different registers
7607     if(AOP_TYPE(result) == AOP_CRY){
7608       // result = bit
7609       // if(size), result in bit
7610       // if(!size && ifx), conditional oper: if(left & right)
7611       symbol *tlbl = newiTempLabel(NULL);
7612       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7613       if(size)
7614         pic16_emitcode("setb","c");
7615       while(sizer--){
7616         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7617         pic16_emitcode("anl","a,%s",
7618                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7619         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7620         offset++;
7621       }
7622       if(size){
7623         CLRC;
7624         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7625         pic16_outBitC(result);
7626       } else if(ifx)
7627         jmpTrueOrFalse(ifx, tlbl);
7628     } else {
7629       for(;(size--);offset++) {
7630         // normal case
7631         // result = left & right
7632         if(AOP_TYPE(right) == AOP_LIT){
7633           int t = (lit >> (offset*8)) & 0x0FFL;
7634           switch(t) { 
7635           case 0x00:
7636             pic16_emitcode("clrf","%s",
7637                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7638             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7639             break;
7640           case 0xff:
7641             pic16_emitcode("movf","%s,w",
7642                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7643             pic16_emitcode("movwf","%s",
7644                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7645             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7646             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7647             break;
7648           default:
7649             pic16_emitcode("movlw","0x%x",t);
7650             pic16_emitcode("andwf","%s,w",
7651                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7652             pic16_emitcode("movwf","%s",
7653                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7654               
7655             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7656             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7657             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7658           }
7659           continue;
7660         }
7661
7662         if (AOP_TYPE(left) == AOP_ACC) {
7663           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7664           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7665         } else {
7666           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7667           pic16_emitcode("andwf","%s,w",
7668                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7669           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7670           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7671         }
7672         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7673         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7674       }
7675     }
7676   }
7677
7678   release :
7679     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7680   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7681   pic16_freeAsmop(result,NULL,ic,TRUE);     
7682 }
7683
7684 /*-----------------------------------------------------------------*/
7685 /* genOr  - code for or                                            */
7686 /*-----------------------------------------------------------------*/
7687 static void genOr (iCode *ic, iCode *ifx)
7688 {
7689     operand *left, *right, *result;
7690     int size, offset=0;
7691     unsigned long lit = 0L;
7692
7693     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7694
7695     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7696     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7697     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7698
7699     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7700
7701     /* if left is a literal & right is not then exchange them */
7702     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7703         AOP_NEEDSACC(left)) {
7704         operand *tmp = right ;
7705         right = left;
7706         left = tmp;
7707     }
7708
7709     /* if result = right then exchange them */
7710     if(pic16_sameRegs(AOP(result),AOP(right))){
7711         operand *tmp = right ;
7712         right = left;
7713         left = tmp;
7714     }
7715
7716     /* if right is bit then exchange them */
7717     if (AOP_TYPE(right) == AOP_CRY &&
7718         AOP_TYPE(left) != AOP_CRY){
7719         operand *tmp = right ;
7720         right = left;
7721         left = tmp;
7722     }
7723
7724     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7725
7726     if(AOP_TYPE(right) == AOP_LIT)
7727         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7728
7729     size = AOP_SIZE(result);
7730
7731     // if(bit | yy)
7732     // xx = bit | yy;
7733     if (AOP_TYPE(left) == AOP_CRY){
7734         if(AOP_TYPE(right) == AOP_LIT){
7735             // c = bit & literal;
7736             if(lit){
7737                 // lit != 0 => result = 1
7738                 if(AOP_TYPE(result) == AOP_CRY){
7739                   if(size)
7740                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7741                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7742                   //     AOP(result)->aopu.aop_dir,
7743                   //     AOP(result)->aopu.aop_dir);
7744                     else if(ifx)
7745                         continueIfTrue(ifx);
7746                     goto release;
7747                 }
7748             } else {
7749                 // lit == 0 => result = left
7750                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7751                     goto release;
7752                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7753             }
7754         } else {
7755             if (AOP_TYPE(right) == AOP_CRY){
7756               if(pic16_sameRegs(AOP(result),AOP(left))){
7757                 // c = bit | bit;
7758                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7759                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7760                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7761
7762                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7763                          AOP(result)->aopu.aop_dir,
7764                          AOP(result)->aopu.aop_dir);
7765                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7766                          AOP(right)->aopu.aop_dir,
7767                          AOP(right)->aopu.aop_dir);
7768                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7769                          AOP(result)->aopu.aop_dir,
7770                          AOP(result)->aopu.aop_dir);
7771               } else {
7772                 if( AOP_TYPE(result) == AOP_ACC) {
7773                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7774                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7775                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7776                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7777
7778                 } else {
7779
7780                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7781                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7782                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7783                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7784
7785                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7786                                  AOP(result)->aopu.aop_dir,
7787                                  AOP(result)->aopu.aop_dir);
7788                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7789                                  AOP(right)->aopu.aop_dir,
7790                                  AOP(right)->aopu.aop_dir);
7791                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7792                                  AOP(left)->aopu.aop_dir,
7793                                  AOP(left)->aopu.aop_dir);
7794                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7795                                  AOP(result)->aopu.aop_dir,
7796                                  AOP(result)->aopu.aop_dir);
7797                 }
7798               }
7799             } else {
7800                 // c = bit | val;
7801                 symbol *tlbl = newiTempLabel(NULL);
7802                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7803
7804
7805                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7806                 if( AOP_TYPE(right) == AOP_ACC) {
7807                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7808                   emitSKPNZ;
7809                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7810                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7811                 }
7812
7813
7814
7815                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7816                     pic16_emitcode(";XXX setb","c");
7817                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7818                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7819                 pic16_toBoolean(right);
7820                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7821                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7822                     jmpTrueOrFalse(ifx, tlbl);
7823                     goto release;
7824                 } else {
7825                     CLRC;
7826                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7827                 }
7828             }
7829         }
7830         // bit = c
7831         // val = c
7832         if(size)
7833             pic16_outBitC(result);
7834         // if(bit | ...)
7835         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7836             genIfxJump(ifx, "c");           
7837         goto release ;
7838     }
7839
7840     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7841     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7842     if((AOP_TYPE(right) == AOP_LIT) &&
7843        (AOP_TYPE(result) == AOP_CRY) &&
7844        (AOP_TYPE(left) != AOP_CRY)){
7845         if(lit){
7846           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7847             // result = 1
7848             if(size)
7849                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7850             else 
7851                 continueIfTrue(ifx);
7852             goto release;
7853         } else {
7854           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7855             // lit = 0, result = boolean(left)
7856             if(size)
7857                 pic16_emitcode(";XXX setb","c");
7858             pic16_toBoolean(right);
7859             if(size){
7860                 symbol *tlbl = newiTempLabel(NULL);
7861                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7862                 CLRC;
7863                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7864             } else {
7865                 genIfxJump (ifx,"a");
7866                 goto release;
7867             }
7868         }
7869         pic16_outBitC(result);
7870         goto release ;
7871     }
7872
7873     /* if left is same as result */
7874     if(pic16_sameRegs(AOP(result),AOP(left))){
7875       int know_W = -1;
7876       for(;size--; offset++,lit>>=8) {
7877         if(AOP_TYPE(right) == AOP_LIT){
7878           if((lit & 0xff) == 0)
7879             /*  or'ing with 0 has no effect */
7880             continue;
7881           else {
7882             int p = pic16_my_powof2(lit & 0xff);
7883             if(p>=0) {
7884               /* only one bit is set in the literal, so use a bsf instruction */
7885               pic16_emitpcode(POC_BSF,
7886                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7887             } else {
7888               if(know_W != (lit & 0xff))
7889                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7890               know_W = lit & 0xff;
7891               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7892             }
7893                     
7894           }
7895         } else {
7896           if (AOP_TYPE(left) == AOP_ACC) {
7897             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7898 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7899           } else {                  
7900             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7901             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7902
7903 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7904 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7905
7906           }
7907         }
7908       }
7909     } else {
7910         // left & result in different registers
7911         if(AOP_TYPE(result) == AOP_CRY){
7912             // result = bit
7913             // if(size), result in bit
7914             // if(!size && ifx), conditional oper: if(left | right)
7915             symbol *tlbl = newiTempLabel(NULL);
7916             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7917             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7918
7919
7920             if(size)
7921                 pic16_emitcode(";XXX setb","c");
7922             while(sizer--){
7923                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7924                 pic16_emitcode(";XXX orl","a,%s",
7925                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7926                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7927                 offset++;
7928             }
7929             if(size){
7930                 CLRC;
7931                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7932                 pic16_outBitC(result);
7933             } else if(ifx)
7934                 jmpTrueOrFalse(ifx, tlbl);
7935         } else for(;(size--);offset++){
7936           // normal case
7937           // result = left & right
7938           if(AOP_TYPE(right) == AOP_LIT){
7939             int t = (lit >> (offset*8)) & 0x0FFL;
7940             switch(t) { 
7941             case 0x00:
7942               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7943               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7944
7945 //            pic16_emitcode("movf","%s,w",
7946 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7947 //            pic16_emitcode("movwf","%s",
7948 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7949               break;
7950             default:
7951               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7952               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7953               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7954
7955 //            pic16_emitcode("movlw","0x%x",t);
7956 //            pic16_emitcode("iorwf","%s,w",
7957 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7958 //            pic16_emitcode("movwf","%s",
7959 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7960               
7961             }
7962             continue;
7963           }
7964
7965           // faster than result <- left, anl result,right
7966           // and better if result is SFR
7967           if (AOP_TYPE(left) == AOP_ACC) {
7968             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7969 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7970           } else {
7971             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7972             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7973
7974 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7975 //          pic16_emitcode("iorwf","%s,w",
7976 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7977           }
7978           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7979 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7980         }
7981     }
7982
7983 release :
7984     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7985     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7986     pic16_freeAsmop(result,NULL,ic,TRUE);     
7987 }
7988
7989 /*-----------------------------------------------------------------*/
7990 /* genXor - code for xclusive or                                   */
7991 /*-----------------------------------------------------------------*/
7992 static void genXor (iCode *ic, iCode *ifx)
7993 {
7994   operand *left, *right, *result;
7995   int size, offset=0;
7996   unsigned long lit = 0L;
7997
7998   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7999
8000   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8001   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8002   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8003
8004   /* if left is a literal & right is not ||
8005      if left needs acc & right does not */
8006   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8007       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8008     operand *tmp = right ;
8009     right = left;
8010     left = tmp;
8011   }
8012
8013   /* if result = right then exchange them */
8014   if(pic16_sameRegs(AOP(result),AOP(right))){
8015     operand *tmp = right ;
8016     right = left;
8017     left = tmp;
8018   }
8019
8020   /* if right is bit then exchange them */
8021   if (AOP_TYPE(right) == AOP_CRY &&
8022       AOP_TYPE(left) != AOP_CRY){
8023     operand *tmp = right ;
8024     right = left;
8025     left = tmp;
8026   }
8027   if(AOP_TYPE(right) == AOP_LIT)
8028     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8029
8030   size = AOP_SIZE(result);
8031
8032   // if(bit ^ yy)
8033   // xx = bit ^ yy;
8034   if (AOP_TYPE(left) == AOP_CRY){
8035     if(AOP_TYPE(right) == AOP_LIT){
8036       // c = bit & literal;
8037       if(lit>>1){
8038         // lit>>1  != 0 => result = 1
8039         if(AOP_TYPE(result) == AOP_CRY){
8040           if(size)
8041             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8042             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8043           else if(ifx)
8044             continueIfTrue(ifx);
8045           goto release;
8046         }
8047         pic16_emitcode("setb","c");
8048       } else{
8049         // lit == (0 or 1)
8050         if(lit == 0){
8051           // lit == 0, result = left
8052           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8053             goto release;
8054           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8055         } else{
8056           // lit == 1, result = not(left)
8057           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8058             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8059             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8060             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8061             goto release;
8062           } else {
8063             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8064             pic16_emitcode("cpl","c");
8065           }
8066         }
8067       }
8068
8069     } else {
8070       // right != literal
8071       symbol *tlbl = newiTempLabel(NULL);
8072       if (AOP_TYPE(right) == AOP_CRY){
8073         // c = bit ^ bit;
8074         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8075       }
8076       else{
8077         int sizer = AOP_SIZE(right);
8078         // c = bit ^ val
8079         // if val>>1 != 0, result = 1
8080         pic16_emitcode("setb","c");
8081         while(sizer){
8082           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8083           if(sizer == 1)
8084             // test the msb of the lsb
8085             pic16_emitcode("anl","a,#0xfe");
8086           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8087           sizer--;
8088         }
8089         // val = (0,1)
8090         pic16_emitcode("rrc","a");
8091       }
8092       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8093       pic16_emitcode("cpl","c");
8094       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8095     }
8096     // bit = c
8097     // val = c
8098     if(size)
8099       pic16_outBitC(result);
8100     // if(bit | ...)
8101     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8102       genIfxJump(ifx, "c");           
8103     goto release ;
8104   }
8105
8106   if(pic16_sameRegs(AOP(result),AOP(left))){
8107     /* if left is same as result */
8108     for(;size--; offset++) {
8109       if(AOP_TYPE(right) == AOP_LIT){
8110         int t  = (lit >> (offset*8)) & 0x0FFL;
8111         if(t == 0x00L)
8112           continue;
8113         else
8114           if (IS_AOP_PREG(left)) {
8115             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8116             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8117             pic16_aopPut(AOP(result),"a",offset);
8118           } else {
8119             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8120             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8121             pic16_emitcode("xrl","%s,%s",
8122                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8123                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8124           }
8125       } else {
8126         if (AOP_TYPE(left) == AOP_ACC)
8127           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8128         else {
8129           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8130           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8131 /*
8132           if (IS_AOP_PREG(left)) {
8133             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8134             pic16_aopPut(AOP(result),"a",offset);
8135           } else
8136             pic16_emitcode("xrl","%s,a",
8137                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8138 */
8139         }
8140       }
8141     }
8142   } else {
8143     // left & result in different registers
8144     if(AOP_TYPE(result) == AOP_CRY){
8145       // result = bit
8146       // if(size), result in bit
8147       // if(!size && ifx), conditional oper: if(left ^ right)
8148       symbol *tlbl = newiTempLabel(NULL);
8149       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8150       if(size)
8151         pic16_emitcode("setb","c");
8152       while(sizer--){
8153         if((AOP_TYPE(right) == AOP_LIT) &&
8154            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8155           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8156         } else {
8157           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8158           pic16_emitcode("xrl","a,%s",
8159                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8160         }
8161         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8162         offset++;
8163       }
8164       if(size){
8165         CLRC;
8166         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8167         pic16_outBitC(result);
8168       } else if(ifx)
8169         jmpTrueOrFalse(ifx, tlbl);
8170     } else for(;(size--);offset++){
8171       // normal case
8172       // result = left & right
8173       if(AOP_TYPE(right) == AOP_LIT){
8174         int t = (lit >> (offset*8)) & 0x0FFL;
8175         switch(t) { 
8176         case 0x00:
8177           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8178           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8179           pic16_emitcode("movf","%s,w",
8180                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8181           pic16_emitcode("movwf","%s",
8182                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8183           break;
8184         case 0xff:
8185           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8186           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8187           pic16_emitcode("comf","%s,w",
8188                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8189           pic16_emitcode("movwf","%s",
8190                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8191           break;
8192         default:
8193           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8194           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8195           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8196           pic16_emitcode("movlw","0x%x",t);
8197           pic16_emitcode("xorwf","%s,w",
8198                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8199           pic16_emitcode("movwf","%s",
8200                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8201
8202         }
8203         continue;
8204       }
8205
8206       // faster than result <- left, anl result,right
8207       // and better if result is SFR
8208       if (AOP_TYPE(left) == AOP_ACC) {
8209         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8210         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8211       } else {
8212         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8213         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8214         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8215         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8216       }
8217       if ( AOP_TYPE(result) != AOP_ACC){
8218         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8219         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8220       }
8221     }
8222   }
8223
8224   release :
8225     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8226   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8227   pic16_freeAsmop(result,NULL,ic,TRUE);     
8228 }
8229
8230 /*-----------------------------------------------------------------*/
8231 /* genInline - write the inline code out                           */
8232 /*-----------------------------------------------------------------*/
8233 static void genInline (iCode *ic)
8234 {
8235   char *buffer, *bp, *bp1;
8236     
8237         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8238
8239         _G.inLine += (!options.asmpeep);
8240
8241         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8242         strcpy(buffer,IC_INLINE(ic));
8243         
8244         while((bp1=strstr(bp, "\\n"))) {
8245           *bp1++ = '\n';
8246           *bp1++ = ' ';
8247           bp = bp1;
8248         }
8249         bp = bp1 = buffer;
8250
8251 #if 0
8252   /* This is an experimental code for #pragma inline
8253      and is temporarily disabled for 2.5.0 release */
8254         if(asmInlineMap)
8255         {
8256           symbol *sym;
8257           char *s;
8258           char *cbuf;
8259           int cblen;
8260
8261             cbuf = Safe_strdup(buffer);
8262             cblen = strlen(buffer)+1;
8263             memset(cbuf, 0, cblen);
8264
8265             bp = buffer;
8266             bp1 = cbuf;
8267             while(*bp) {
8268               if(*bp != '%')*bp1++ = *bp++;
8269               else {
8270                 int i;
8271
8272                   bp++;
8273                   i = *bp - '0';
8274                   if(i>elementsInSet(asmInlineMap))break;
8275                   
8276                   bp++;
8277                   s = indexSet(asmInlineMap, i);
8278                   DEBUGpc("searching symbol s = `%s'", s);
8279                   sym = findSym(SymbolTab, NULL, s);
8280
8281                   if(sym->reqv) {
8282                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8283                   } else {
8284                     strcat(bp1, sym->rname);
8285                   }
8286                   
8287                   while(*bp1)bp1++;
8288               }
8289               
8290               if(strlen(bp1) > cblen - 16) {
8291                 int i = strlen(cbuf);
8292                 cblen += 50;
8293                 cbuf = realloc(cbuf, cblen);
8294                 memset(cbuf+i, 0, 50);
8295                 bp1 = cbuf + i;
8296               }
8297             }
8298             
8299             free(buffer);
8300             buffer = Safe_strdup( cbuf );
8301             free(cbuf);
8302             
8303             bp = bp1 = buffer;
8304         }
8305 #endif  /* 0 */
8306
8307         /* emit each line as a code */
8308         while (*bp) {
8309                 if (*bp == '\n') {
8310                         *bp++ = '\0';
8311
8312                         if(*bp1)
8313                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8314                         bp1 = bp;
8315                 } else {
8316                         if (*bp == ':') {
8317                                 bp++;
8318                                 *bp = '\0';
8319                                 bp++;
8320
8321                                 /* print label, use this special format with NULL directive
8322                                  * to denote that the argument should not be indented with tab */
8323                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8324                                 bp1 = bp;
8325                         } if (*bp == ';') {
8326                                 /* advance to end of line (prevent splitting of comments at ':' */
8327                                 while (*bp && *bp != '\n') {
8328                                         bp++;
8329                                 } // while
8330                         } else
8331                                 bp++;
8332                 }
8333         }
8334
8335         if ((bp1 != bp) && *bp1)
8336                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8337
8338
8339     Safe_free(buffer);
8340
8341     _G.inLine -= (!options.asmpeep);
8342 }
8343
8344 /*-----------------------------------------------------------------*/
8345 /* genRRC - rotate right with carry                                */
8346 /*-----------------------------------------------------------------*/
8347 static void genRRC (iCode *ic)
8348 {
8349   operand *left , *result ;
8350   int size, offset = 0, same;
8351
8352   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8353
8354   /* rotate right with carry */
8355   left = IC_LEFT(ic);
8356   result=IC_RESULT(ic);
8357   pic16_aopOp (left,ic,FALSE);
8358   pic16_aopOp (result,ic,TRUE);
8359
8360   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8361
8362   same = pic16_sameRegs(AOP(result),AOP(left));
8363
8364   size = AOP_SIZE(result);    
8365
8366   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8367
8368   /* get the lsb and put it into the carry */
8369   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8370
8371   offset = 0 ;
8372
8373   while(size--) {
8374
8375     if(same) {
8376       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8377     } else {
8378       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8379       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8380     }
8381
8382     offset++;
8383   }
8384
8385   pic16_freeAsmop(left,NULL,ic,TRUE);
8386   pic16_freeAsmop(result,NULL,ic,TRUE);
8387 }
8388
8389 /*-----------------------------------------------------------------*/
8390 /* genRLC - generate code for rotate left with carry               */
8391 /*-----------------------------------------------------------------*/
8392 static void genRLC (iCode *ic)
8393 {    
8394   operand *left , *result ;
8395   int size, offset = 0;
8396   int same;
8397
8398   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8399   /* rotate right with carry */
8400   left = IC_LEFT(ic);
8401   result=IC_RESULT(ic);
8402   pic16_aopOp (left,ic,FALSE);
8403   pic16_aopOp (result,ic,TRUE);
8404
8405   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8406
8407   same = pic16_sameRegs(AOP(result),AOP(left));
8408
8409   /* move it to the result */
8410   size = AOP_SIZE(result);    
8411
8412   /* get the msb and put it into the carry */
8413   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8414
8415   offset = 0 ;
8416
8417   while(size--) {
8418
8419     if(same) {
8420       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8421     } else {
8422       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8423       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8424     }
8425
8426     offset++;
8427   }
8428
8429
8430   pic16_freeAsmop(left,NULL,ic,TRUE);
8431   pic16_freeAsmop(result,NULL,ic,TRUE);
8432 }
8433
8434
8435 /* gpasm can get the highest order bit with HIGH/UPPER
8436  * so the following probably is not needed -- VR */
8437  
8438 /*-----------------------------------------------------------------*/
8439 /* genGetHbit - generates code get highest order bit               */
8440 /*-----------------------------------------------------------------*/
8441 static void genGetHbit (iCode *ic)
8442 {
8443     operand *left, *result;
8444     left = IC_LEFT(ic);
8445     result=IC_RESULT(ic);
8446     pic16_aopOp (left,ic,FALSE);
8447     pic16_aopOp (result,ic,FALSE);
8448
8449     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8450     /* get the highest order byte into a */
8451     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8452     if(AOP_TYPE(result) == AOP_CRY){
8453         pic16_emitcode("rlc","a");
8454         pic16_outBitC(result);
8455     }
8456     else{
8457         pic16_emitcode("rl","a");
8458         pic16_emitcode("anl","a,#0x01");
8459         pic16_outAcc(result);
8460     }
8461
8462
8463     pic16_freeAsmop(left,NULL,ic,TRUE);
8464     pic16_freeAsmop(result,NULL,ic,TRUE);
8465 }
8466
8467 #if 0
8468 /*-----------------------------------------------------------------*/
8469 /* AccRol - rotate left accumulator by known count                 */
8470 /*-----------------------------------------------------------------*/
8471 static void AccRol (int shCount)
8472 {
8473     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8474     shCount &= 0x0007;              // shCount : 0..7
8475     switch(shCount){
8476         case 0 :
8477             break;
8478         case 1 :
8479             pic16_emitcode("rl","a");
8480             break;
8481         case 2 :
8482             pic16_emitcode("rl","a");
8483             pic16_emitcode("rl","a");
8484             break;
8485         case 3 :
8486             pic16_emitcode("swap","a");
8487             pic16_emitcode("rr","a");
8488             break;
8489         case 4 :
8490             pic16_emitcode("swap","a");
8491             break;
8492         case 5 :
8493             pic16_emitcode("swap","a");
8494             pic16_emitcode("rl","a");
8495             break;
8496         case 6 :
8497             pic16_emitcode("rr","a");
8498             pic16_emitcode("rr","a");
8499             break;
8500         case 7 :
8501             pic16_emitcode("rr","a");
8502             break;
8503     }
8504 }
8505 #endif
8506
8507 /*-----------------------------------------------------------------*/
8508 /* AccLsh - left shift accumulator by known count                  */
8509 /*-----------------------------------------------------------------*/
8510 static void AccLsh (int shCount, int doMask)
8511 {
8512         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8513         switch(shCount){
8514                 case 0 :
8515                         return;
8516                         break;
8517                 case 1 :
8518                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8519                         break;
8520                 case 2 :
8521                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8522                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8523                         break;
8524                 case 3 :
8525                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8526                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527                         break;
8528                 case 4 :
8529                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8530                         break;
8531                 case 5 :
8532                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8533                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8534                         break;
8535                 case 6 :
8536                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8537                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8538                         break;
8539                 case 7 :
8540                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8541                         break;
8542         }
8543         if (doMask) {
8544                 /* no masking is required in genPackBits */
8545                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8546         }
8547 }
8548
8549 /*-----------------------------------------------------------------*/
8550 /* AccRsh - right shift accumulator by known count                 */
8551 /*-----------------------------------------------------------------*/
8552 static void AccRsh (int shCount, int andmask)
8553 {
8554         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8555         switch(shCount){
8556                 case 0 :
8557                         return; break;
8558                 case 1 :
8559                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8560                         break;
8561                 case 2 :
8562                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8563                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8564                         break;
8565                 case 3 :
8566                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8567                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8568                         break;
8569                 case 4 :
8570                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8571                         break;
8572                 case 5 :
8573                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8574                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8575                         break;
8576                 case 6 :
8577                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8578                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8579                         break;
8580                 case 7 :
8581                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8582                         break;
8583         }
8584         
8585         if(andmask)
8586                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8587         else
8588                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8589 }
8590
8591 #if 0
8592 /*-----------------------------------------------------------------*/
8593 /* AccSRsh - signed right shift accumulator by known count                 */
8594 /*-----------------------------------------------------------------*/
8595 static void AccSRsh (int shCount)
8596 {
8597     symbol *tlbl ;
8598     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8599     if(shCount != 0){
8600         if(shCount == 1){
8601             pic16_emitcode("mov","c,acc.7");
8602             pic16_emitcode("rrc","a");
8603         } else if(shCount == 2){
8604             pic16_emitcode("mov","c,acc.7");
8605             pic16_emitcode("rrc","a");
8606             pic16_emitcode("mov","c,acc.7");
8607             pic16_emitcode("rrc","a");
8608         } else {
8609             tlbl = newiTempLabel(NULL);
8610             /* rotate right accumulator */
8611             AccRol(8 - shCount);
8612             /* and kill the higher order bits */
8613             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8614             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8615             pic16_emitcode("orl","a,#0x%02x",
8616                      (unsigned char)~SRMask[shCount]);
8617             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8618         }
8619     }
8620 }
8621 #endif
8622
8623 /*-----------------------------------------------------------------*/
8624 /* shiftR1Left2Result - shift right one byte from left to result   */
8625 /*-----------------------------------------------------------------*/
8626 static void shiftR1Left2ResultSigned (operand *left, int offl,
8627                                 operand *result, int offr,
8628                                 int shCount)
8629 {
8630   int same;
8631
8632   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8633
8634   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8635
8636   switch(shCount) {
8637   case 1:
8638     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8639     if(same) 
8640       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8641     else {
8642       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8643       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8644     }
8645
8646     break;
8647   case 2:
8648
8649     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8650     if(same) 
8651       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8652     else {
8653       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8654       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8655     }
8656     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8657     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8658
8659     break;
8660
8661   case 3:
8662     if(same)
8663       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8664     else {
8665       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8666       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8667     }
8668
8669     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8670     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8671     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8672
8673     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8674     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8675
8676     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8677     break;
8678
8679   case 4:
8680     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8681     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8682     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8683     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8684     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8685     break;
8686   case 5:
8687     if(same) {
8688       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8689     } else {
8690       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8691       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8692     }
8693     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8694     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8695     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8696     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8697     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8698     break;
8699
8700   case 6:
8701     if(same) {
8702       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8703       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8704       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8705       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8706       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8707       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8708     } else {
8709       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8710       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8711       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8712       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8713       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8714     }
8715     break;
8716
8717   case 7:
8718     if(same) {
8719       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8720       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8721       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8722       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8723     } else {
8724       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8725       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8726       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8727     }
8728
8729   default:
8730     break;
8731   }
8732 }
8733
8734 /*-----------------------------------------------------------------*/
8735 /* shiftR1Left2Result - shift right one byte from left to result   */
8736 /*-----------------------------------------------------------------*/
8737 static void shiftR1Left2Result (operand *left, int offl,
8738                                 operand *result, int offr,
8739                                 int shCount, int sign)
8740 {
8741   int same;
8742
8743   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8744
8745   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8746
8747   /* Copy the msb into the carry if signed. */
8748   if(sign) {
8749     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8750     return;
8751   }
8752
8753
8754
8755   switch(shCount) {
8756   case 1:
8757     emitCLRC;
8758     if(same) 
8759       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8760     else {
8761       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8762       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8763     }
8764     break;
8765   case 2:
8766     emitCLRC;
8767     if(same) {
8768       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8769     } else {
8770       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8771       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8772     }
8773     emitCLRC;
8774     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8775
8776     break;
8777   case 3:
8778     if(same)
8779       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8780     else {
8781       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8782       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8783     }
8784
8785     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8786     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8787     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8788     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8789     break;
8790       
8791   case 4:
8792     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8793     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8794     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8795     break;
8796
8797   case 5:
8798     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8799     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8800     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8801     //emitCLRC;
8802     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8803
8804     break;
8805   case 6:
8806
8807     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8808     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8809     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8810     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8811     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8812     break;
8813
8814   case 7:
8815
8816     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8817     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8818     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8819
8820     break;
8821
8822   default:
8823     break;
8824   }
8825 }
8826
8827 /*-----------------------------------------------------------------*/
8828 /* shiftL1Left2Result - shift left one byte from left to result    */
8829 /*-----------------------------------------------------------------*/
8830 static void shiftL1Left2Result (operand *left, int offl,
8831                                 operand *result, int offr, int shCount)
8832 {
8833   int same;
8834
8835   //    char *l;
8836   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8837
8838   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8839   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8840     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8841     //    MOVA(l);
8842     /* shift left accumulator */
8843     //AccLsh(shCount, 1); // don't comment out just yet...
8844   //    pic16_aopPut(AOP(result),"a",offr);
8845
8846   switch(shCount) {
8847   case 1:
8848     /* Shift left 1 bit position */
8849     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8850     if(same) {
8851       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8852     } else {
8853       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8854       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8855     }
8856     break;
8857   case 2:
8858     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8859     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8860     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8861     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8862     break;
8863   case 3:
8864     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8865     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8866     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8867     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8868     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8869     break;
8870   case 4:
8871     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8872     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8873     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8874     break;
8875   case 5:
8876     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8877     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8878     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8879     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8880     break;
8881   case 6:
8882     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8883     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8884     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8885     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8886     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8887     break;
8888   case 7:
8889     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8890     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8891     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8892     break;
8893
8894   default:
8895     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8896   }
8897
8898 }
8899
8900 /*-----------------------------------------------------------------*/
8901 /* movLeft2Result - move byte from left to result                  */
8902 /*-----------------------------------------------------------------*/
8903 static void movLeft2Result (operand *left, int offl,
8904                             operand *result, int offr)
8905 {
8906   char *l;
8907   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8908   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8909     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8910
8911     if (*l == '@' && (IS_AOP_PREG(result))) {
8912       pic16_emitcode("mov","a,%s",l);
8913       pic16_aopPut(AOP(result),"a",offr);
8914     } else {
8915       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8916       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8917     }
8918   }
8919 }
8920
8921 /*-----------------------------------------------------------------*/
8922 /* shiftL2Left2Result - shift left two bytes from left to result   */
8923 /*-----------------------------------------------------------------*/
8924 static void shiftL2Left2Result (operand *left, int offl,
8925                                 operand *result, int offr, int shCount)
8926 {
8927   int same = pic16_sameRegs(AOP(result), AOP(left));
8928   int i;
8929
8930   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8931
8932   if (same && (offl != offr)) { // shift bytes
8933     if (offr > offl) {
8934        for(i=1;i>-1;i--) {
8935          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8936          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8937        }
8938     } else { // just treat as different later on
8939                 same = 0;
8940     }
8941   }
8942
8943   if(same) {
8944     switch(shCount) {
8945     case 0:
8946       break;
8947     case 1:
8948     case 2:
8949     case 3:
8950
8951       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8952       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8953       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8954
8955       while(--shCount) {
8956                 emitCLRC;
8957                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8958                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8959       }
8960
8961       break;
8962     case 4:
8963     case 5:
8964       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8965       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8966       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8967       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8968       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8969       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8971       if(shCount >=5) {
8972                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8973                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8974       }
8975       break;
8976     case 6:
8977       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8978       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8979       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8980       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8981       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8982       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8983       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8984       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8985       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8986       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8987       break;
8988     case 7:
8989       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8990       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8991       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8992       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8993       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8994     }
8995
8996   } else {
8997     switch(shCount) {
8998     case 0:
8999       break;
9000     case 1:
9001     case 2:
9002     case 3:
9003       /* note, use a mov/add for the shift since the mov has a
9004          chance of getting optimized out */
9005       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9006       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9007       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9008       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9009       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9010
9011       while(--shCount) {
9012                 emitCLRC;
9013                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9014                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9015       }
9016       break;
9017
9018     case 4:
9019     case 5:
9020       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9021       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9022       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9023       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9024       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9025       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9026       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9027       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9028
9029
9030       if(shCount == 5) {
9031                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9032                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9033       }
9034       break;
9035     case 6:
9036       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9037       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9038       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9039       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9040
9041       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9042       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9043       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9044       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9045       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9046       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9047       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9048       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9049       break;
9050     case 7:
9051       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9052       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9053       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9054       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9055       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9056     }
9057   }
9058
9059 }
9060 /*-----------------------------------------------------------------*/
9061 /* shiftR2Left2Result - shift right two bytes from left to result  */
9062 /*-----------------------------------------------------------------*/
9063 static void shiftR2Left2Result (operand *left, int offl,
9064                                 operand *result, int offr,
9065                                 int shCount, int sign)
9066 {
9067   int same = pic16_sameRegs(AOP(result), AOP(left));
9068   int i;
9069   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9070
9071   if (same && (offl != offr)) { // shift right bytes
9072     if (offr < offl) {
9073        for(i=0;i<2;i++) {
9074          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9075          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9076        }
9077     } else { // just treat as different later on
9078                 same = 0;
9079     }
9080   }
9081
9082   switch(shCount) {
9083   case 0:
9084     break;
9085   case 1:
9086   case 2:
9087   case 3:
9088     if(sign)
9089       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9090     else
9091       emitCLRC;
9092
9093     if(same) {
9094       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9095       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9096     } else {
9097       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9098       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9099       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9100       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9101     }
9102
9103     while(--shCount) {
9104       if(sign)
9105                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9106       else
9107                 emitCLRC;
9108       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9109       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9110     }
9111     break;
9112   case 4:
9113   case 5:
9114     if(same) {
9115
9116       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9117       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9118       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9119
9120       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9121       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9122       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9123       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9124     } else {
9125       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9126       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9127       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9128
9129       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9130       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9131       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9132       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9133       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9134     }
9135
9136     if(shCount >=5) {
9137       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9138       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9139     }
9140
9141     if(sign) {
9142       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9143       pic16_emitpcode(POC_BTFSC, 
9144                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9145       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9146     }
9147
9148     break;
9149
9150   case 6:
9151     if(same) {
9152
9153       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9154       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9155
9156       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9157       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9158       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9159       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9160       if(sign) {
9161         pic16_emitpcode(POC_BTFSC, 
9162                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9163         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9164       }
9165       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9166       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9167       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9168       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9169     } else {
9170       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9171       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9172       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9173       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9174       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9175       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9176       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9177       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9178       if(sign) {
9179         pic16_emitpcode(POC_BTFSC, 
9180                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9181         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9182       }
9183       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9184       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9185
9186         
9187     }
9188
9189     break;
9190   case 7:
9191     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9192     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9193     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9194     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9195     if(sign) {
9196       emitSKPNC;
9197       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9198     } else 
9199       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9200   }
9201 }
9202
9203
9204 /*-----------------------------------------------------------------*/
9205 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9206 /*-----------------------------------------------------------------*/
9207 static void shiftLLeftOrResult (operand *left, int offl,
9208                                 operand *result, int offr, int shCount)
9209 {
9210     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9211
9212     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9213     /* shift left accumulator */
9214     AccLsh(shCount, 1);
9215     /* or with result */
9216     /* back to result */
9217     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9218 }
9219
9220 /*-----------------------------------------------------------------*/
9221 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9222 /*-----------------------------------------------------------------*/
9223 static void shiftRLeftOrResult (operand *left, int offl,
9224                                 operand *result, int offr, int shCount)
9225 {
9226     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9227     
9228     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9229     /* shift right accumulator */
9230     AccRsh(shCount, 1);
9231     /* or with result */
9232     /* back to result */
9233     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9234 }
9235
9236 /*-----------------------------------------------------------------*/
9237 /* genlshOne - left shift a one byte quantity by known count       */
9238 /*-----------------------------------------------------------------*/
9239 static void genlshOne (operand *result, operand *left, int shCount)
9240 {       
9241     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9242     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9243 }
9244
9245 /*-----------------------------------------------------------------*/
9246 /* genlshTwo - left shift two bytes by known amount != 0           */
9247 /*-----------------------------------------------------------------*/
9248 static void genlshTwo (operand *result,operand *left, int shCount)
9249 {
9250     int size;
9251     
9252     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9253     size = pic16_getDataSize(result);
9254
9255     /* if shCount >= 8 */
9256     if (shCount >= 8) {
9257         shCount -= 8 ;
9258
9259         if (size > 1){
9260             if (shCount)
9261                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9262             else 
9263                 movLeft2Result(left, LSB, result, MSB16);
9264         }
9265         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9266     }
9267
9268     /*  1 <= shCount <= 7 */
9269     else {  
9270         if(size == 1)
9271             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9272         else 
9273             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9274     }
9275 }
9276
9277 /*-----------------------------------------------------------------*/
9278 /* shiftLLong - shift left one long from left to result            */
9279 /* offr = LSB or MSB16                                             */
9280 /*-----------------------------------------------------------------*/
9281 static void shiftLLong (operand *left, operand *result, int offr )
9282 {
9283     int size = AOP_SIZE(result);
9284     int same = pic16_sameRegs(AOP(left),AOP(result));
9285         int i;
9286
9287     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9288
9289         if (same && (offr == MSB16)) { //shift one byte
9290                 for(i=size-1;i>=MSB16;i--) {
9291                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9292                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9293                 }
9294         } else {
9295                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9296         }
9297         
9298     if (size > LSB+offr ){
9299                 if (same) {
9300                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9301                 } else {
9302                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9303                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9304                 }
9305          }
9306
9307     if(size > MSB16+offr){
9308                 if (same) {
9309                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9310                 } else {
9311                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9312                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9313                 }
9314     }
9315
9316     if(size > MSB24+offr){
9317                 if (same) {
9318                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9319                 } else {
9320                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9321                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9322                 }
9323     }
9324
9325     if(size > MSB32+offr){
9326                 if (same) {
9327                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9328                 } else {
9329                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9330                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9331                 }
9332     }
9333     if(offr != LSB)
9334                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9335
9336 }
9337
9338 /*-----------------------------------------------------------------*/
9339 /* genlshFour - shift four byte by a known amount != 0             */
9340 /*-----------------------------------------------------------------*/
9341 static void genlshFour (operand *result, operand *left, int shCount)
9342 {
9343     int size;
9344
9345     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9346     size = AOP_SIZE(result);
9347
9348     /* if shifting more that 3 bytes */
9349     if (shCount >= 24 ) {
9350         shCount -= 24;
9351         if (shCount)
9352             /* lowest order of left goes to the highest
9353             order of the destination */
9354             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9355         else
9356             movLeft2Result(left, LSB, result, MSB32);
9357
9358                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9359                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9360                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9361
9362         return;
9363     }
9364
9365     /* more than two bytes */
9366     else if ( shCount >= 16 ) {
9367         /* lower order two bytes goes to higher order two bytes */
9368         shCount -= 16;
9369         /* if some more remaining */
9370         if (shCount)
9371             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9372         else {
9373             movLeft2Result(left, MSB16, result, MSB32);
9374             movLeft2Result(left, LSB, result, MSB24);
9375         }
9376                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9377                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9378         return;
9379     }    
9380
9381     /* if more than 1 byte */
9382     else if ( shCount >= 8 ) {
9383         /* lower order three bytes goes to higher order  three bytes */
9384         shCount -= 8;
9385         if(size == 2){
9386             if(shCount)
9387                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9388             else
9389                 movLeft2Result(left, LSB, result, MSB16);
9390         }
9391         else{   /* size = 4 */
9392             if(shCount == 0){
9393                 movLeft2Result(left, MSB24, result, MSB32);
9394                 movLeft2Result(left, MSB16, result, MSB24);
9395                 movLeft2Result(left, LSB, result, MSB16);
9396                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9397             }
9398             else if(shCount == 1)
9399                 shiftLLong(left, result, MSB16);
9400             else{
9401                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9402                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9403                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9404                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9405             }
9406         }
9407     }
9408
9409     /* 1 <= shCount <= 7 */
9410     else if(shCount <= 3)
9411     { 
9412         shiftLLong(left, result, LSB);
9413         while(--shCount >= 1)
9414             shiftLLong(result, result, LSB);
9415     }
9416     /* 3 <= shCount <= 7, optimize */
9417     else{
9418         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9419         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9420         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9421     }
9422 }
9423
9424 /*-----------------------------------------------------------------*/
9425 /* genLeftShiftLiteral - left shifting by known count              */
9426 /*-----------------------------------------------------------------*/
9427 void pic16_genLeftShiftLiteral (operand *left,
9428                                  operand *right,
9429                                  operand *result,
9430                                  iCode *ic)
9431 {    
9432     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9433     int size;
9434
9435     FENTRY;
9436     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9437     pic16_freeAsmop(right,NULL,ic,TRUE);
9438
9439     pic16_aopOp(left,ic,FALSE);
9440     pic16_aopOp(result,ic,TRUE);
9441
9442     size = getSize(operandType(result));
9443
9444 #if VIEW_SIZE
9445     pic16_emitcode("; shift left ","result %d, left %d",size,
9446              AOP_SIZE(left));
9447 #endif
9448
9449     /* I suppose that the left size >= result size */
9450     if(shCount == 0){
9451         while(size--){
9452             movLeft2Result(left, size, result, size);
9453         }
9454     }
9455
9456     else if(shCount >= (size * 8))
9457         while(size--)
9458             pic16_aopPut(AOP(result),zero,size);
9459     else{
9460         switch (size) {
9461             case 1:
9462                 genlshOne (result,left,shCount);
9463                 break;
9464
9465             case 2:
9466             case 3:
9467                 genlshTwo (result,left,shCount);
9468                 break;
9469
9470             case 4:
9471                 genlshFour (result,left,shCount);
9472                 break;
9473         }
9474     }
9475     pic16_freeAsmop(left,NULL,ic,TRUE);
9476     pic16_freeAsmop(result,NULL,ic,TRUE);
9477 }
9478
9479 /*-----------------------------------------------------------------*
9480  * genMultiAsm - repeat assembly instruction for size of register.
9481  * if endian == 1, then the high byte (i.e base address + size of 
9482  * register) is used first else the low byte is used first;
9483  *-----------------------------------------------------------------*/
9484 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9485 {
9486
9487   int offset = 0;
9488
9489   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9490
9491   if(!reg)
9492     return;
9493
9494   if(!endian) {
9495     endian = 1;
9496   } else {
9497     endian = -1;
9498     offset = size-1;
9499   }
9500
9501   while(size--) {
9502     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9503     offset += endian;
9504   }
9505
9506 }
9507
9508 #if !(USE_GENERIC_SIGNED_SHIFT)
9509 /*-----------------------------------------------------------------*/
9510 /* genLeftShift - generates code for left shifting                 */
9511 /*-----------------------------------------------------------------*/
9512 static void genLeftShift (iCode *ic)
9513 {
9514   operand *left,*right, *result;
9515   int size, offset;
9516 //  char *l;
9517   symbol *tlbl , *tlbl1;
9518   pCodeOp *pctemp;
9519
9520   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9521
9522   right = IC_RIGHT(ic);
9523   left  = IC_LEFT(ic);
9524   result = IC_RESULT(ic);
9525
9526   pic16_aopOp(right,ic,FALSE);
9527
9528   /* if the shift count is known then do it 
9529      as efficiently as possible */
9530   if (AOP_TYPE(right) == AOP_LIT) {
9531     pic16_genLeftShiftLiteral (left,right,result,ic);
9532     return ;
9533   }
9534
9535   /* shift count is unknown then we have to form
9536    * a loop. Get the loop count in WREG : Note: we take
9537    * only the lower order byte since shifting
9538    * more than 32 bits make no sense anyway, ( the
9539    * largest size of an object can be only 32 bits ) */
9540   
9541   pic16_aopOp(left,ic,FALSE);
9542   pic16_aopOp(result,ic,FALSE);
9543
9544   /* now move the left to the result if they are not the
9545    * same, and if size > 1,
9546    * and if right is not same to result (!!!) -- VR */
9547   if (!pic16_sameRegs(AOP(left),AOP(result))
9548       && (AOP_SIZE(result) > 1)) {
9549
9550     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9551
9552     size = AOP_SIZE(result);
9553     offset=0;
9554     while (size--) {
9555
9556 #if 0
9557       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9558       if (*l == '@' && (IS_AOP_PREG(result))) {
9559
9560           pic16_emitcode("mov","a,%s",l);
9561           pic16_aopPut(AOP(result),"a",offset);
9562       } else
9563 #endif
9564       {
9565         /* we don't know if left is a literal or a register, take care -- VR */
9566         pic16_mov2f(AOP(result), AOP(left), offset);
9567       }
9568       offset++;
9569     }
9570   }
9571
9572   size = AOP_SIZE(result);
9573
9574   /* if it is only one byte then */
9575   if (size == 1) {
9576     if(optimized_for_speed) {
9577       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9578       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9579       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9580       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9581       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9582       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9583       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9584       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9585       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9586       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9587       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9588       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9589     } else {
9590
9591       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9592
9593       tlbl = newiTempLabel(NULL);
9594
9595 #if 1
9596       /* this is already done, why change it? */
9597       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9598                 pic16_mov2f(AOP(result), AOP(left), 0);
9599       }
9600 #endif
9601
9602       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9603       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9604       pic16_emitpLabel(tlbl->key);
9605       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9606       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9607       emitSKPC;
9608       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9609     }
9610     goto release ;
9611   }
9612     
9613   if (pic16_sameRegs(AOP(left),AOP(result))) {
9614
9615     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9616     
9617     tlbl = newiTempLabel(NULL);
9618     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9619     genMultiAsm(POC_RRCF, result, size,1);
9620     pic16_emitpLabel(tlbl->key);
9621     genMultiAsm(POC_RLCF, result, size,0);
9622     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9623     emitSKPC;
9624     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9625     goto release;
9626   }
9627
9628   //tlbl = newiTempLabel(NULL);
9629   //offset = 0 ;   
9630   //tlbl1 = newiTempLabel(NULL);
9631
9632   //reAdjustPreg(AOP(result));    
9633     
9634   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9635   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9636   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9637   //MOVA(l);
9638   //pic16_emitcode("add","a,acc");         
9639   //pic16_aopPut(AOP(result),"a",offset++);
9640   //while (--size) {
9641   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9642   //  MOVA(l);
9643   //  pic16_emitcode("rlc","a");         
9644   //  pic16_aopPut(AOP(result),"a",offset++);
9645   //}
9646   //reAdjustPreg(AOP(result));
9647
9648   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9649   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9650
9651
9652   tlbl = newiTempLabel(NULL);
9653   tlbl1= newiTempLabel(NULL);
9654
9655   size = AOP_SIZE(result);
9656   offset = 1;
9657
9658   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9659
9660   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9661
9662   /* offset should be 0, 1 or 3 */
9663   
9664   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9665   emitSKPNZ;
9666   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9667
9668   pic16_emitpcode(POC_MOVWF, pctemp);
9669
9670
9671   pic16_emitpLabel(tlbl->key);
9672
9673   emitCLRC;
9674   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9675   while(--size)
9676     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9677
9678   pic16_emitpcode(POC_DECFSZ,  pctemp);
9679   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9680   pic16_emitpLabel(tlbl1->key);
9681
9682   pic16_popReleaseTempReg(pctemp,1);
9683
9684
9685  release:
9686   pic16_freeAsmop (right,NULL,ic,TRUE);
9687   pic16_freeAsmop(left,NULL,ic,TRUE);
9688   pic16_freeAsmop(result,NULL,ic,TRUE);
9689 }
9690 #endif
9691
9692
9693 #if 0
9694 #error old code (left here for reference)
9695 /*-----------------------------------------------------------------*/
9696 /* genLeftShift - generates code for left shifting                 */
9697 /*-----------------------------------------------------------------*/
9698 static void genLeftShift (iCode *ic)
9699 {
9700   operand *left,*right, *result;
9701   int size, offset;
9702   char *l;
9703   symbol *tlbl , *tlbl1;
9704   pCodeOp *pctemp;
9705
9706   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9707
9708   right = IC_RIGHT(ic);
9709   left  = IC_LEFT(ic);
9710   result = IC_RESULT(ic);
9711
9712   pic16_aopOp(right,ic,FALSE);
9713
9714   /* if the shift count is known then do it 
9715      as efficiently as possible */
9716   if (AOP_TYPE(right) == AOP_LIT) {
9717     pic16_genLeftShiftLiteral (left,right,result,ic);
9718     return ;
9719   }
9720
9721   /* shift count is unknown then we have to form 
9722      a loop get the loop count in B : Note: we take
9723      only the lower order byte since shifting
9724      more that 32 bits make no sense anyway, ( the
9725      largest size of an object can be only 32 bits ) */  
9726
9727     
9728   pic16_aopOp(left,ic,FALSE);
9729   pic16_aopOp(result,ic,FALSE);
9730
9731   /* now move the left to the result if they are not the
9732      same */
9733   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9734       AOP_SIZE(result) > 1) {
9735
9736     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9737
9738     size = AOP_SIZE(result);
9739     offset=0;
9740     while (size--) {
9741       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9742       if (*l == '@' && (IS_AOP_PREG(result))) {
9743
9744         pic16_emitcode("mov","a,%s",l);
9745         pic16_aopPut(AOP(result),"a",offset);
9746       } else {
9747
9748         /* we don't know if left is a literal or a register, take care -- VR */
9749         pic16_mov2f(AOP(result), AOP(left), offset);
9750       }
9751       offset++;
9752     }
9753   }
9754
9755   size = AOP_SIZE(result);
9756
9757   /* if it is only one byte then */
9758   if (size == 1) {
9759     if(optimized_for_speed) {
9760       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9761       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9762       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9763       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9764       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9765       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9766       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9767       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9768       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9769       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9770       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9771       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9772     } else {
9773
9774       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9775
9776       tlbl = newiTempLabel(NULL);
9777       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9778                 pic16_mov2f(AOP(result), AOP(left), 0);
9779                 
9780 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9781 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9782       }
9783
9784       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9785       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9786       pic16_emitpLabel(tlbl->key);
9787       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9788       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9789       emitSKPC;
9790       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9791     }
9792     goto release ;
9793   }
9794     
9795   if (pic16_sameRegs(AOP(left),AOP(result))) {
9796
9797     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9798     
9799     tlbl = newiTempLabel(NULL);
9800     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9801     genMultiAsm(POC_RRCF, result, size,1);
9802     pic16_emitpLabel(tlbl->key);
9803     genMultiAsm(POC_RLCF, result, size,0);
9804     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9805     emitSKPC;
9806     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9807     goto release;
9808   }
9809
9810   //tlbl = newiTempLabel(NULL);
9811   //offset = 0 ;   
9812   //tlbl1 = newiTempLabel(NULL);
9813
9814   //reAdjustPreg(AOP(result));    
9815     
9816   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9817   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9818   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9819   //MOVA(l);
9820   //pic16_emitcode("add","a,acc");         
9821   //pic16_aopPut(AOP(result),"a",offset++);
9822   //while (--size) {
9823   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9824   //  MOVA(l);
9825   //  pic16_emitcode("rlc","a");         
9826   //  pic16_aopPut(AOP(result),"a",offset++);
9827   //}
9828   //reAdjustPreg(AOP(result));
9829
9830   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9831   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9832
9833
9834   tlbl = newiTempLabel(NULL);
9835   tlbl1= newiTempLabel(NULL);
9836
9837   size = AOP_SIZE(result);
9838   offset = 1;
9839
9840   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9841
9842   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9843
9844   /* offset should be 0, 1 or 3 */
9845   
9846   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9847   emitSKPNZ;
9848   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9849
9850   pic16_emitpcode(POC_MOVWF, pctemp);
9851
9852
9853   pic16_emitpLabel(tlbl->key);
9854
9855   emitCLRC;
9856   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9857   while(--size)
9858     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9859
9860   pic16_emitpcode(POC_DECFSZ,  pctemp);
9861   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9862   pic16_emitpLabel(tlbl1->key);
9863
9864   pic16_popReleaseTempReg(pctemp,1);
9865
9866
9867  release:
9868   pic16_freeAsmop (right,NULL,ic,TRUE);
9869   pic16_freeAsmop(left,NULL,ic,TRUE);
9870   pic16_freeAsmop(result,NULL,ic,TRUE);
9871 }
9872 #endif
9873
9874 /*-----------------------------------------------------------------*/
9875 /* genrshOne - right shift a one byte quantity by known count      */
9876 /*-----------------------------------------------------------------*/
9877 static void genrshOne (operand *result, operand *left,
9878                        int shCount, int sign)
9879 {
9880     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9881     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9882 }
9883
9884 /*-----------------------------------------------------------------*/
9885 /* genrshTwo - right shift two bytes by known amount != 0          */
9886 /*-----------------------------------------------------------------*/
9887 static void genrshTwo (operand *result,operand *left,
9888                        int shCount, int sign)
9889 {
9890   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9891   /* if shCount >= 8 */
9892   if (shCount >= 8) {
9893     shCount -= 8 ;
9894     if (shCount)
9895       shiftR1Left2Result(left, MSB16, result, LSB,
9896                          shCount, sign);
9897     else
9898       movLeft2Result(left, MSB16, result, LSB);
9899
9900     pic16_addSign (result, 1, sign);
9901   }
9902
9903   /*  1 <= shCount <= 7 */
9904   else
9905     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9906 }
9907
9908 /*-----------------------------------------------------------------*/
9909 /* shiftRLong - shift right one long from left to result           */
9910 /* offl = LSB or MSB16                                             */
9911 /*-----------------------------------------------------------------*/
9912 static void shiftRLong (operand *left, int offl,
9913                         operand *result, int sign)
9914 {
9915     int size = AOP_SIZE(result);
9916     int same = pic16_sameRegs(AOP(left),AOP(result));
9917     int i;
9918     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9919
9920         if (same && (offl == MSB16)) { //shift one byte right
9921                 for(i=MSB16;i<size;i++) {
9922                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9923                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9924                 }
9925         }
9926
9927     if(sign)
9928                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9929         else
9930                 emitCLRC;
9931
9932         if (same) {
9933                 if (offl == LSB)
9934                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9935         } else {
9936         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9937         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9938         }
9939
9940     if(offl == MSB16) {
9941         /* add sign of "a" */
9942         pic16_addSign(result, MSB32, sign);
9943         }
9944
9945         if (same) {
9946         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9947         } else {
9948         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9949         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9950         }
9951         
9952         if (same) {
9953         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9954         } else {
9955         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9956         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9957         }
9958
9959         if (same) {
9960         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9961         } else {
9962         if(offl == LSB){
9963                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9964                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9965         }
9966         }
9967 }
9968
9969 /*-----------------------------------------------------------------*/
9970 /* genrshFour - shift four byte by a known amount != 0             */
9971 /*-----------------------------------------------------------------*/
9972 static void genrshFour (operand *result, operand *left,
9973                         int shCount, int sign)
9974 {
9975   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9976   /* if shifting more that 3 bytes */
9977   if(shCount >= 24 ) {
9978     shCount -= 24;
9979     if(shCount)
9980       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9981     else
9982       movLeft2Result(left, MSB32, result, LSB);
9983
9984     pic16_addSign(result, MSB16, sign);
9985   }
9986   else if(shCount >= 16){
9987     shCount -= 16;
9988     if(shCount)
9989       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9990     else{
9991       movLeft2Result(left, MSB24, result, LSB);
9992       movLeft2Result(left, MSB32, result, MSB16);
9993     }
9994     pic16_addSign(result, MSB24, sign);
9995   }
9996   else if(shCount >= 8){
9997     shCount -= 8;
9998     if(shCount == 1)
9999       shiftRLong(left, MSB16, result, sign);
10000     else if(shCount == 0){
10001       movLeft2Result(left, MSB16, result, LSB);
10002       movLeft2Result(left, MSB24, result, MSB16);
10003       movLeft2Result(left, MSB32, result, MSB24);
10004       pic16_addSign(result, MSB32, sign);
10005     }
10006     else{ //shcount >= 2
10007       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10008       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10009       /* the last shift is signed */
10010       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10011       pic16_addSign(result, MSB32, sign);
10012     }
10013   }
10014   else{   /* 1 <= shCount <= 7 */
10015     if(shCount <= 2){
10016       shiftRLong(left, LSB, result, sign);
10017       if(shCount == 2)
10018         shiftRLong(result, LSB, result, sign);
10019     }
10020     else{
10021       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10022       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10023       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10024     }
10025   }
10026 }
10027
10028 /*-----------------------------------------------------------------*/
10029 /* genRightShiftLiteral - right shifting by known count            */
10030 /*-----------------------------------------------------------------*/
10031 static void genRightShiftLiteral (operand *left,
10032                                   operand *right,
10033                                   operand *result,
10034                                   iCode *ic,
10035                                   int sign)
10036 {    
10037   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10038   int lsize,res_size;
10039
10040   pic16_freeAsmop(right,NULL,ic,TRUE);
10041
10042   pic16_aopOp(left,ic,FALSE);
10043   pic16_aopOp(result,ic,TRUE);
10044
10045   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10046
10047 #if VIEW_SIZE
10048   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10049                  AOP_SIZE(left));
10050 #endif
10051
10052   lsize = pic16_getDataSize(left);
10053   res_size = pic16_getDataSize(result);
10054   /* test the LEFT size !!! */
10055
10056   /* I suppose that the left size >= result size */
10057   if(shCount == 0){
10058     assert (res_size <= lsize);
10059     while (res_size--) {
10060       pic16_mov2f (AOP(result), AOP(left), res_size);
10061     } // for
10062   }
10063
10064   else if(shCount >= (lsize * 8)){
10065
10066     if(res_size == 1) {
10067       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10068       if(sign) {
10069         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10070         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10071       }
10072     } else {
10073
10074       if(sign) {
10075         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10076         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10077         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10078         while(res_size--)
10079           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10080
10081       } else {
10082
10083         while(res_size--)
10084           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10085       }
10086     }
10087   } else {
10088
10089     switch (res_size) {
10090     case 1:
10091       genrshOne (result,left,shCount,sign);
10092       break;
10093
10094     case 2:
10095       genrshTwo (result,left,shCount,sign);
10096       break;
10097
10098     case 4:
10099       genrshFour (result,left,shCount,sign);
10100       break;
10101     default :
10102       break;
10103     }
10104
10105   }
10106
10107   pic16_freeAsmop(left,NULL,ic,TRUE);
10108   pic16_freeAsmop(result,NULL,ic,TRUE);
10109 }
10110
10111 #if !(USE_GENERIC_SIGNED_SHIFT)
10112 /*-----------------------------------------------------------------*/
10113 /* genSignedRightShift - right shift of signed number              */
10114 /*-----------------------------------------------------------------*/
10115 static void genSignedRightShift (iCode *ic)
10116 {
10117   operand *right, *left, *result;
10118   int size, offset;
10119   //  char *l;
10120   symbol *tlbl, *tlbl1 ;
10121   pCodeOp *pctemp;
10122
10123   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10124
10125   /* we do it the hard way put the shift count in b
10126      and loop thru preserving the sign */
10127   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10128
10129   right = IC_RIGHT(ic);
10130   left  = IC_LEFT(ic);
10131   result = IC_RESULT(ic);
10132
10133   pic16_aopOp(right,ic,FALSE);  
10134   pic16_aopOp(left,ic,FALSE);
10135   pic16_aopOp(result,ic,FALSE);
10136
10137
10138   if ( AOP_TYPE(right) == AOP_LIT) {
10139     genRightShiftLiteral (left,right,result,ic,1);
10140     return ;
10141   }
10142   /* shift count is unknown then we have to form 
10143      a loop get the loop count in B : Note: we take
10144      only the lower order byte since shifting
10145      more that 32 bits make no sense anyway, ( the
10146      largest size of an object can be only 32 bits ) */  
10147
10148   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10149   //pic16_emitcode("inc","b");
10150   //pic16_freeAsmop (right,NULL,ic,TRUE);
10151   //pic16_aopOp(left,ic,FALSE);
10152   //pic16_aopOp(result,ic,FALSE);
10153
10154   /* now move the left to the result if they are not the
10155      same */
10156   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10157       AOP_SIZE(result) > 1) {
10158
10159     size = AOP_SIZE(result);
10160     offset=0;
10161     while (size--) { 
10162       /*
10163         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10164         if (*l == '@' && IS_AOP_PREG(result)) {
10165
10166         pic16_emitcode("mov","a,%s",l);
10167         pic16_aopPut(AOP(result),"a",offset);
10168         } else
10169         pic16_aopPut(AOP(result),l,offset);
10170       */
10171       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10172       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10173
10174       offset++;
10175     }
10176   }
10177
10178   /* mov the highest order bit to OVR */    
10179   tlbl = newiTempLabel(NULL);
10180   tlbl1= newiTempLabel(NULL);
10181
10182   size = AOP_SIZE(result);
10183   offset = size - 1;
10184
10185   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10186
10187   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10188
10189   /* offset should be 0, 1 or 3 */
10190   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10191   emitSKPNZ;
10192   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10193
10194   pic16_emitpcode(POC_MOVWF, pctemp);
10195
10196
10197   pic16_emitpLabel(tlbl->key);
10198
10199   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10200   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10201
10202   while(--size) {
10203     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10204   }
10205
10206   pic16_emitpcode(POC_DECFSZ,  pctemp);
10207   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10208   pic16_emitpLabel(tlbl1->key);
10209
10210   pic16_popReleaseTempReg(pctemp,1);
10211 #if 0
10212   size = AOP_SIZE(result);
10213   offset = size - 1;
10214   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10215   pic16_emitcode("rlc","a");
10216   pic16_emitcode("mov","ov,c");
10217   /* if it is only one byte then */
10218   if (size == 1) {
10219     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10220     MOVA(l);
10221     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10222     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10223     pic16_emitcode("mov","c,ov");
10224     pic16_emitcode("rrc","a");
10225     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10226     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10227     pic16_aopPut(AOP(result),"a",0);
10228     goto release ;
10229   }
10230
10231   reAdjustPreg(AOP(result));
10232   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10233   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10234   pic16_emitcode("mov","c,ov");
10235   while (size--) {
10236     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10237     MOVA(l);
10238     pic16_emitcode("rrc","a");         
10239     pic16_aopPut(AOP(result),"a",offset--);
10240   }
10241   reAdjustPreg(AOP(result));
10242   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10243   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10244
10245  release:
10246 #endif
10247
10248   pic16_freeAsmop(left,NULL,ic,TRUE);
10249   pic16_freeAsmop(result,NULL,ic,TRUE);
10250   pic16_freeAsmop(right,NULL,ic,TRUE);
10251 }
10252 #endif
10253
10254 #if !(USE_GENERIC_SIGNED_SHIFT)
10255 #warning This implementation of genRightShift() is incomplete!
10256 /*-----------------------------------------------------------------*/
10257 /* genRightShift - generate code for right shifting                */
10258 /*-----------------------------------------------------------------*/
10259 static void genRightShift (iCode *ic)
10260 {
10261     operand *right, *left, *result;
10262     sym_link *letype ;
10263     int size, offset;
10264     char *l;
10265     symbol *tlbl, *tlbl1 ;
10266
10267     /* if signed then we do it the hard way preserve the
10268     sign bit moving it inwards */
10269     letype = getSpec(operandType(IC_LEFT(ic)));
10270     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10271
10272     if (!SPEC_USIGN(letype)) {
10273         genSignedRightShift (ic);
10274         return ;
10275     }
10276
10277     /* signed & unsigned types are treated the same : i.e. the
10278     signed is NOT propagated inwards : quoting from the
10279     ANSI - standard : "for E1 >> E2, is equivalent to division
10280     by 2**E2 if unsigned or if it has a non-negative value,
10281     otherwise the result is implementation defined ", MY definition
10282     is that the sign does not get propagated */
10283
10284     right = IC_RIGHT(ic);
10285     left  = IC_LEFT(ic);
10286     result = IC_RESULT(ic);
10287
10288     pic16_aopOp(right,ic,FALSE);
10289
10290     /* if the shift count is known then do it 
10291     as efficiently as possible */
10292     if (AOP_TYPE(right) == AOP_LIT) {
10293         genRightShiftLiteral (left,right,result,ic, 0);
10294         return ;
10295     }
10296
10297     /* shift count is unknown then we have to form 
10298     a loop get the loop count in B : Note: we take
10299     only the lower order byte since shifting
10300     more that 32 bits make no sense anyway, ( the
10301     largest size of an object can be only 32 bits ) */  
10302
10303     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10304     pic16_emitcode("inc","b");
10305     pic16_aopOp(left,ic,FALSE);
10306     pic16_aopOp(result,ic,FALSE);
10307
10308     /* now move the left to the result if they are not the
10309     same */
10310     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10311         AOP_SIZE(result) > 1) {
10312
10313         size = AOP_SIZE(result);
10314         offset=0;
10315         while (size--) {
10316             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10317             if (*l == '@' && IS_AOP_PREG(result)) {
10318
10319                 pic16_emitcode("mov","a,%s",l);
10320                 pic16_aopPut(AOP(result),"a",offset);
10321             } else
10322                 pic16_aopPut(AOP(result),l,offset);
10323             offset++;
10324         }
10325     }
10326
10327     tlbl = newiTempLabel(NULL);
10328     tlbl1= newiTempLabel(NULL);
10329     size = AOP_SIZE(result);
10330     offset = size - 1;
10331
10332     /* if it is only one byte then */
10333     if (size == 1) {
10334
10335       tlbl = newiTempLabel(NULL);
10336       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10337         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10338         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10339       }
10340
10341       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10342       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10343       pic16_emitpLabel(tlbl->key);
10344       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10345       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10346       emitSKPC;
10347       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10348
10349       goto release ;
10350     }
10351
10352     reAdjustPreg(AOP(result));
10353     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10354     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10355     CLRC;
10356     while (size--) {
10357         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10358         MOVA(l);
10359         pic16_emitcode("rrc","a");         
10360         pic16_aopPut(AOP(result),"a",offset--);
10361     }
10362     reAdjustPreg(AOP(result));
10363
10364     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10365     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10366
10367 release:
10368     pic16_freeAsmop(left,NULL,ic,TRUE);
10369     pic16_freeAsmop (right,NULL,ic,TRUE);
10370     pic16_freeAsmop(result,NULL,ic,TRUE);
10371 }
10372 #endif
10373
10374 #if (USE_GENERIC_SIGNED_SHIFT)
10375 /*-----------------------------------------------------------------*/
10376 /* genGenericShift - generates code for left or right shifting     */
10377 /*-----------------------------------------------------------------*/
10378 static void genGenericShift (iCode *ic, int isShiftLeft) {
10379   operand *left,*right, *result;
10380   int offset;
10381   int sign, signedCount;
10382   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10383   PIC_OPCODE pos_shift, neg_shift;
10384
10385   FENTRY;
10386
10387   right = IC_RIGHT(ic);
10388   left  = IC_LEFT(ic);
10389   result = IC_RESULT(ic);
10390
10391   pic16_aopOp(right,ic,FALSE);
10392   pic16_aopOp(left,ic,FALSE);
10393   pic16_aopOp(result,ic,TRUE);
10394
10395   sign = !SPEC_USIGN(operandType (left));
10396   signedCount = !SPEC_USIGN(operandType (right));
10397
10398   /* if the shift count is known then do it 
10399      as efficiently as possible */
10400   if (AOP_TYPE(right) == AOP_LIT) {
10401     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10402     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10403     // we should modify right->aopu.aop_lit here!
10404     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10405     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10406     if (isShiftLeft)
10407       pic16_genLeftShiftLiteral (left,right,result,ic);
10408     else
10409       genRightShiftLiteral (left,right,result,ic, sign);
10410
10411     goto release;
10412   } // if (right is literal)
10413
10414   /* shift count is unknown then we have to form a loop.
10415    * Note: we take only the lower order byte since shifting
10416    * more than 32 bits make no sense anyway, ( the
10417    * largest size of an object can be only 32 bits )
10418    * Note: we perform arithmetic shifts if the left operand is
10419    * signed and we do an (effective) right shift, i. e. we
10420    * shift in the sign bit from the left. */
10421    
10422   label_complete = newiTempLabel ( NULL );
10423   label_loop_pos = newiTempLabel ( NULL );
10424   label_loop_neg = NULL;
10425   label_negative = NULL;
10426   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10427   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10428
10429   if (signedCount) {
10430     // additional labels needed
10431     label_loop_neg = newiTempLabel ( NULL );
10432     label_negative = newiTempLabel ( NULL );
10433   } // if
10434
10435   // copy source to result -- this will effectively truncate the left operand to the size of result!
10436   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10437   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10438   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10439     pic16_mov2f (AOP(result),AOP(left), offset);
10440   } // for
10441
10442   // if result is longer than left, fill with zeros (or sign)
10443   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10444     if (sign && AOP_SIZE(left) > 0) {
10445       // shift signed operand -- fill with sign
10446       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10447       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10448       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10449       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10450         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10451       } // for
10452     } else {
10453       // shift unsigned operand -- fill result with zeros
10454       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10455         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10456       } // for
10457     }
10458   } // if (size mismatch)
10459
10460   pic16_mov2w (AOP(right), 0);
10461   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10462   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10463   
10464 #if 0
10465   // perform a shift by one (shift count is positive)
10466   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10467   // 2n+[2,3]+({1,3}+n+3)c-2+[0,2]=({4,6}+n)c+2n+[0,3]          ({5,7}c+[2,5] / {6,8}c+[4, 7] / {8,10}c+[ 8,11])
10468   pic16_emitpLabel (label_loop_pos->key);
10469   emitCLRC;
10470   if (sign && (pos_shift == POC_RRCF)) {
10471     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10472     emitSETC;
10473   } // if
10474   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10475   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10476   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10477 #else
10478   // perform a shift by one (shift count is positive)
10479   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10480   // 2n+[2,3]+2+({0,2}+n+3)c-1+[0,2]=({3,5}+n)c+2n+[3,6]        ({4,6}c+[5,8] / {5,7}c+[7,10] / {7, 9}c+[11,14])
10481   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10482   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10483   emitCLRC;
10484   pic16_emitpLabel (label_loop_pos->key);
10485   if (sign && (pos_shift == POC_RRCF)) {
10486     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10487     emitSETC;
10488   } // if
10489   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10490   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10491   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10492   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10493 #endif
10494
10495   if (signedCount) {
10496     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10497
10498     pic16_emitpLabel (label_negative->key);
10499     // perform a shift by -1 (shift count is negative)
10500     // 2n+4+1+({0,2}+n+3)*c-1=({3,5}+n)c+2n+4                   ({4,6}c+6 / {5,7}c+8 / {7,9}c+12)
10501     emitCLRC;
10502     pic16_emitpLabel (label_loop_neg->key);
10503     if (sign && (neg_shift == POC_RRCF)) {
10504       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10505       emitSETC;
10506     } // if
10507     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10508     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10509     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10510     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10511   } // if (signedCount)
10512
10513   pic16_emitpLabel (label_complete->key);
10514
10515 release:
10516   pic16_freeAsmop (right,NULL,ic,TRUE);
10517   pic16_freeAsmop(left,NULL,ic,TRUE);
10518   pic16_freeAsmop(result,NULL,ic,TRUE);
10519 }
10520
10521 static void genLeftShift (iCode *ic) {
10522   genGenericShift (ic, 1);
10523 }
10524
10525 static void genRightShift (iCode *ic) {
10526   genGenericShift (ic, 0);
10527 }
10528 #endif
10529
10530
10531 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10532 void pic16_loadFSR0(operand *op, int lit)
10533 {
10534   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10535     if (AOP_TYPE(op) == AOP_LIT) {
10536       /* handle 12 bit integers correctly */
10537       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10538       if ((val & 0x0fff) != val) {
10539         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10540                 val, (val & 0x0fff) );
10541         val &= 0x0fff;
10542       }
10543       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10544     } else {
10545       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10546     }
10547   } else {
10548     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10549     // set up FSR0 with address of result
10550     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10551     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10552   }
10553 }
10554
10555 /*----------------------------------------------------------------*/
10556 /* pic16_derefPtr - move one byte from the location ptr points to */
10557 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10558 /*                  to the location ptr points to (doWrite != 0)   */
10559 /*----------------------------------------------------------------*/
10560 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10561 {
10562   if (!IS_PTR(operandType(ptr)))
10563   {
10564     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10565     else pic16_mov2w (AOP(ptr), 0);
10566     return;
10567   }
10568
10569   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10570   /* We might determine pointer type right here: */
10571   p_type = DCL_TYPE(operandType(ptr));
10572
10573   switch (p_type) {
10574     case FPOINTER:
10575     case POINTER:
10576       if (!fsr0_setup || !*fsr0_setup)
10577       {
10578         pic16_loadFSR0( ptr, 0 );
10579         if (fsr0_setup) *fsr0_setup = 1;
10580       }
10581       if (doWrite)
10582         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10583       else
10584         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10585       break;
10586
10587     case GPOINTER:
10588       if (AOP(ptr)->aopu.aop_reg[2]) {
10589         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10590         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10591         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10592         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10593         pic16_mov2w(AOP(ptr), 2);
10594         pic16_callGenericPointerRW(doWrite, 1);
10595       } else {
10596         // data pointer (just 2 byte given)
10597         if (!fsr0_setup || !*fsr0_setup)
10598         {
10599           pic16_loadFSR0( ptr, 0 );
10600           if (fsr0_setup) *fsr0_setup = 1;
10601         }
10602         if (doWrite)
10603           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10604         else
10605           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10606       }
10607       break;
10608
10609     default:
10610       assert (0 && "invalid pointer type specified");
10611       break;
10612   }
10613 }
10614
10615 /*-----------------------------------------------------------------*/
10616 /* genUnpackBits - generates code for unpacking bits               */
10617 /*-----------------------------------------------------------------*/
10618 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10619 {    
10620   int shCnt ;
10621   sym_link *etype, *letype;
10622   int blen=0, bstr=0;
10623   int lbstr;
10624   int same;
10625   pCodeOp *op;
10626
10627   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10628   etype = getSpec(operandType(result));
10629   letype = getSpec(operandType(left));
10630
10631   //    if(IS_BITFIELD(etype)) {
10632   blen = SPEC_BLEN(etype);
10633   bstr = SPEC_BSTR(etype);
10634   //    }
10635
10636   lbstr = SPEC_BSTR( letype );
10637
10638   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10639       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10640
10641 #if 1
10642   if((blen == 1) && (bstr < 8)
10643       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10644     /* it is a single bit, so use the appropriate bit instructions */
10645     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10646
10647     same = pic16_sameRegs(AOP(left),AOP(result));
10648     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10649     pic16_emitpcode(POC_CLRF, op);
10650
10651     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10652       /* workaround to reduce the extra lfsr instruction */
10653       pic16_emitpcode(POC_BTFSC,
10654           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10655     } else {
10656       assert (PIC_IS_DATA_PTR (operandType(left)));
10657       pic16_loadFSR0 (left, 0);
10658       pic16_emitpcode(POC_BTFSC,
10659           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10660     }
10661
10662     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10663       /* unsigned bitfields result in either 0 or 1 */
10664       pic16_emitpcode(POC_INCF, op);
10665     } else {
10666       /* signed bitfields result in either 0 or -1 */
10667       pic16_emitpcode(POC_DECF, op);
10668     }
10669     if (same) {
10670       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10671     }
10672
10673     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10674     return;
10675   }
10676
10677 #endif
10678
10679   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10680     // access symbol directly
10681     pic16_mov2w (AOP(left), 0);
10682   } else {
10683     pic16_derefPtr (left, ptype, 0, NULL);
10684   }
10685
10686   /* if we have bitdisplacement then it fits   */
10687   /* into this byte completely or if length is */
10688   /* less than a byte                          */
10689   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10690
10691     /* shift right acc */
10692     AccRsh(shCnt, 0);
10693
10694     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10695           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10696
10697     /* VR -- normally I would use the following, but since we use the hack,
10698      * to avoid the masking from AccRsh, why not mask it right now? */
10699
10700     /*
10701        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10702      */
10703
10704     /* extend signed bitfields to 8 bits */
10705     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10706     {
10707       assert (blen + bstr > 0);
10708       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10709       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10710     }
10711
10712     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10713
10714     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10715     return ;
10716   }
10717
10718   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10719   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10720   exit(-1);
10721
10722   return ;
10723 }
10724
10725
10726 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10727 {
10728   int size, offset = 0, leoffset=0 ;
10729
10730         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10731         pic16_aopOp(result, ic, TRUE);
10732
10733         FENTRY;
10734
10735         size = AOP_SIZE(result);
10736 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10737
10738
10739 #if 1
10740         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10741                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10742                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10743                 goto release;
10744         }
10745 #endif
10746
10747         if(AOP(left)->aopu.pcop->type == PO_DIR)
10748                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10749
10750         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10751
10752         while (size--) {
10753                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10754                 
10755 //              pic16_DumpOp("(result)",result);
10756                 if(is_LitAOp(AOP(result))) {
10757                         pic16_mov2w(AOP(left), offset); // patch 8
10758                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10759                 } else {
10760                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10761                                 pic16_popGet(AOP(left), offset), //patch 8
10762                                 pic16_popGet(AOP(result), offset)));
10763                 }
10764
10765                 offset++;
10766                 leoffset++;
10767         }
10768
10769 release:
10770     pic16_freeAsmop(result,NULL,ic,TRUE);
10771 }
10772
10773
10774
10775 /*-----------------------------------------------------------------*/
10776 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10777 /*-----------------------------------------------------------------*/
10778 static void genNearPointerGet (operand *left, 
10779                                operand *result, 
10780                                iCode *ic)
10781 {
10782 //  asmop *aop = NULL;
10783   //regs *preg = NULL ;
10784   sym_link *rtype, *retype;
10785   sym_link *ltype, *letype;
10786
10787     FENTRY;
10788     
10789     rtype = operandType(result);
10790     retype= getSpec(rtype);
10791     ltype = operandType(left);
10792     letype= getSpec(ltype);
10793     
10794     pic16_aopOp(left,ic,FALSE);
10795
10796 //    pic16_DumpOp("(left)",left);
10797 //    pic16_DumpOp("(result)",result);
10798
10799     /* if left is rematerialisable and
10800      * result is not bit variable type and
10801      * the left is pointer to data space i.e
10802      * lower 128 bytes of space */
10803     
10804     if (AOP_TYPE(left) == AOP_PCODE
10805       && !IS_BITFIELD(retype)
10806       && DCL_TYPE(ltype) == POINTER) {
10807
10808         genDataPointerGet (left,result,ic);
10809         pic16_freeAsmop(left, NULL, ic, TRUE);
10810         return ;
10811     }
10812     
10813     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10814     pic16_aopOp (result,ic,TRUE);
10815     
10816     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10817
10818 #if 1
10819     if(IS_BITFIELD( retype )
10820       && (SPEC_BLEN(operandType(result))==1)
10821     ) {
10822       iCode *nextic;
10823       pCodeOp *jop;
10824       int bitstrt, bytestrt;
10825
10826         /* if this is bitfield of size 1, see if we are checking the value
10827          * of a single bit in an if-statement,
10828          * if yes, then don't generate usual code, but execute the
10829          * genIfx directly -- VR */
10830
10831         nextic = ic->next;
10832
10833         /* CHECK: if next iCode is IFX
10834          * and current result operand is nextic's conditional operand
10835          * and current result operand live ranges ends at nextic's key number
10836          */
10837         if((nextic->op == IFX)
10838           && (result == IC_COND(nextic))
10839           && (OP_LIVETO(result) == nextic->seq)
10840           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10841           ) {
10842             /* everything is ok then */
10843             /* find a way to optimize the genIfx iCode */
10844
10845             bytestrt = SPEC_BSTR(operandType(result))/8;
10846             bitstrt = SPEC_BSTR(operandType(result))%8;
10847             
10848             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10849
10850             genIfxpCOpJump(nextic, jop);
10851             
10852             pic16_freeAsmop(left, NULL, ic, TRUE);
10853             pic16_freeAsmop(result, NULL, ic, TRUE);
10854             return;
10855         }
10856     }
10857 #endif
10858
10859     /* if bitfield then unpack the bits */
10860     if (IS_BITFIELD(letype)) 
10861       genUnpackBits (result, left, NULL, POINTER);
10862     else {
10863       /* we have can just get the values */
10864       int size = AOP_SIZE(result);
10865       int offset = 0;   
10866         
10867       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10868
10869       pic16_loadFSR0( left, 0 );
10870
10871       while(size--) {
10872         if(size) {
10873           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10874                 pic16_popGet(AOP(result), offset++)));
10875         } else {
10876           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10877                 pic16_popGet(AOP(result), offset++)));
10878         }
10879       }
10880     }
10881
10882 #if 0
10883     /* now some housekeeping stuff */
10884     if (aop) {
10885       /* we had to allocate for this iCode */
10886       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10887       pic16_freeAsmop(NULL,aop,ic,TRUE);
10888     } else { 
10889       /* we did not allocate which means left
10890        * already in a pointer register, then
10891        * if size > 0 && this could be used again
10892        * we have to point it back to where it 
10893        * belongs */
10894       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10895       if (AOP_SIZE(result) > 1
10896         && !OP_SYMBOL(left)->remat
10897         && ( OP_SYMBOL(left)->liveTo > ic->seq
10898             || ic->depth )) {
10899 //        int size = AOP_SIZE(result) - 1;
10900 //        while (size--)
10901 //          pic16_emitcode("dec","%s",rname);
10902         }
10903     }
10904 #endif
10905
10906     /* done */
10907     pic16_freeAsmop(left,NULL,ic,TRUE);
10908     pic16_freeAsmop(result,NULL,ic,TRUE);
10909 }
10910
10911 /*-----------------------------------------------------------------*/
10912 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10913 /*-----------------------------------------------------------------*/
10914 static void genPagedPointerGet (operand *left, 
10915                                operand *result, 
10916                                iCode *ic)
10917 {
10918     asmop *aop = NULL;
10919     regs *preg = NULL ;
10920     char *rname ;
10921     sym_link *rtype, *retype;    
10922
10923     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10924
10925     rtype = operandType(result);
10926     retype= getSpec(rtype);
10927     
10928     pic16_aopOp(left,ic,FALSE);
10929
10930   /* if the value is already in a pointer register
10931        then don't need anything more */
10932     if (!AOP_INPREG(AOP(left))) {
10933         /* otherwise get a free pointer register */
10934         aop = newAsmop(0);
10935         preg = getFreePtr(ic,&aop,FALSE);
10936         pic16_emitcode("mov","%s,%s",
10937                 preg->name,
10938                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10939         rname = preg->name ;
10940     } else
10941         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10942     
10943     pic16_freeAsmop(left,NULL,ic,TRUE);
10944     pic16_aopOp (result,ic,TRUE);
10945
10946     /* if bitfield then unpack the bits */
10947     if (IS_BITFIELD(retype)) 
10948         genUnpackBits (result,left,rname,PPOINTER);
10949     else {
10950         /* we have can just get the values */
10951         int size = AOP_SIZE(result);
10952         int offset = 0 ;        
10953         
10954         while (size--) {
10955             
10956             pic16_emitcode("movx","a,@%s",rname);
10957             pic16_aopPut(AOP(result),"a",offset);
10958             
10959             offset++ ;
10960             
10961             if (size)
10962                 pic16_emitcode("inc","%s",rname);
10963         }
10964     }
10965
10966     /* now some housekeeping stuff */
10967     if (aop) {
10968         /* we had to allocate for this iCode */
10969         pic16_freeAsmop(NULL,aop,ic,TRUE);
10970     } else { 
10971         /* we did not allocate which means left
10972            already in a pointer register, then
10973            if size > 0 && this could be used again
10974            we have to point it back to where it 
10975            belongs */
10976         if (AOP_SIZE(result) > 1 &&
10977             !OP_SYMBOL(left)->remat &&
10978             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10979               ic->depth )) {
10980             int size = AOP_SIZE(result) - 1;
10981             while (size--)
10982                 pic16_emitcode("dec","%s",rname);
10983         }
10984     }
10985
10986     /* done */
10987     pic16_freeAsmop(result,NULL,ic,TRUE);
10988     
10989         
10990 }
10991
10992 #if 0
10993 /* This code is not adjusted to PIC16 and fails utterly.
10994  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10995
10996 /*-----------------------------------------------------------------*/
10997 /* genFarPointerGet - gget value from far space                    */
10998 /*-----------------------------------------------------------------*/
10999 static void genFarPointerGet (operand *left,
11000                               operand *result, iCode *ic)
11001 {
11002     int size, offset ;
11003     sym_link *retype = getSpec(operandType(result));
11004
11005     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11006
11007     pic16_aopOp(left,ic,FALSE);
11008
11009     /* if the operand is already in dptr 
11010     then we do nothing else we move the value to dptr */
11011     if (AOP_TYPE(left) != AOP_STR) {
11012         /* if this is remateriazable */
11013         if (AOP_TYPE(left) == AOP_IMMD)
11014             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11015         else { /* we need to get it byte by byte */
11016             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11017             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11018             if (options.model == MODEL_FLAT24)
11019             {
11020                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11021             }
11022         }
11023     }
11024     /* so dptr know contains the address */
11025     pic16_freeAsmop(left,NULL,ic,TRUE);
11026     pic16_aopOp(result,ic,TRUE);
11027
11028     /* if bit then unpack */
11029     if (IS_BITFIELD(retype)) 
11030         genUnpackBits(result,left,"dptr",FPOINTER);
11031     else {
11032         size = AOP_SIZE(result);
11033         offset = 0 ;
11034
11035         while (size--) {
11036             pic16_emitcode("movx","a,@dptr");
11037             pic16_aopPut(AOP(result),"a",offset++);
11038             if (size)
11039                 pic16_emitcode("inc","dptr");
11040         }
11041     }
11042
11043     pic16_freeAsmop(result,NULL,ic,TRUE);
11044 }
11045 #endif
11046
11047 #if 0
11048 /*-----------------------------------------------------------------*/
11049 /* genCodePointerGet - get value from code space                  */
11050 /*-----------------------------------------------------------------*/
11051 static void genCodePointerGet (operand *left,
11052                                 operand *result, iCode *ic)
11053 {
11054     int size, offset ;
11055     sym_link *retype = getSpec(operandType(result));
11056
11057     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11058
11059     pic16_aopOp(left,ic,FALSE);
11060
11061     /* if the operand is already in dptr 
11062     then we do nothing else we move the value to dptr */
11063     if (AOP_TYPE(left) != AOP_STR) {
11064         /* if this is remateriazable */
11065         if (AOP_TYPE(left) == AOP_IMMD)
11066             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11067         else { /* we need to get it byte by byte */
11068             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11069             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11070             if (options.model == MODEL_FLAT24)
11071             {
11072                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11073             }
11074         }
11075     }
11076     /* so dptr know contains the address */
11077     pic16_freeAsmop(left,NULL,ic,TRUE);
11078     pic16_aopOp(result,ic,FALSE);
11079
11080     /* if bit then unpack */
11081     if (IS_BITFIELD(retype)) 
11082         genUnpackBits(result,left,"dptr",CPOINTER);
11083     else {
11084         size = AOP_SIZE(result);
11085         offset = 0 ;
11086
11087         while (size--) {
11088             pic16_emitcode("clr","a");
11089             pic16_emitcode("movc","a,@a+dptr");
11090             pic16_aopPut(AOP(result),"a",offset++);
11091             if (size)
11092                 pic16_emitcode("inc","dptr");
11093         }
11094     }
11095
11096     pic16_freeAsmop(result,NULL,ic,TRUE);
11097 }
11098 #endif
11099
11100 #if 0
11101 /*-----------------------------------------------------------------*/
11102 /* genGenPointerGet - gget value from generic pointer space        */
11103 /*-----------------------------------------------------------------*/
11104 static void genGenPointerGet (operand *left,
11105                               operand *result, iCode *ic)
11106 {
11107   int size, offset, lit;
11108   sym_link *retype = getSpec(operandType(result));
11109
11110         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11111         pic16_aopOp(left,ic,FALSE);
11112         pic16_aopOp(result,ic,FALSE);
11113         size = AOP_SIZE(result);
11114
11115         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11116
11117         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11118
11119                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11120                 // load FSR0 from immediate
11121                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11122
11123 //              pic16_loadFSR0( left );
11124
11125                 offset = 0;
11126                 while(size--) {
11127                         if(size) {
11128                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11129                         } else {
11130                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11131                         }
11132                         offset++;
11133                 }
11134                 goto release;
11135
11136         }
11137         else { /* we need to get it byte by byte */
11138                 // set up FSR0 with address from left
11139                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11140                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11141                 
11142                 offset = 0 ;
11143
11144                 while(size--) {
11145                         if(size) {
11146                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11147                         } else {
11148                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11149                         }
11150                         offset++;
11151                 }
11152                 goto release;
11153         }
11154
11155   /* if bit then unpack */
11156         if (IS_BITFIELD(retype)) 
11157                 genUnpackBits(result,left,"BAD",GPOINTER);
11158
11159         release:
11160         pic16_freeAsmop(left,NULL,ic,TRUE);
11161         pic16_freeAsmop(result,NULL,ic,TRUE);
11162
11163 }
11164 #endif
11165
11166
11167 /*-----------------------------------------------------------------*/
11168 /* genGenPointerGet - gget value from generic pointer space        */
11169 /*-----------------------------------------------------------------*/
11170 static void genGenPointerGet (operand *left,
11171                               operand *result, iCode *ic)
11172 {
11173   int size, offset, lit;
11174   sym_link *letype = getSpec(operandType(left));
11175
11176     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11177     pic16_aopOp(left,ic,FALSE);
11178     pic16_aopOp(result,ic,TRUE);
11179     size = AOP_SIZE(result);
11180
11181     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11182   
11183     /* if bit then unpack */
11184     if (IS_BITFIELD(letype)) {
11185       genUnpackBits(result,left,"BAD",GPOINTER);
11186       goto release;
11187     }
11188
11189     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11190
11191       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11192       // load FSR0 from immediate
11193       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11194
11195       werror(W_POSSBUG2, __FILE__, __LINE__);
11196
11197       offset = 0;
11198       while(size--) {
11199         if(size) {
11200           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11201         } else {
11202           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11203         }
11204         offset++;
11205       }
11206
11207       goto release;
11208
11209     } else { /* we need to get it byte by byte */
11210
11211       /* set up WREG:PRODL:FSR0L with address from left */
11212       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11213       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11214       pic16_mov2w(AOP(left), 2);
11215       pic16_callGenericPointerRW(0, size);
11216       
11217       assignResultValue(result, 1);
11218       
11219       goto release;
11220     }
11221
11222 release:
11223   pic16_freeAsmop(left,NULL,ic,TRUE);
11224   pic16_freeAsmop(result,NULL,ic,TRUE);
11225 }
11226
11227 /*-----------------------------------------------------------------*/
11228 /* genConstPointerGet - get value from const generic pointer space */
11229 /*-----------------------------------------------------------------*/
11230 static void genConstPointerGet (operand *left,
11231                                 operand *result, iCode *ic)
11232 {
11233   //sym_link *retype = getSpec(operandType(result));
11234   // symbol *albl = newiTempLabel(NULL);        // patch 15
11235   // symbol *blbl = newiTempLabel(NULL);        //
11236   // PIC_OPCODE poc;                            // patch 15
11237   int size;
11238   int offset = 0;
11239
11240   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11241   pic16_aopOp(left,ic,FALSE);
11242   pic16_aopOp(result,ic,TRUE);
11243   size = AOP_SIZE(result);
11244
11245   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11246
11247   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11248
11249   // set up table pointer
11250   if( (AOP_TYPE(left) == AOP_PCODE) 
11251       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11252           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11253     {
11254       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11255       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11256       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11257       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11258       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11259       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11260   } else {
11261     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11262     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11263     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11264   }
11265
11266   while(size--) {
11267     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11268     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11269     offset++;
11270   }
11271     
11272   pic16_freeAsmop(left,NULL,ic,TRUE);
11273   pic16_freeAsmop(result,NULL,ic,TRUE);
11274 }
11275
11276
11277 /*-----------------------------------------------------------------*/
11278 /* genPointerGet - generate code for pointer get                   */
11279 /*-----------------------------------------------------------------*/
11280 static void genPointerGet (iCode *ic)
11281 {
11282   operand *left, *result ;
11283   sym_link *type, *etype;
11284   int p_type;
11285
11286     FENTRY;
11287     
11288     left = IC_LEFT(ic);
11289     result = IC_RESULT(ic) ;
11290
11291     /* depending on the type of pointer we need to
11292     move it to the correct pointer register */
11293     type = operandType(left);
11294     etype = getSpec(type);
11295
11296 #if 0
11297     if (IS_PTR_CONST(type))
11298 #else
11299     if (IS_CODEPTR(type))
11300 #endif
11301       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11302
11303     /* if left is of type of pointer then it is simple */
11304     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11305       p_type = DCL_TYPE(type);
11306     else {
11307       /* we have to go by the storage class */
11308       p_type = PTR_TYPE(SPEC_OCLS(etype));
11309
11310       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11311
11312       if (SPEC_OCLS(etype)->codesp ) {
11313         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11314         //p_type = CPOINTER ;   
11315       } else
11316       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11317         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11318         /*p_type = FPOINTER ;*/ 
11319       } else
11320       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11321         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11322         /* p_type = PPOINTER; */
11323       } else
11324       if (SPEC_OCLS(etype) == idata ) {
11325         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11326         /* p_type = IPOINTER; */
11327       } else {
11328         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11329         /* p_type = POINTER ; */
11330       }
11331     }
11332
11333     /* now that we have the pointer type we assign
11334     the pointer values */
11335     switch (p_type) {
11336       case POINTER:     
11337       case FPOINTER:
11338       case IPOINTER:
11339         genNearPointerGet (left,result,ic);
11340         break;
11341
11342       case PPOINTER:
11343         genPagedPointerGet(left,result,ic);
11344         break;
11345
11346 #if 0
11347       /* PICs do not support FAR pointers... */
11348       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11349       case FPOINTER:
11350         genFarPointerGet (left,result,ic);
11351         break;
11352 #endif
11353
11354       case CPOINTER:
11355         genConstPointerGet (left,result,ic);
11356         //pic16_emitcodePointerGet (left,result,ic);
11357         break;
11358
11359       case GPOINTER:
11360 #if 0
11361       if (IS_PTR_CONST(type))
11362         genConstPointerGet (left,result,ic);
11363       else
11364 #endif
11365         genGenPointerGet (left,result,ic);
11366       break;
11367
11368     default:
11369       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11370               "genPointerGet: illegal pointer type");
11371     
11372     }
11373 }
11374
11375 /*-----------------------------------------------------------------*/
11376 /* genPackBits - generates code for packed bit storage             */
11377 /*-----------------------------------------------------------------*/
11378 static void genPackBits (sym_link    *etype , operand *result,
11379                          operand *right ,
11380                          char *rname, int p_type)
11381 {
11382   int shCnt = 0 ;
11383   int offset = 0  ;
11384   int rLen = 0 ;
11385   int blen, bstr ;   
11386   int shifted_and_masked = 0;
11387   unsigned long lit = (unsigned long)-1;
11388   sym_link *retype;
11389
11390   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11391   blen = SPEC_BLEN(etype);
11392   bstr = SPEC_BSTR(etype);
11393
11394   retype = getSpec(operandType(right));
11395
11396   if(AOP_TYPE(right) == AOP_LIT) {
11397     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11398     
11399     if((blen == 1) && (bstr < 8)) {
11400       /* it is a single bit, so use the appropriate bit instructions */
11401
11402       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11403
11404       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11405         /* workaround to reduce the extra lfsr instruction */
11406         if(lit) {
11407           pic16_emitpcode(POC_BSF,
11408               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11409         } else {
11410           pic16_emitpcode(POC_BCF,
11411               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11412         }
11413       } else {
11414         if (PIC_IS_DATA_PTR(operandType(result))) {
11415           pic16_loadFSR0(result, 0);
11416           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11417               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11418         } else {
11419           /* get old value */
11420           pic16_derefPtr (result, p_type, 0, NULL);
11421           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11422               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11423           /* write back new value */
11424           pic16_derefPtr (result, p_type, 1, NULL);
11425         }
11426       }
11427
11428       return;
11429     }
11430     /* IORLW below is more efficient */
11431     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11432     lit = (lit & ((1UL << blen) - 1)) << bstr;
11433     shifted_and_masked = 1;
11434     offset++;
11435   } else
11436     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11437         && IS_BITFIELD(retype) 
11438         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11439         && (blen == 1)) {
11440       int rblen, rbstr;
11441
11442       rblen = SPEC_BLEN( retype );
11443       rbstr = SPEC_BSTR( retype );
11444
11445       if(IS_BITFIELD(etype)) {
11446         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11447         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11448       } else {
11449         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11450       }
11451
11452       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11453
11454       if(IS_BITFIELD(etype)) {
11455         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11456       } else {
11457         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11458       }
11459
11460       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11461
11462       return;
11463     } else {
11464       /* move right to W */
11465       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11466     }
11467
11468   /* if the bit length is less than or   */
11469   /* it exactly fits a byte then         */
11470   if((shCnt=SPEC_BSTR(etype))
11471       || SPEC_BLEN(etype) <= 8 )  {
11472     int fsr0_setup = 0;
11473
11474     if (blen != 8 || bstr != 0) {
11475       // we need to combine the value with the old value
11476       if(!shifted_and_masked)
11477       {
11478         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11479
11480         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11481             SPEC_BSTR(etype), SPEC_BLEN(etype));
11482
11483         /* shift left acc, do NOT mask the result again */
11484         AccLsh(shCnt, 0);
11485
11486         /* using PRODH as a temporary register here */
11487         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11488       }
11489
11490       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11491         || IS_DIRECT(result)) {
11492         /* access symbol directly */
11493         pic16_mov2w (AOP(result), 0);
11494       } else {
11495         /* get old value */
11496         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11497       }
11498 #if 1
11499       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11500             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11501                             (unsigned char)(0xff >> (8-bstr))) ));
11502       if (!shifted_and_masked) {
11503         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11504       } else {
11505         /* We have the shifted and masked (literal) right value in `lit' */
11506         if (lit != 0)
11507           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11508       }
11509     } // if (blen != 8 || bstr != 0)
11510
11511     /* write new value back */
11512     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11513         || IS_DIRECT(result)) {
11514       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11515     } else {
11516       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11517     }
11518 #endif
11519
11520     return;
11521   }
11522
11523
11524 #if 0
11525   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11526   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11527   exit(-1);
11528 #endif
11529
11530
11531   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11532   rLen = SPEC_BLEN(etype)-8;
11533
11534   /* now generate for lengths greater than one byte */
11535   while (1) {
11536     rLen -= 8 ;
11537     if (rLen <= 0 ) {
11538       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11539       break ;
11540     }
11541
11542     switch (p_type) {
11543       case POINTER:
11544         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11545         break;
11546
11547         /*
11548            case FPOINTER:
11549            MOVA(l);
11550            pic16_emitcode("movx","@dptr,a");
11551            break;
11552
11553            case GPOINTER:
11554            MOVA(l);
11555            DEBUGpic16_emitcode(";lcall","__gptrput");
11556            break;  
11557          */
11558       default:
11559         assert(0);
11560     }   
11561
11562
11563     pic16_mov2w(AOP(right), offset++);
11564   }
11565
11566   /* last last was not complete */
11567   if (rLen)   {
11568     /* save the byte & read byte */
11569     switch (p_type) {
11570       case POINTER:
11571         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11572         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11573         break;
11574
11575         /*
11576            case FPOINTER:
11577            pic16_emitcode ("mov","b,a");
11578            pic16_emitcode("movx","a,@dptr");
11579            break;
11580
11581            case GPOINTER:
11582            pic16_emitcode ("push","b");
11583            pic16_emitcode ("push","acc");
11584            pic16_emitcode ("lcall","__gptrget");
11585            pic16_emitcode ("pop","b");
11586            break;
11587          */
11588       default:
11589         assert(0);
11590     }
11591     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11592     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11593     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11594     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11595     //        pic16_emitcode ("orl","a,b");
11596   }
11597
11598   //    if (p_type == GPOINTER)
11599   //        pic16_emitcode("pop","b");
11600
11601   switch (p_type) {
11602
11603     case POINTER:
11604       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11605       //        pic16_emitcode("mov","@%s,a",rname);
11606       break;
11607       /*
11608          case FPOINTER:
11609          pic16_emitcode("movx","@dptr,a");
11610          break;
11611
11612          case GPOINTER:
11613          DEBUGpic16_emitcode(";lcall","__gptrput");
11614          break;                 
11615        */
11616     default:
11617       assert(0);
11618   }
11619
11620   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11621 }
11622
11623 /*-----------------------------------------------------------------*/
11624 /* genDataPointerSet - remat pointer to data space                 */
11625 /*-----------------------------------------------------------------*/
11626 static void genDataPointerSet(operand *right,
11627                               operand *result,
11628                               iCode *ic)
11629 {
11630   int size, offset = 0, resoffset=0 ;
11631
11632     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11633     pic16_aopOp(right,ic,FALSE);
11634
11635     size = AOP_SIZE(right);
11636
11637 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11638
11639 #if 0
11640     if ( AOP_TYPE(result) == AOP_PCODE) {
11641       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11642               AOP(result)->aopu.pcop->name,
11643                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11644               PCOR(AOP(result)->aopu.pcop)->instance:
11645               PCOI(AOP(result)->aopu.pcop)->offset);
11646     }
11647 #endif
11648
11649     if(AOP(result)->aopu.pcop->type == PO_DIR)
11650       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11651
11652     while (size--) {
11653       if (AOP_TYPE(right) == AOP_LIT) {
11654         unsigned int lit;
11655
11656           if(!IS_FLOAT(operandType( right )))
11657             lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11658           else {
11659             union {
11660               unsigned long lit_int;
11661               float lit_float;
11662             } info;
11663         
11664               /* take care if literal is a float */
11665               info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11666               lit = info.lit_int;
11667           }
11668                     lit = lit >> (8*offset);
11669                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11670                 } else {
11671                   pic16_mov2w(AOP(right), offset);
11672                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11673                 }
11674                 offset++;
11675                 resoffset++;
11676         }
11677
11678     pic16_freeAsmop(right,NULL,ic,TRUE);
11679 }
11680
11681
11682
11683 /*-----------------------------------------------------------------*/
11684 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11685 /*-----------------------------------------------------------------*/
11686 static void genNearPointerSet (operand *right,
11687                                operand *result, 
11688                                iCode *ic)
11689 {
11690   asmop *aop = NULL;
11691   sym_link *retype;
11692   sym_link *ptype = operandType(result);
11693   sym_link *resetype;
11694     
11695     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11696     retype= getSpec(operandType(right));
11697     resetype = getSpec(operandType(result));
11698   
11699     pic16_aopOp(result,ic,FALSE);
11700     
11701     /* if the result is rematerializable &
11702      * in data space & not a bit variable */
11703         
11704     /* and result is not a bit variable */
11705     if (AOP_TYPE(result) == AOP_PCODE
11706 //      && AOP_TYPE(result) == AOP_IMMD
11707       && DCL_TYPE(ptype) == POINTER
11708       && !IS_BITFIELD(retype)
11709       && !IS_BITFIELD(resetype)) {
11710
11711         genDataPointerSet (right,result,ic);
11712         pic16_freeAsmop(result,NULL,ic,TRUE);
11713       return;
11714     }
11715
11716     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11717     pic16_aopOp(right,ic,FALSE);
11718     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11719
11720     /* if bitfield then unpack the bits */
11721     if (IS_BITFIELD(resetype)) {
11722       genPackBits (resetype, result, right, NULL, POINTER);
11723     } else {
11724       /* we have can just get the values */
11725       int size = AOP_SIZE(right);
11726       int offset = 0 ;    
11727
11728         pic16_loadFSR0(result, 0);
11729             
11730         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11731         while (size--) {
11732           if (AOP_TYPE(right) == AOP_LIT) {
11733             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11734             if (size) {
11735               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11736             } else {
11737               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11738             }
11739           } else { // no literal
11740             if(size) {
11741               pic16_emitpcode(POC_MOVFF,
11742                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11743                   pic16_popCopyReg(&pic16_pc_postinc0)));
11744             } else {
11745               pic16_emitpcode(POC_MOVFF,
11746                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11747                   pic16_popCopyReg(&pic16_pc_indf0)));
11748             }
11749           }
11750           
11751           offset++;
11752         }
11753     }
11754
11755     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11756     /* now some housekeeping stuff */
11757     if (aop) {
11758       /* we had to allocate for this iCode */
11759       pic16_freeAsmop(NULL,aop,ic,TRUE);
11760     } else { 
11761       /* we did not allocate which means left
11762        * already in a pointer register, then
11763        * if size > 0 && this could be used again
11764        * we have to point it back to where it 
11765        * belongs */
11766       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11767       if (AOP_SIZE(right) > 1
11768         && !OP_SYMBOL(result)->remat
11769         && ( OP_SYMBOL(result)->liveTo > ic->seq
11770         || ic->depth )) {
11771
11772           int size = AOP_SIZE(right) - 1;
11773
11774             while (size--)
11775               pic16_emitcode("decf","fsr0,f");
11776               //pic16_emitcode("dec","%s",rname);
11777       }
11778     }
11779
11780     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11781     /* done */
11782 //release:
11783     pic16_freeAsmop(right,NULL,ic,TRUE);
11784     pic16_freeAsmop(result,NULL,ic,TRUE);
11785 }
11786
11787 /*-----------------------------------------------------------------*/
11788 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11789 /*-----------------------------------------------------------------*/
11790 static void genPagedPointerSet (operand *right,
11791                                operand *result, 
11792                                iCode *ic)
11793 {
11794     asmop *aop = NULL;
11795     regs *preg = NULL ;
11796     char *rname , *l;
11797     sym_link *retype;
11798        
11799     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11800
11801     retype= getSpec(operandType(right));
11802     
11803     pic16_aopOp(result,ic,FALSE);
11804     
11805     /* if the value is already in a pointer register
11806        then don't need anything more */
11807     if (!AOP_INPREG(AOP(result))) {
11808         /* otherwise get a free pointer register */
11809         aop = newAsmop(0);
11810         preg = getFreePtr(ic,&aop,FALSE);
11811         pic16_emitcode("mov","%s,%s",
11812                 preg->name,
11813                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11814         rname = preg->name ;
11815     } else
11816         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11817     
11818     pic16_freeAsmop(result,NULL,ic,TRUE);
11819     pic16_aopOp (right,ic,FALSE);
11820
11821     /* if bitfield then unpack the bits */
11822     if (IS_BITFIELD(retype)) 
11823         genPackBits (retype,result,right,rname,PPOINTER);
11824     else {
11825         /* we have can just get the values */
11826         int size = AOP_SIZE(right);
11827         int offset = 0 ;        
11828         
11829         while (size--) {
11830             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11831             
11832             MOVA(l);
11833             pic16_emitcode("movx","@%s,a",rname);
11834
11835             if (size)
11836                 pic16_emitcode("inc","%s",rname);
11837
11838             offset++;
11839         }
11840     }
11841     
11842     /* now some housekeeping stuff */
11843     if (aop) {
11844         /* we had to allocate for this iCode */
11845         pic16_freeAsmop(NULL,aop,ic,TRUE);
11846     } else { 
11847         /* we did not allocate which means left
11848            already in a pointer register, then
11849            if size > 0 && this could be used again
11850            we have to point it back to where it 
11851            belongs */
11852         if (AOP_SIZE(right) > 1 &&
11853             !OP_SYMBOL(result)->remat &&
11854             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11855               ic->depth )) {
11856             int size = AOP_SIZE(right) - 1;
11857             while (size--)
11858                 pic16_emitcode("dec","%s",rname);
11859         }
11860     }
11861
11862     /* done */
11863     pic16_freeAsmop(right,NULL,ic,TRUE);
11864     
11865         
11866 }
11867
11868 #if 0
11869 /* This code is not adjusted to PIC16 and fails utterly...
11870  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11871
11872 /*-----------------------------------------------------------------*/
11873 /* genFarPointerSet - set value from far space                     */
11874 /*-----------------------------------------------------------------*/
11875 static void genFarPointerSet (operand *right,
11876                               operand *result, iCode *ic)
11877 {
11878     int size, offset ;
11879     sym_link *retype = getSpec(operandType(right));
11880
11881     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11882     pic16_aopOp(result,ic,FALSE);
11883
11884     /* if the operand is already in dptr 
11885     then we do nothing else we move the value to dptr */
11886     if (AOP_TYPE(result) != AOP_STR) {
11887         /* if this is remateriazable */
11888         if (AOP_TYPE(result) == AOP_IMMD)
11889             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11890         else { /* we need to get it byte by byte */
11891             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11892             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11893             if (options.model == MODEL_FLAT24)
11894             {
11895                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11896             }
11897         }
11898     }
11899     /* so dptr know contains the address */
11900     pic16_freeAsmop(result,NULL,ic,TRUE);
11901     pic16_aopOp(right,ic,FALSE);
11902
11903     /* if bit then unpack */
11904     if (IS_BITFIELD(retype)) 
11905         genPackBits(retype,result,right,"dptr",FPOINTER);
11906     else {
11907         size = AOP_SIZE(right);
11908         offset = 0 ;
11909
11910         while (size--) {
11911             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11912             MOVA(l);
11913             pic16_emitcode("movx","@dptr,a");
11914             if (size)
11915                 pic16_emitcode("inc","dptr");
11916         }
11917     }
11918
11919     pic16_freeAsmop(right,NULL,ic,TRUE);
11920 }
11921 #endif
11922
11923 /*-----------------------------------------------------------------*/
11924 /* genGenPointerSet - set value from generic pointer space         */
11925 /*-----------------------------------------------------------------*/
11926 #if 0
11927 static void genGenPointerSet (operand *right,
11928                               operand *result, iCode *ic)
11929 {
11930         int i, size, offset, lit;
11931         sym_link *retype = getSpec(operandType(right));
11932
11933         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11934
11935         pic16_aopOp(result,ic,FALSE);
11936         pic16_aopOp(right,ic,FALSE);
11937         size = AOP_SIZE(right);
11938         offset = 0;
11939
11940         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11941
11942         /* if the operand is already in dptr 
11943                 then we do nothing else we move the value to dptr */
11944         if (AOP_TYPE(result) != AOP_STR) {
11945                 /* if this is remateriazable */
11946                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11947                 // WARNING: anythig until "else" is untested!
11948                 if (AOP_TYPE(result) == AOP_IMMD) {
11949                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11950                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11951                         // load FSR0 from immediate
11952                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11953                         offset = 0;
11954                         while(size--) {
11955                                 if(size) {
11956                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11957                                 } else {
11958                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11959                                 }
11960                                 offset++;
11961                         }
11962                         goto release;
11963                 }
11964                 else { /* we need to get it byte by byte */
11965                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11966                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11967
11968                         // set up FSR0 with address of result
11969                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11970                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11971
11972                         /* hack hack! see if this the FSR. If so don't load W */
11973                         if(AOP_TYPE(right) != AOP_ACC) {
11974
11975                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11976
11977                                 if(AOP_TYPE(right) == AOP_LIT)
11978                                 {
11979                                         // copy literal
11980                                         // note: pic16_popGet handles sign extension
11981                                         for(i=0;i<size;i++) {
11982                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11983                                                 if(i < size-1)
11984                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11985                                                 else
11986                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11987                                         }
11988                                 } else {
11989                                         // copy regs
11990
11991                                         for(i=0;i<size;i++) {
11992                                                 if(i < size-1)
11993                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11994                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11995                                                 else
11996                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11997                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11998                                         }
11999                                 }
12000                                 goto release;
12001                         } 
12002                         // right = ACC
12003                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12004                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12005                         goto release;
12006         } // if (AOP_TYPE(result) != AOP_IMMD)
12007
12008         } // if (AOP_TYPE(result) != AOP_STR)
12009         /* so dptr know contains the address */
12010
12011
12012         /* if bit then unpack */
12013         if (IS_BITFIELD(retype)) 
12014                 genPackBits(retype,result,right,"dptr",GPOINTER);
12015         else {
12016                 size = AOP_SIZE(right);
12017                 offset = 0 ;
12018
12019                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12020
12021                 // set up FSR0 with address of result
12022                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12023                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12024         
12025                 while (size--) {
12026                         if (AOP_TYPE(right) == AOP_LIT) {
12027                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12028                                 if (size) {
12029                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12030                                 } else {
12031                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12032                                 }
12033                         } else { // no literal
12034                                 if(size) {
12035                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12036                                 } else {
12037                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12038                                 }
12039                         }
12040                         offset++;
12041                 }
12042         }
12043
12044         release:
12045         pic16_freeAsmop(right,NULL,ic,TRUE);
12046         pic16_freeAsmop(result,NULL,ic,TRUE);
12047 }
12048 #endif
12049
12050 static void genGenPointerSet (operand *right,
12051                               operand *result, iCode *ic)
12052 {
12053   int size;
12054   sym_link *retype = getSpec(operandType(result));
12055
12056     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12057
12058     pic16_aopOp(result,ic,FALSE);
12059     pic16_aopOp(right,ic,FALSE);
12060     size = AOP_SIZE(right);
12061
12062     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12063
12064
12065     /* if bit then unpack */
12066     if (IS_BITFIELD(retype)) {
12067 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12068       genPackBits(retype,result,right,"dptr",GPOINTER);
12069       goto release;
12070     }
12071
12072     size = AOP_SIZE(right);
12073
12074     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12075
12076
12077     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12078
12079     /* value of right+0 is placed on stack, which will be retrieved
12080      * by the support function thus restoring the stack. The important
12081      * thing is that there is no need to manually restore stack pointer
12082      * here */
12083     pushaop(AOP(right), 0);
12084 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12085     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12086     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12087     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12088     
12089     /* load address to write to in WREG:FSR0H:FSR0L */
12090     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12091                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12092     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12093                                 pic16_popCopyReg(&pic16_pc_prodl)));
12094     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12095     
12096     pic16_callGenericPointerRW(1, size);
12097
12098 release:
12099     pic16_freeAsmop(right,NULL,ic,TRUE);
12100     pic16_freeAsmop(result,NULL,ic,TRUE);
12101 }
12102
12103 /*-----------------------------------------------------------------*/
12104 /* genPointerSet - stores the value into a pointer location        */
12105 /*-----------------------------------------------------------------*/
12106 static void genPointerSet (iCode *ic)
12107 {    
12108   operand *right, *result ;
12109   sym_link *type, *etype;
12110   int p_type;
12111
12112     FENTRY;
12113
12114     right = IC_RIGHT(ic);
12115     result = IC_RESULT(ic) ;
12116
12117     /* depending on the type of pointer we need to
12118     move it to the correct pointer register */
12119     type = operandType(result);
12120     etype = getSpec(type);
12121     
12122     /* if left is of type of pointer then it is simple */
12123     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12124         p_type = DCL_TYPE(type);
12125     }
12126     else {
12127         /* we have to go by the storage class */
12128         p_type = PTR_TYPE(SPEC_OCLS(etype));
12129
12130 /*      if (SPEC_OCLS(etype)->codesp ) { */
12131 /*          p_type = CPOINTER ;  */
12132 /*      } */
12133 /*      else */
12134 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12135 /*              p_type = FPOINTER ; */
12136 /*          else */
12137 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12138 /*                  p_type = PPOINTER ; */
12139 /*              else */
12140 /*                  if (SPEC_OCLS(etype) == idata ) */
12141 /*                      p_type = IPOINTER ; */
12142 /*                  else */
12143 /*                      p_type = POINTER ; */
12144     }
12145
12146     /* now that we have the pointer type we assign
12147     the pointer values */
12148     switch (p_type) {
12149       case POINTER:
12150       case FPOINTER:
12151       case IPOINTER:
12152         genNearPointerSet (right,result,ic);
12153         break;
12154
12155       case PPOINTER:
12156         genPagedPointerSet (right,result,ic);
12157         break;
12158
12159 #if 0
12160       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12161       case FPOINTER:
12162         genFarPointerSet (right,result,ic);
12163         break;
12164 #endif
12165         
12166       case GPOINTER:
12167         genGenPointerSet (right,result,ic);
12168         break;
12169
12170       default:
12171         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12172           "genPointerSet: illegal pointer type");
12173     }
12174 }
12175
12176 /*-----------------------------------------------------------------*/
12177 /* genIfx - generate code for Ifx statement                        */
12178 /*-----------------------------------------------------------------*/
12179 static void genIfx (iCode *ic, iCode *popIc)
12180 {
12181   operand *cond = IC_COND(ic);
12182   int isbit =0;
12183
12184     FENTRY;
12185
12186     pic16_aopOp(cond,ic,FALSE);
12187
12188     /* get the value into acc */
12189     if (AOP_TYPE(cond) != AOP_CRY)
12190       pic16_toBoolean(cond);
12191     else
12192       isbit = 1;
12193     /* the result is now in the accumulator */
12194     pic16_freeAsmop(cond,NULL,ic,TRUE);
12195
12196     /* if there was something to be popped then do it */
12197     if (popIc)
12198       genIpop(popIc);
12199
12200     /* if the condition is  a bit variable */
12201     if (isbit && IS_ITEMP(cond) && 
12202         SPIL_LOC(cond)) {
12203       genIfxJump(ic,"c");
12204       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12205     } else {
12206       if (isbit && !IS_ITEMP(cond))
12207         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12208         else
12209         genIfxJump(ic,"a");
12210     }
12211     ic->generated = 1;
12212 }
12213
12214 /*-----------------------------------------------------------------*/
12215 /* genAddrOf - generates code for address of                       */
12216 /*-----------------------------------------------------------------*/
12217 static void genAddrOf (iCode *ic)
12218 {
12219   operand *result, *left;
12220   int size;
12221   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12222   pCodeOp *pcop0, *pcop1, *pcop2;
12223
12224     FENTRY;
12225
12226     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12227
12228     sym = OP_SYMBOL( IC_LEFT(ic) );
12229     
12230     if(sym->onStack) {
12231       /* get address of symbol on stack */
12232       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12233 #if 0
12234       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12235                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12236 #endif
12237
12238       // operands on stack are accessible via "FSR2 + index" with index
12239       // starting at 2 for arguments and growing from 0 downwards for
12240       // local variables (index == 0 is not assigned so we add one here)
12241       {
12242         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12243
12244           if (soffs <= 0) {
12245             assert (soffs < 0);
12246             soffs++;
12247           } // if
12248
12249           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12250           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12251           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12252           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12253           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12254           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12255           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12256       }
12257
12258       goto release;
12259     }
12260         
12261 //      if(pic16_debug_verbose) {
12262 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12263 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12264 //      }
12265         
12266     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12267     size = AOP_SIZE(IC_RESULT(ic));
12268
12269     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12270     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12271     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12272         
12273     if (size == 3) {
12274       pic16_emitpcode(POC_MOVLW, pcop0);
12275       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12276       pic16_emitpcode(POC_MOVLW, pcop1);
12277       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12278       pic16_emitpcode(POC_MOVLW, pcop2);
12279       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12280     } else
12281     if (size == 2) {
12282       pic16_emitpcode(POC_MOVLW, pcop0);
12283       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12284       pic16_emitpcode(POC_MOVLW, pcop1);
12285     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12286     } else {
12287       pic16_emitpcode(POC_MOVLW, pcop0);
12288       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12289     }
12290
12291     pic16_freeAsmop(left, NULL, ic, FALSE);
12292 release:
12293     pic16_freeAsmop(result,NULL,ic,TRUE);
12294 }
12295
12296
12297 #if 0
12298 /*-----------------------------------------------------------------*/
12299 /* genFarFarAssign - assignment when both are in far space         */
12300 /*-----------------------------------------------------------------*/
12301 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12302 {
12303     int size = AOP_SIZE(right);
12304     int offset = 0;
12305     char *l ;
12306     /* first push the right side on to the stack */
12307     while (size--) {
12308         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12309         MOVA(l);
12310         pic16_emitcode ("push","acc");
12311     }
12312     
12313     pic16_freeAsmop(right,NULL,ic,FALSE);
12314     /* now assign DPTR to result */
12315     pic16_aopOp(result,ic,FALSE);
12316     size = AOP_SIZE(result);
12317     while (size--) {
12318         pic16_emitcode ("pop","acc");
12319         pic16_aopPut(AOP(result),"a",--offset);
12320     }
12321     pic16_freeAsmop(result,NULL,ic,FALSE);
12322         
12323 }
12324 #endif
12325
12326 /*-----------------------------------------------------------------*/
12327 /* genAssign - generate code for assignment                        */
12328 /*-----------------------------------------------------------------*/
12329 static void genAssign (iCode *ic)
12330 {
12331   operand *result, *right;
12332   sym_link *restype, *rtype;
12333   int size, offset,know_W;
12334   unsigned long lit = 0L;
12335
12336     result = IC_RESULT(ic);
12337     right  = IC_RIGHT(ic) ;
12338
12339     FENTRY;
12340   
12341     /* if they are the same */
12342     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12343       return ;
12344
12345     /* reversed order operands are aopOp'ed so that result operand
12346      * is effective in case right is a stack symbol. This maneauver
12347      * allows to use the _G.resDirect flag later */
12348      pic16_aopOp(result,ic,TRUE);
12349     pic16_aopOp(right,ic,FALSE);
12350
12351     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12352
12353     /* if they are the same registers */
12354     if (pic16_sameRegs(AOP(right),AOP(result)))
12355       goto release;
12356
12357     /* if the result is a bit */
12358     if (AOP_TYPE(result) == AOP_CRY) {
12359       /* if the right size is a literal then
12360          we know what the value is */
12361       if (AOP_TYPE(right) == AOP_LIT) {
12362           
12363         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12364             pic16_popGet(AOP(result),0));
12365
12366         if (((int) operandLitValue(right))) 
12367           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12368               AOP(result)->aopu.aop_dir,
12369               AOP(result)->aopu.aop_dir);
12370         else
12371           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12372               AOP(result)->aopu.aop_dir,
12373               AOP(result)->aopu.aop_dir);
12374         
12375         goto release;
12376       }
12377
12378       /* the right is also a bit variable */
12379       if (AOP_TYPE(right) == AOP_CRY) {
12380         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12381         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12382         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12383
12384         goto release ;
12385       }
12386
12387       /* we need to or */
12388       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12389       pic16_toBoolean(right);
12390       emitSKPZ;
12391       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12392       //pic16_aopPut(AOP(result),"a",0);
12393       goto release ;
12394     }
12395
12396     /* bit variables done */
12397     /* general case */
12398     size = AOP_SIZE(result);
12399     offset = 0 ;
12400
12401   /* bit variables done */
12402   /* general case */
12403   size = AOP_SIZE(result);
12404   restype = operandType(result);
12405   rtype = operandType(right);
12406   offset = 0 ;
12407
12408   if(AOP_TYPE(right) == AOP_LIT) {
12409     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12410     {
12411       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12412
12413       /* patch tag for literals that are cast to pointers */
12414       if (IS_CODEPTR(restype)) {
12415         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12416         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12417       } else {
12418         if (IS_GENPTR(restype))
12419         {
12420           if (IS_CODEPTR(rtype)) {
12421             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12422             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12423           } else if (PIC_IS_DATA_PTR(rtype)) {
12424             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12425             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12426           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12427             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12428           } else if (IS_PTR(rtype)) {
12429             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12430             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12431           }
12432         }
12433       }
12434     } else {
12435       union {
12436         unsigned long lit_int;
12437         float lit_float;
12438       } info;
12439
12440
12441       if(IS_FIXED16X16(operandType(right))) {
12442         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12443       } else {
12444         /* take care if literal is a float */
12445         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12446         lit = info.lit_int;
12447       }
12448     }
12449   }
12450
12451 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12452 //                      sizeof(unsigned long int), sizeof(float));
12453
12454
12455     if (AOP_TYPE(right) == AOP_REG) {
12456       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12457       while (size--) {
12458         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12459       } // while
12460       goto release;
12461     }
12462
12463     /* when do we have to read the program memory?
12464      * - if right itself is a symbol in code space
12465      *   (we don't care what it points to if it's a pointer)
12466      * - AND right is not a function (we would want its address)
12467      */
12468     if(AOP_TYPE(right) != AOP_LIT
12469       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12470       && !IS_FUNC(OP_SYM_TYPE(right))
12471       && !IS_ITEMP(right)) {
12472
12473       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12474       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12475       
12476       // set up table pointer
12477       if(is_LitOp(right)) {
12478 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12479         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12480         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12481         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12482         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12483         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12484         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12485       } else {
12486 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12487         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12488             pic16_popCopyReg(&pic16_pc_tblptrl)));
12489         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12490             pic16_popCopyReg(&pic16_pc_tblptrh)));
12491         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12492             pic16_popCopyReg(&pic16_pc_tblptru)));
12493       }
12494
12495       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12496       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12497       while(size--) {
12498         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12499         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12500             pic16_popGet(AOP(result),offset)));
12501         offset++;
12502       }
12503
12504       /* FIXME: for pointers we need to extend differently (according
12505        * to pointer type DATA/CODE/EEPROM/... :*/
12506       size = getSize(OP_SYM_TYPE(right));
12507       if(AOP_SIZE(result) > size) {
12508         size = AOP_SIZE(result) - size;
12509         while(size--) {
12510           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12511           offset++;
12512         }
12513       }
12514       goto release;
12515     }
12516
12517 #if 0
12518     /* VR - What is this?! */
12519     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12520       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12521       
12522       if(aopIdx(AOP(result),0) == 4) {
12523         /* this is a workaround to save value of right into wreg too,
12524          * value of wreg is going to be used later */
12525         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12526         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12527         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12528         goto release;
12529       } else
12530 //      assert(0);
12531       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12532     }
12533 #endif
12534
12535   know_W=-1;
12536   while (size--) {
12537     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12538     if(AOP_TYPE(right) == AOP_LIT) {
12539       if(lit&0xff) {
12540         if(know_W != (lit&0xff))
12541           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12542         know_W = lit&0xff;
12543         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12544       } else
12545         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12546
12547       lit >>= 8;
12548
12549     } else if (AOP_TYPE(right) == AOP_CRY) {
12550       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12551       if(offset == 0) {
12552         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12553         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12554         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12555       }
12556     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12557         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12558         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12559     } else {
12560       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12561
12562       if(!_G.resDirect) {                                               /* use this aopForSym feature */
12563           if(AOP_TYPE(result) == AOP_ACC) {
12564             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12565           } else
12566           if(AOP_TYPE(right) == AOP_ACC) {
12567             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12568           } else {
12569             pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12570           }
12571       }
12572     }
12573       
12574       offset++;
12575     }
12576   
12577 release:
12578   pic16_freeAsmop (right,NULL,ic,FALSE);
12579   pic16_freeAsmop (result,NULL,ic,TRUE);
12580
12581
12582 /*-----------------------------------------------------------------*/
12583 /* genJumpTab - generates code for jump table                       */
12584 /*-----------------------------------------------------------------*/
12585 static void genJumpTab (iCode *ic)
12586 {
12587   symbol *jtab;
12588   char *l;
12589   pCodeOp *jt_offs;
12590   pCodeOp *jt_offs_hi;
12591   pCodeOp *jt_label;
12592
12593     FENTRY;
12594
12595     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12596     /* get the condition into accumulator */
12597     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12598     MOVA(l);
12599     /* multiply by three */
12600     pic16_emitcode("add","a,acc");
12601     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12602
12603     jtab = newiTempLabel(NULL);
12604     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12605     pic16_emitcode("jmp","@a+dptr");
12606     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12607
12608 #if 0
12609     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12610     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12611     emitSKPNC;
12612     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12613     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12614     pic16_emitpLabel(jtab->key);
12615
12616 #else
12617
12618     jt_offs = pic16_popGetTempReg(0);
12619     jt_offs_hi = pic16_popGetTempReg(1);
12620     jt_label = pic16_popGetLabel (jtab->key);
12621     //fprintf (stderr, "Creating jump table...\n");
12622
12623     // calculate offset into jump table (idx * sizeof (GOTO))
12624     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12625     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12626     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12627     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12628     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12629     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12630     pic16_emitpcode(POC_MOVWF , jt_offs);
12631
12632     // prepare PCLATx (set to first entry in jump table)
12633     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12634     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12635     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12636     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12637     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12638
12639     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12640     pic16_emitpcode(POC_ADDWF , jt_offs);
12641     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12642     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12643     emitSKPNC;
12644     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12645
12646     // release temporaries and prepare jump into table (new PCL --> WREG)
12647     pic16_emitpcode(POC_MOVFW , jt_offs);
12648     pic16_popReleaseTempReg (jt_offs_hi, 1);
12649     pic16_popReleaseTempReg (jt_offs, 0);
12650
12651     // jump into the table
12652     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12653
12654     pic16_emitpLabelFORCE(jtab->key);
12655 #endif
12656
12657     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12658 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12659
12660     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12661     /* now generate the jump labels */
12662     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12663          jtab = setNextItem(IC_JTLABELS(ic))) {
12664 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12665         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12666         
12667     }
12668     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12669
12670 }
12671
12672 /*-----------------------------------------------------------------*/
12673 /* genMixedOperation - gen code for operators between mixed types  */
12674 /*-----------------------------------------------------------------*/
12675 /*
12676   TSD - Written for the PIC port - but this unfortunately is buggy.
12677   This routine is good in that it is able to efficiently promote 
12678   types to different (larger) sizes. Unfortunately, the temporary
12679   variables that are optimized out by this routine are sometimes
12680   used in other places. So until I know how to really parse the 
12681   iCode tree, I'm going to not be using this routine :(.
12682 */
12683 static int genMixedOperation (iCode *ic)
12684 {
12685 #if 0
12686   operand *result = IC_RESULT(ic);
12687   sym_link *ctype = operandType(IC_LEFT(ic));
12688   operand *right = IC_RIGHT(ic);
12689   int ret = 0;
12690   int big,small;
12691   int offset;
12692
12693   iCode *nextic;
12694   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12695
12696   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12697
12698   nextic = ic->next;
12699   if(!nextic)
12700     return 0;
12701
12702   nextright = IC_RIGHT(nextic);
12703   nextleft  = IC_LEFT(nextic);
12704   nextresult = IC_RESULT(nextic);
12705
12706   pic16_aopOp(right,ic,FALSE);
12707   pic16_aopOp(result,ic,FALSE);
12708   pic16_aopOp(nextright,  nextic, FALSE);
12709   pic16_aopOp(nextleft,   nextic, FALSE);
12710   pic16_aopOp(nextresult, nextic, FALSE);
12711
12712   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12713
12714     operand *t = right;
12715     right = nextright;
12716     nextright = t; 
12717
12718     pic16_emitcode(";remove right +","");
12719
12720   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12721 /*
12722     operand *t = right;
12723     right = nextleft;
12724     nextleft = t; 
12725 */
12726     pic16_emitcode(";remove left +","");
12727   } else
12728     return 0;
12729
12730   big = AOP_SIZE(nextleft);
12731   small = AOP_SIZE(nextright);
12732
12733   switch(nextic->op) {
12734
12735   case '+':
12736     pic16_emitcode(";optimize a +","");
12737     /* if unsigned or not an integral type */
12738     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12739       pic16_emitcode(";add a bit to something","");
12740     } else {
12741
12742       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12743
12744       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12745         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12746         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12747       } else
12748         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12749
12750       offset = 0;
12751       while(--big) {
12752
12753         offset++;
12754
12755         if(--small) {
12756           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12757             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12758             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12759           }
12760
12761           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12762           emitSKPNC;
12763           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12764                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12765                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12766           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12767           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12768
12769         } else {
12770           pic16_emitcode("rlf","known_zero,w");
12771
12772           /*
12773             if right is signed
12774               btfsc  right,7
12775                addlw ff
12776           */
12777           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12778             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12779             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12780           } else {
12781             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12782           }
12783         }
12784       }
12785       ret = 1;
12786     }
12787   }
12788   ret = 1;
12789
12790 release:
12791   pic16_freeAsmop(right,NULL,ic,TRUE);
12792   pic16_freeAsmop(result,NULL,ic,TRUE);
12793   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12794   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12795   if(ret)
12796     nextic->generated = 1;
12797
12798   return ret;
12799 #else
12800   return 0;
12801 #endif
12802 }
12803 /*-----------------------------------------------------------------*/
12804 /* genCast - gen code for casting                                  */
12805 /*-----------------------------------------------------------------*/
12806 static void genCast (iCode *ic)
12807 {
12808   operand *result = IC_RESULT(ic);
12809   sym_link *ctype = operandType(IC_LEFT(ic));
12810   sym_link *rtype = operandType(IC_RIGHT(ic));
12811   sym_link *restype = operandType(IC_RESULT(ic));
12812   operand *right = IC_RIGHT(ic);
12813   int size, offset ;
12814
12815
12816     FENTRY;
12817
12818         /* if they are equivalent then do nothing */
12819 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12820 //              return ;
12821
12822         pic16_aopOp(result,ic,FALSE);
12823         pic16_aopOp(right,ic,FALSE) ;
12824
12825         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12826
12827
12828         /* if the result is a bit */
12829         if (AOP_TYPE(result) == AOP_CRY) {
12830         
12831                 /* if the right size is a literal then
12832                  * we know what the value is */
12833                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12834
12835                 if (AOP_TYPE(right) == AOP_LIT) {
12836                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12837                                 pic16_popGet(AOP(result),0));
12838
12839                         if (((int) operandLitValue(right))) 
12840                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12841                                         AOP(result)->aopu.aop_dir,
12842                                         AOP(result)->aopu.aop_dir);
12843                         else
12844                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12845                                         AOP(result)->aopu.aop_dir,
12846                                         AOP(result)->aopu.aop_dir);
12847                         goto release;
12848                 }
12849
12850                 /* the right is also a bit variable */
12851                 if (AOP_TYPE(right) == AOP_CRY) {
12852                         emitCLRC;
12853                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12854
12855                         pic16_emitcode("clrc","");
12856                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12857                                 AOP(right)->aopu.aop_dir,
12858                                 AOP(right)->aopu.aop_dir);
12859                         pic16_aopPut(AOP(result),"c",0);
12860                         goto release ;
12861                 }
12862
12863                 /* we need to or */
12864                 if (AOP_TYPE(right) == AOP_REG) {
12865                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12866                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12867                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12868                 }
12869                 pic16_toBoolean(right);
12870                 pic16_aopPut(AOP(result),"a",0);
12871                 goto release ;
12872         }
12873
12874         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12875           int offset = 1;
12876
12877                 size = AOP_SIZE(result);
12878
12879                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12880
12881                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12882                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12883                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12884
12885                 while (size--)
12886                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12887
12888                 goto release;
12889         }
12890
12891         if(IS_BITFIELD(getSpec(restype))
12892           && IS_BITFIELD(getSpec(rtype))) {
12893           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12894         }
12895         
12896         /* port from pic14 to cope with generic pointers */
12897         if (PIC_IS_TAGGED(restype))
12898         {
12899           operand *result = IC_RESULT(ic);
12900           //operand *left = IC_LEFT(ic);
12901           operand *right = IC_RIGHT(ic);
12902           int tag = 0xff;
12903
12904           /* copy common part */
12905           int max, size = AOP_SIZE(result);
12906           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12907           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12908
12909           max = size;
12910           while (size--)
12911           {
12912             pic16_mov2w (AOP(right), size);
12913             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12914           } // while
12915
12916           /* upcast into generic pointer type? */
12917           if (IS_GENPTR(restype)
12918               && !PIC_IS_TAGGED(rtype)
12919               && (AOP_SIZE(result) > max))
12920           {
12921             /* determine appropriate tag for right */
12922             if (PIC_IS_DATA_PTR(rtype))
12923               tag = GPTR_TAG_DATA;
12924             else if (IS_CODEPTR(rtype))
12925               tag = GPTR_TAG_CODE;
12926             else if (PIC_IS_DATA_PTR(ctype)) {
12927               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12928               tag = GPTR_TAG_DATA;
12929             } else if (IS_CODEPTR(ctype)) {
12930               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12931               tag = GPTR_TAG_CODE;
12932             } else if (IS_PTR(rtype)) {
12933               PERFORM_ONCE(weirdcast,
12934               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12935               );
12936               tag = GPTR_TAG_DATA;
12937             } else {
12938               PERFORM_ONCE(weirdcast,
12939               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12940               );
12941               tag = GPTR_TAG_DATA;
12942             }
12943
12944             assert (AOP_SIZE(result) == 3);
12945             /* zero-extend address... */
12946             for (size = max; size < AOP_SIZE(result)-1; size++)
12947               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12948             /* ...and add tag */
12949             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12950           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12951             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12952             for (size = max; size < AOP_SIZE(result)-1; size++)
12953               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12954             /* add __code tag */
12955             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12956           } else if (AOP_SIZE(result) > max) {
12957             /* extend non-pointers */
12958             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12959             pic16_addSign(result, max, 0);
12960           } // if
12961           goto release;
12962         }
12963
12964         /* if they are the same size : or less */
12965         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12966
12967                 /* if they are in the same place */
12968                 if (pic16_sameRegs(AOP(right),AOP(result)))
12969                         goto release;
12970
12971                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12972 #if 0
12973                 if (IS_PTR_CONST(rtype))
12974 #else
12975                 if (IS_CODEPTR(rtype))
12976 #endif
12977                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12978
12979 #if 0
12980                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12981 #else
12982                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12983 #endif
12984                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12985
12986 #if 0
12987                 if(AOP_TYPE(right) == AOP_IMMD) {
12988                   pCodeOp *pcop0, *pcop1, *pcop2;
12989                   symbol *sym = OP_SYMBOL( right );
12990
12991                         size = AOP_SIZE(result);
12992                         /* low */
12993                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12994                         /* high */
12995                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12996                         /* upper */
12997                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12998         
12999                         if (size == 3) {
13000                                 pic16_emitpcode(POC_MOVLW, pcop0);
13001                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13002                                 pic16_emitpcode(POC_MOVLW, pcop1);
13003                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13004                                 pic16_emitpcode(POC_MOVLW, pcop2);
13005                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13006                         } else
13007                         if (size == 2) {
13008                                 pic16_emitpcode(POC_MOVLW, pcop0);
13009                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13010                                 pic16_emitpcode(POC_MOVLW, pcop1);
13011                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13012                         } else {
13013                                 pic16_emitpcode(POC_MOVLW, pcop0);
13014                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13015                         }
13016                 } else
13017 #endif
13018                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13019                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13020                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13021                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13022                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13023                         if(AOP_SIZE(result) <2)
13024                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13025                 } else {
13026                         /* if they in different places then copy */
13027                         size = AOP_SIZE(result);
13028                         offset = 0 ;
13029                         while (size--) {
13030                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13031                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13032                                 offset++;
13033                         }
13034                 }
13035                 goto release;
13036         }
13037
13038         /* if the result is of type pointer */
13039         if (IS_PTR(ctype)) {
13040           int p_type;
13041           sym_link *type = operandType(right);
13042           sym_link *etype = getSpec(type);
13043
13044                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13045
13046                 /* pointer to generic pointer */
13047                 if (IS_GENPTR(ctype)) {
13048                   char *l = zero;
13049             
13050                         if (IS_PTR(type)) 
13051                                 p_type = DCL_TYPE(type);
13052                         else {
13053                 /* we have to go by the storage class */
13054                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13055
13056 /*              if (SPEC_OCLS(etype)->codesp )  */
13057 /*                  p_type = CPOINTER ;  */
13058 /*              else */
13059 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13060 /*                      p_type = FPOINTER ; */
13061 /*                  else */
13062 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13063 /*                          p_type = PPOINTER; */
13064 /*                      else */
13065 /*                          if (SPEC_OCLS(etype) == idata ) */
13066 /*                              p_type = IPOINTER ; */
13067 /*                          else */
13068 /*                              p_type = POINTER ; */
13069             }
13070                 
13071             /* the first two bytes are known */
13072       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13073             size = GPTRSIZE - 1; 
13074             offset = 0 ;
13075             while (size--) {
13076               if(offset < AOP_SIZE(right)) {
13077                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13078                 pic16_mov2f(AOP(result), AOP(right), offset);
13079 /*
13080                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13081                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13082                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13083                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13084                 } else { 
13085                   
13086                   pic16_aopPut(AOP(result),
13087                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13088                          offset);
13089                 }
13090 */
13091               } else 
13092                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13093               offset++;
13094             }
13095             /* the last byte depending on type */
13096             switch (p_type) {
13097             case IPOINTER:
13098             case POINTER:
13099             case FPOINTER:
13100                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13101                 break;
13102
13103             case CPOINTER:
13104                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13105                 break;
13106
13107             case PPOINTER:
13108               pic16_emitcode(";BUG!? ","%d",__LINE__);
13109                 l = "#0x03";
13110                 break;
13111
13112             case GPOINTER:
13113                 if (GPTRSIZE > AOP_SIZE(right)) {
13114                   // assume __data pointer... THIS MIGHT BE WRONG!
13115                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13116                 } else {
13117                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13118                 }
13119               break;
13120               
13121             default:
13122                 /* this should never happen */
13123                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13124                        "got unknown pointer type");
13125                 exit(1);
13126             }
13127             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13128             goto release ;
13129         }
13130         
13131         
13132         assert( 0 );
13133         /* just copy the pointers */
13134         size = AOP_SIZE(result);
13135         offset = 0 ;
13136         while (size--) {
13137             pic16_aopPut(AOP(result),
13138                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13139                    offset);
13140             offset++;
13141         }
13142         goto release ;
13143     }
13144     
13145
13146
13147     /* so we now know that the size of destination is greater
13148     than the size of the source.
13149     Now, if the next iCode is an operator then we might be
13150     able to optimize the operation without performing a cast.
13151     */
13152     if(genMixedOperation(ic))
13153       goto release;
13154
13155     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13156     
13157     /* we move to result for the size of source */
13158     size = AOP_SIZE(right);
13159     offset = 0 ;
13160
13161     while (size--) {
13162       if(!_G.resDirect)
13163         pic16_mov2f(AOP(result), AOP(right), offset);
13164       offset++;
13165     }
13166
13167     /* now depending on the sign of the destination */
13168     size = AOP_SIZE(result) - AOP_SIZE(right);
13169     /* if unsigned or not an integral type */
13170     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13171       while (size--)
13172         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13173     } else {
13174       /* we need to extend the sign :( */
13175
13176       if(size == 1) {
13177         /* Save one instruction of casting char to int */
13178         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13179         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13180         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13181       } else {
13182         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13183
13184         if(offset)
13185           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13186         else
13187           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13188         
13189         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13190
13191         while (size--)
13192           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13193       }
13194     }
13195
13196 release:
13197     pic16_freeAsmop(right,NULL,ic,TRUE);
13198     pic16_freeAsmop(result,NULL,ic,TRUE);
13199
13200 }
13201
13202 /*-----------------------------------------------------------------*/
13203 /* genDjnz - generate decrement & jump if not zero instrucion      */
13204 /*-----------------------------------------------------------------*/
13205 static int genDjnz (iCode *ic, iCode *ifx)
13206 {
13207     symbol *lbl, *lbl1;
13208     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13209
13210     if (!ifx)
13211         return 0;
13212     
13213     /* if the if condition has a false label
13214        then we cannot save */
13215     if (IC_FALSE(ifx))
13216         return 0;
13217
13218     /* if the minus is not of the form 
13219        a = a - 1 */
13220     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13221         !IS_OP_LITERAL(IC_RIGHT(ic)))
13222         return 0;
13223
13224     if (operandLitValue(IC_RIGHT(ic)) != 1)
13225         return 0;
13226
13227     /* if the size of this greater than one then no
13228        saving */
13229     if (getSize(operandType(IC_RESULT(ic))) > 1)
13230         return 0;
13231
13232     /* otherwise we can save BIG */
13233     lbl = newiTempLabel(NULL);
13234     lbl1= newiTempLabel(NULL);
13235
13236     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13237     
13238     if (IS_AOP_PREG(IC_RESULT(ic))) {
13239         pic16_emitcode("dec","%s",
13240                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13241         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13242         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13243     } else {    
13244
13245
13246       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13247       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13248
13249       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13250       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13251
13252     }
13253     
13254     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13255     ifx->generated = 1;
13256     return 1;
13257 }
13258
13259 /*-----------------------------------------------------------------*/
13260 /* genReceive - generate code for a receive iCode                  */
13261 /*-----------------------------------------------------------------*/
13262 static void genReceive (iCode *ic)
13263 {    
13264
13265   FENTRY;
13266
13267 #if 0
13268   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13269         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13270 #endif
13271 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13272
13273   if (isOperandInFarSpace(IC_RESULT(ic))
13274       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13275           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13276
13277     int size = getSize(operandType(IC_RESULT(ic)));
13278     int offset =  pic16_fReturnSizePic - size;
13279
13280       assert( 0 );
13281       while (size--) {
13282         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13283                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13284                       offset++;
13285         }
13286
13287       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13288
13289       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13290       size = AOP_SIZE(IC_RESULT(ic));
13291       offset = 0;
13292       while (size--) {
13293         pic16_emitcode ("pop","acc");
13294         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13295       }
13296   } else {
13297     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13298     _G.accInUse++;
13299     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13300     _G.accInUse--;
13301
13302     /* set pseudo stack pointer to where it should be - dw*/
13303     GpsuedoStkPtr = ic->parmBytes;
13304
13305     /* setting GpsuedoStkPtr has side effects here: */
13306     assignResultValue(IC_RESULT(ic), 0);
13307   }
13308
13309   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13310 }
13311
13312 /*-----------------------------------------------------------------*/
13313 /* genDummyRead - generate code for dummy read of volatiles        */
13314 /*-----------------------------------------------------------------*/
13315 static void
13316 genDummyRead (iCode * ic)
13317 {
13318   operand *op;
13319   int i;
13320
13321   op = IC_RIGHT(ic);
13322   if (op && IS_SYMOP(op)) {
13323     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13324       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13325       return;
13326     }
13327     pic16_aopOp (op, ic, FALSE);
13328     for (i=0; i < AOP_SIZE(op); i++) {
13329       // may need to protect this from the peepholer -- this is not nice but works...
13330       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13331       pic16_mov2w (AOP(op),i);
13332       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13333     } // for i
13334     pic16_freeAsmop (op, NULL, ic, TRUE);
13335   } else if (op) {
13336     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13337   } // if
13338 }
13339
13340 /*-----------------------------------------------------------------*/
13341 /* genpic16Code - generate code for pic16 based controllers        */
13342 /*-----------------------------------------------------------------*/
13343 /*
13344  * At this point, ralloc.c has gone through the iCode and attempted
13345  * to optimize in a way suitable for a PIC. Now we've got to generate
13346  * PIC instructions that correspond to the iCode.
13347  *
13348  * Once the instructions are generated, we'll pass through both the
13349  * peep hole optimizer and the pCode optimizer.
13350  *-----------------------------------------------------------------*/
13351
13352 void genpic16Code (iCode *lic)
13353 {
13354   iCode *ic;
13355   int cln = 0;
13356
13357     lineHead = lineCurr = NULL;
13358
13359     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13360     pic16_addpBlock(pb);
13361
13362 #if 0
13363     /* if debug information required */
13364     if (options.debug && currFunc) {
13365       if (currFunc) {
13366         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13367       }
13368     }
13369 #endif
13370
13371     for (ic = lic ; ic ; ic = ic->next ) {
13372
13373       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13374       if ( cln != ic->lineno ) {
13375         if ( options.debug ) {
13376           debugFile->writeCLine (ic);
13377         }
13378         
13379         if(!options.noCcodeInAsm) {
13380           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13381               printCLine(ic->filename, ic->lineno)));
13382         }
13383
13384         cln = ic->lineno ;
13385       }
13386         
13387       if(options.iCodeInAsm) {
13388         char *l;
13389
13390           /* insert here code to print iCode as comment */
13391           l = Safe_strdup(printILine(ic));
13392           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13393       }
13394
13395       /* if the result is marked as
13396        * spilt and rematerializable or code for
13397        * this has already been generated then
13398        * do nothing */
13399       if (resultRemat(ic) || ic->generated ) 
13400         continue ;
13401         
13402       /* depending on the operation */
13403       switch (ic->op) {
13404         case '!' :
13405           pic16_genNot(ic);
13406           break;
13407             
13408         case '~' :
13409           pic16_genCpl(ic);
13410           break;
13411             
13412         case UNARYMINUS:
13413           genUminus (ic);
13414           break;
13415             
13416         case IPUSH:
13417           genIpush (ic);
13418           break;
13419             
13420         case IPOP:
13421           /* IPOP happens only when trying to restore a 
13422            * spilt live range, if there is an ifx statement
13423            * following this pop then the if statement might
13424            * be using some of the registers being popped which
13425            * would destroy the contents of the register so
13426            * we need to check for this condition and handle it */
13427            if (ic->next
13428              && ic->next->op == IFX
13429              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13430                genIfx (ic->next,ic);
13431           else
13432             genIpop (ic);
13433           break; 
13434             
13435         case CALL:
13436           genCall (ic);
13437           break;
13438             
13439         case PCALL:
13440           genPcall (ic);
13441           break;
13442             
13443         case FUNCTION:
13444           genFunction (ic);
13445           break;
13446             
13447         case ENDFUNCTION:
13448           genEndFunction (ic);
13449           break;
13450             
13451         case RETURN:
13452           genRet (ic);
13453           break;
13454             
13455         case LABEL:
13456           genLabel (ic);
13457           break;
13458             
13459         case GOTO:
13460           genGoto (ic);
13461           break;
13462             
13463         case '+' :
13464           pic16_genPlus (ic) ;
13465           break;
13466             
13467         case '-' :
13468           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13469             pic16_genMinus (ic);
13470           break;
13471
13472         case '*' :
13473           genMult (ic);
13474           break;
13475             
13476         case '/' :
13477           genDiv (ic) ;
13478           break;
13479             
13480         case '%' :
13481           genMod (ic);
13482           break;
13483             
13484         case '>' :
13485           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13486           break;
13487             
13488         case '<' :
13489           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13490           break;
13491             
13492         case LE_OP:
13493         case GE_OP:
13494         case NE_OP:
13495           /* note these two are xlated by algebraic equivalence
13496            * during parsing SDCC.y */
13497           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13498             "got '>=' or '<=' shouldn't have come here");
13499           break;
13500
13501         case EQ_OP:
13502           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13503           break;            
13504             
13505         case AND_OP:
13506           genAndOp (ic);
13507           break;
13508             
13509         case OR_OP:
13510           genOrOp (ic);
13511           break;
13512             
13513         case '^' :
13514           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13515           break;
13516             
13517         case '|' :
13518           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13519           break;
13520             
13521         case BITWISEAND:
13522           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13523           break;
13524             
13525         case INLINEASM:
13526           genInline (ic);
13527           break;
13528             
13529         case RRC:
13530           genRRC (ic);
13531           break;
13532             
13533         case RLC:
13534           genRLC (ic);
13535           break;
13536             
13537         case GETHBIT:
13538           genGetHbit (ic);
13539           break;
13540             
13541         case LEFT_OP:
13542           genLeftShift (ic);
13543           break;
13544             
13545         case RIGHT_OP:
13546           genRightShift (ic);
13547           break;
13548             
13549         case GET_VALUE_AT_ADDRESS:
13550           genPointerGet(ic);
13551           break;
13552             
13553         case '=' :
13554           if (POINTER_SET(ic))
13555             genPointerSet(ic);
13556           else
13557             genAssign(ic);
13558           break;
13559             
13560         case IFX:
13561           genIfx (ic,NULL);
13562           break;
13563             
13564         case ADDRESS_OF:
13565           genAddrOf (ic);
13566           break;
13567             
13568         case JUMPTABLE:
13569           genJumpTab (ic);
13570           break;
13571             
13572         case CAST:
13573           genCast (ic);
13574           break;
13575             
13576         case RECEIVE:
13577           genReceive(ic);
13578           break;
13579             
13580         case SEND:
13581           addSet(&_G.sendSet,ic);
13582           break;
13583
13584         case DUMMY_READ_VOLATILE:
13585           genDummyRead (ic);
13586           break;
13587
13588         default :
13589           ic = ic;
13590       }
13591     }
13592
13593
13594     /* now we are ready to call the
13595        peep hole optimizer */
13596     if (!options.nopeep)
13597       peepHole (&lineHead);
13598
13599     /* now do the actual printing */
13600     printLine (lineHead, codeOutFile);
13601
13602 #ifdef PCODE_DEBUG
13603     DFPRINTF((stderr,"printing pBlock\n\n"));
13604     pic16_printpBlock(stdout,pb);
13605 #endif
13606
13607     return;
13608 }
13609