* src/pic16/{pcode.h,genarith.c}:
[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         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1292         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1293             /* Don't reuse the new aop */
1294             sym->usl.spillLoc->aop = NULL;
1295         }
1296         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1297         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1298           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1299                                                   getSize(sym->type), 
1300                                                   sym->usl.spillLoc->offset, op);
1301         } else {
1302           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1303           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1304           assert (getSize(sym->type) <= 1);
1305           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1306         }
1307         aop->size = getSize(sym->type);
1308
1309         return;
1310     }
1311
1312     {
1313       sym_link *type = operandType(op);
1314 #if 0
1315       if(IS_PTR_CONST(type)) 
1316 #else
1317       if(IS_CODEPTR(type)) 
1318 #endif
1319         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1320     }
1321
1322     /* must be in a register */
1323     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1324     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1325     aop->size = sym->nRegs;
1326     for ( i = 0 ; i < sym->nRegs ;i++)
1327         aop->aopu.aop_reg[i] = sym->regs[i];
1328 }
1329
1330 /*-----------------------------------------------------------------*/
1331 /* pic16_freeAsmop - free up the asmop given to an operand               */
1332 /*----------------------------------------------------------------*/
1333 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1334 {   
1335     asmop *aop ;
1336
1337     if (!op)
1338         aop = aaop;
1339     else 
1340         aop = op->aop;
1341
1342     if (!aop)
1343         return ;
1344
1345     if (aop->freed)
1346         goto dealloc; 
1347
1348     aop->freed = 1;
1349
1350     /* depending on the asmop type only three cases need work AOP_RO
1351        , AOP_R1 && AOP_STK */
1352 #if 1
1353     switch (aop->type) {
1354         case AOP_FSR0 :
1355             if (_G.fsr0Pushed ) {
1356                 if (pop) {
1357                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1358                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1359 //                    pic16_emitcode ("pop","ar0");
1360                     _G.fsr0Pushed--;
1361                 }
1362             }
1363             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1364             break;
1365
1366         case AOP_FSR2 :
1367             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1368             break;
1369
1370         case AOP_R0 :
1371             if (_G.r0Pushed ) {
1372                 if (pop) {
1373                     pic16_emitcode ("pop","ar0");     
1374                     _G.r0Pushed--;
1375                 }
1376             }
1377             bitVectUnSetBit(ic->rUsed,R0_IDX);
1378             break;
1379
1380         case AOP_R1 :
1381             if (_G.r1Pushed ) {
1382                 if (pop) {
1383                     pic16_emitcode ("pop","ar1");
1384                     _G.r1Pushed--;
1385                 }
1386             }
1387             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1388             break;
1389
1390         case AOP_STA:
1391           {
1392             int i;
1393
1394               /* we must store the result on stack */
1395               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1396                 // operands on stack are accessible via "FSR2 + index" with index
1397                 // starting at 2 for arguments and growing from 0 downwards for
1398                 // local variables (index == 0 is not assigned so we add one here)
1399                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1400                 if (soffs <= 0) {
1401                   assert (soffs < 0);
1402                   soffs++;
1403                 } // if
1404                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1405                 for(i=0;i<aop->size;i++) {
1406                   /* initialise for stack access via frame pointer */
1407                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1408                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1409                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1410                 }
1411         
1412                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1413               }
1414
1415               if(!_G.resDirect) {
1416                 for(i=0;i<aop->size;i++) {
1417                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1418
1419                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1420                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1421 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1422                   }
1423                 }
1424                 
1425                 {
1426                   regs *sr;
1427                   
1428                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1429                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1430                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1431                       deleteSetItem( &_G.sregsAllocSet, sr );
1432                     }
1433                 }
1434               }
1435               _G.resDirect = 0;
1436           }
1437           break;
1438 #if 0
1439         case AOP_STK :
1440         {
1441             int sz = aop->size;    
1442             int stk = aop->aopu.aop_stk + aop->size;
1443             bitVectUnSetBit(ic->rUsed,R0_IDX);
1444             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1445
1446             getFreePtr(ic,&aop,FALSE);
1447             
1448             if (options.stack10bit)
1449             {
1450                 /* I'm not sure what to do here yet... */
1451                 /* #STUB */
1452                 fprintf(stderr, 
1453                         "*** Warning: probably generating bad code for "
1454                         "10 bit stack mode.\n");
1455             }
1456             
1457             if (stk) {
1458                 pic16_emitcode ("mov","a,_bp");
1459                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1460                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1461             } else {
1462                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1463             }
1464
1465             while (sz--) {
1466                 pic16_emitcode("pop","acc");
1467                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1468                 if (!sz) break;
1469                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1470             }
1471             op->aop = aop;
1472             pic16_freeAsmop(op,NULL,ic,TRUE);
1473             if (_G.r0Pushed) {
1474                 pic16_emitcode("pop","ar0");
1475                 _G.r0Pushed--;
1476             }
1477
1478             if (_G.r1Pushed) {
1479                 pic16_emitcode("pop","ar1");
1480                 _G.r1Pushed--;
1481             }       
1482         }
1483 #endif
1484
1485     }
1486 #endif
1487
1488 dealloc:
1489     /* all other cases just dealloc */
1490     if (op ) {
1491         op->aop = NULL;
1492         if (IS_SYMOP(op)) {
1493             OP_SYMBOL(op)->aop = NULL;    
1494             /* if the symbol has a spill */
1495             if (SPIL_LOC(op))
1496                 SPIL_LOC(op)->aop = NULL;
1497         }
1498     }
1499 }
1500
1501 /*-----------------------------------------------------------------*/
1502 /* pic16_aopGet - for fetching value of the aop                          */
1503 /*-----------------------------------------------------------------*/
1504 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1505 {
1506     char *s = buffer ;
1507     char *rs;
1508
1509     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1510
1511     /* offset is greater than size then zero */
1512     if (offset > (aop->size - 1) &&
1513         aop->type != AOP_LIT)
1514         return zero;
1515
1516     /* depending on type */
1517     switch (aop->type) {
1518
1519     case AOP_FSR0:
1520     case AOP_FSR2:
1521       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1522       rs = Safe_calloc(1, strlen(s)+1);
1523       strcpy(rs, s);
1524       return (rs);
1525       
1526 #if 0
1527       /* if we need to increment it */
1528       while (offset > aop->coff)
1529         {
1530           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1531           aop->coff++;
1532         }
1533
1534       while (offset < aop->coff)
1535         {
1536           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1537           aop->coff--;
1538         }
1539       aop->coff = offset;
1540       if (aop->paged)
1541         {
1542           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1543           return (dname ? "acc" : "a");
1544         }
1545       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1546       rs = Safe_calloc (1, strlen (s) + 1);
1547       strcpy (rs, s);
1548       return rs;
1549 #endif
1550
1551         
1552     case AOP_IMMD:
1553         if (bit16) 
1554             sprintf (s,"%s",aop->aopu.aop_immd);
1555         else
1556             if (offset) 
1557                 sprintf(s,"(%s >> %d)",
1558                         aop->aopu.aop_immd,
1559                         offset*8);
1560             else
1561                 sprintf(s,"%s",
1562                         aop->aopu.aop_immd);
1563         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1564         rs = Safe_calloc(1,strlen(s)+1);
1565         strcpy(rs,s);   
1566         return rs;
1567         
1568     case AOP_DIR:
1569       if (offset) {
1570         sprintf(s,"(%s + %d)",
1571                 aop->aopu.aop_dir,
1572                 offset);
1573         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1574       } else
1575             sprintf(s,"%s",aop->aopu.aop_dir);
1576         rs = Safe_calloc(1,strlen(s)+1);
1577         strcpy(rs,s);   
1578         return rs;
1579         
1580     case AOP_REG:
1581       return aop->aopu.aop_reg[offset]->name;
1582         
1583     case AOP_CRY:
1584       return aop->aopu.aop_dir;
1585         
1586     case AOP_ACC:
1587         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1588 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1589 //        assert( 0 );
1590 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1591         rs = Safe_strdup("WREG");
1592         return (rs);
1593
1594     case AOP_LIT:
1595         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1596         rs = Safe_calloc(1,strlen(s)+1);
1597         strcpy(rs,s);   
1598         return rs;
1599         
1600     case AOP_STR:
1601         aop->coff = offset ;
1602
1603 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1604 //          dname)
1605 //          return "acc";
1606         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1607           aop->type = AOP_ACC;
1608           return Safe_strdup("_WREG");
1609         }
1610         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1611         
1612         return aop->aopu.aop_str[offset];
1613         
1614     case AOP_PCODE:
1615       {
1616         pCodeOp *pcop = aop->aopu.pcop;
1617         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1618         if(pcop->name) {
1619           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1620           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1621           if (offset) {
1622             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1623           } else {
1624             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1625           }
1626         } else
1627           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1628
1629       }
1630       rs = Safe_calloc(1,strlen(s)+1);
1631       strcpy(rs,s);   
1632       return rs;
1633
1634 #if 0
1635     case AOP_PAGED:
1636       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1637       if (offset) {
1638         sprintf(s,"(%s + %d)",
1639                 aop->aopu.aop_dir,
1640                 offset);
1641       } else
1642             sprintf(s,"%s",aop->aopu.aop_dir);
1643       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1644       rs = Safe_calloc(1,strlen(s)+1);
1645       strcpy(rs,s);   
1646       return rs;
1647 #endif
1648
1649     case AOP_STA:
1650         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1651         return (rs);
1652         
1653     case AOP_STK:
1654 //        pCodeOp *pcop = aop->aop
1655         break;
1656
1657     }
1658
1659     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1660     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1661            "aopget got unsupported aop->type");
1662     exit(0);
1663 }
1664
1665
1666
1667 /* lock has the following meaning: When allocating temporary registers
1668  * for stack variables storage, the value of the temporary register is
1669  * saved on stack. Its value is restored at the end. This procedure is
1670  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1671  * a possibility that before a call to pic16_aopOp, a temporary register
1672  * is allocated for a while and it is freed after some time, this will
1673  * mess the stack and values will not be restored properly. So use lock=1
1674  * to allocate temporary registers used internally by the programmer, and
1675  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1676  * to inform the compiler developer about a possible bug. This is an internal
1677  * feature for developing the compiler -- VR */
1678  
1679 int _TempReg_lock = 0;
1680 /*-----------------------------------------------------------------*/
1681 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1682 /*-----------------------------------------------------------------*/
1683 pCodeOp *pic16_popGetTempReg(int lock)
1684 {
1685   pCodeOp *pcop=NULL;
1686   symbol *cfunc;
1687
1688 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1689     if(_TempReg_lock) {
1690 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1691     }
1692     
1693     _TempReg_lock += lock;
1694     
1695     cfunc = currFunc;
1696     currFunc = NULL;
1697
1698 #if 0
1699         {
1700           regs *rr;
1701           int i;
1702
1703                 /* this code might seem better but it does the *same* job with
1704                  * the old code, it all depends on ralloc.c to get a free/unused
1705                  * register */
1706          
1707                 i=0;
1708                 while(i < pic16_nRegs) {
1709                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1710                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1711                         if((!rr || (rr && rr->isFree))
1712                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1713                                 pcop = pic16_newpCodeOpReg( i );
1714                                 PCOR(pcop)->r->wasUsed = 1;
1715                                 PCOR(pcop)->r->isFree = 0;
1716                                 break;
1717                         }
1718                         i++;
1719                 }
1720
1721                 if(pcop) {
1722                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1723                 }
1724         }
1725 #else
1726     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1727     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1728       PCOR(pcop)->r->wasUsed=1;
1729       PCOR(pcop)->r->isFree=0;
1730
1731       /* push value on stack */
1732       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1733     }
1734 #endif
1735
1736     currFunc = cfunc;
1737
1738   return pcop;
1739 }
1740
1741 /*-----------------------------------------------------------------*/
1742 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1743 /*                           is not part of f, but don't save if   */
1744 /*                           inside v                              */
1745 /*-----------------------------------------------------------------*/
1746 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1747 {
1748   pCodeOp *pcop=NULL;
1749   symbol *cfunc;
1750   int i;
1751
1752 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1753
1754     if(_TempReg_lock) {
1755 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1756     }
1757
1758     _TempReg_lock += lock;
1759
1760     cfunc = currFunc;
1761     currFunc = NULL;
1762
1763     i = bitVectFirstBit(f);
1764     while(i < 128) {
1765
1766       /* bypass registers that are used by function */
1767       if(!bitVectBitValue(f, i)) {
1768       
1769         /* bypass registers that are already allocated for stack access */
1770         if(!bitVectBitValue(v, i))  {
1771         
1772 //          debugf("getting register rIdx = %d\n", i);
1773           /* ok, get the operand */
1774           pcop = pic16_newpCodeOpReg( i );
1775     
1776           /* should never by NULL */
1777           assert( pcop != NULL );
1778
1779           
1780           /* sanity check */
1781           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1782             int found=0;
1783             
1784               PCOR(pcop)->r->wasUsed=1;
1785               PCOR(pcop)->r->isFree=0;
1786
1787
1788               {
1789                 regs *sr;
1790               
1791                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1792
1793                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1794                       /* already used in previous steps, break */
1795                       found=1;          
1796                       break;
1797                     }
1798                   }
1799               }
1800
1801               /* caller takes care of the following */
1802 //              bitVectSetBit(v, i);
1803
1804               if(!found) {
1805                 /* push value on stack */
1806                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1807                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1808               }
1809           
1810             break;
1811           }
1812         }
1813       }
1814       i++;
1815     }
1816
1817     currFunc = cfunc;
1818
1819   return pcop;
1820 }
1821
1822
1823 /*-----------------------------------------------------------------*/
1824 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1825 /*-----------------------------------------------------------------*/
1826 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1827 {
1828   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1829
1830   _TempReg_lock -= lock;
1831
1832   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1833     PCOR(pcop)->r->isFree = 1;
1834
1835     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1836   }
1837 }
1838 /*-----------------------------------------------------------------*/
1839 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1840 /*-----------------------------------------------------------------*/
1841 pCodeOp *pic16_popGetLabel(int key)
1842 {
1843
1844   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1845
1846   if(key>max_key)
1847     max_key = key;
1848
1849   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1850 }
1851
1852 /*-----------------------------------------------------------------*/
1853 /* pic16_popCopyReg - copy a pcode operator                              */
1854 /*-----------------------------------------------------------------*/
1855 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1856 {
1857   pCodeOpReg *pcor;
1858
1859   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1860   memcpy (pcor, pc, sizeof (pCodeOpReg));
1861   pcor->r->wasUsed = 1;
1862   
1863   //pcor->pcop.type = pc->pcop.type;
1864   if(pc->pcop.name) {
1865     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1866       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1867   } else
1868     pcor->pcop.name = NULL;
1869
1870   //pcor->r = pc->r;
1871   //pcor->rIdx = pc->rIdx;
1872   //pcor->r->wasUsed=1;
1873   //pcor->instance = pc->instance;
1874
1875 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1876
1877   return PCOP(pcor);
1878 }
1879
1880 /*-----------------------------------------------------------------*/
1881 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1882 /*-----------------------------------------------------------------*/
1883 pCodeOp *pic16_popGetLit(int lit)
1884 {
1885   return pic16_newpCodeOpLit(lit);
1886 }
1887
1888 /* Allow for 12 bit literals (LFSR x, <here!>). */
1889 pCodeOp *pic16_popGetLit12(int lit)
1890 {
1891   return pic16_newpCodeOpLit12(lit);
1892 }
1893
1894 /*-----------------------------------------------------------------*/
1895 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1896 /*-----------------------------------------------------------------*/
1897 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1898 {
1899   return pic16_newpCodeOpLit2(lit, arg2);
1900 }
1901
1902
1903 /*-----------------------------------------------------------------*/
1904 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1905 /*-----------------------------------------------------------------*/
1906 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1907 {
1908   return pic16_newpCodeOpImmd(name, offset,index, 0);
1909 }
1910
1911
1912 /*-----------------------------------------------------------------*/
1913 /* pic16_popGet - asm operator to pcode operator conversion              */
1914 /*-----------------------------------------------------------------*/
1915 pCodeOp *pic16_popGetWithString(char *str)
1916 {
1917   pCodeOp *pcop;
1918
1919
1920   if(!str) {
1921     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1922     exit (1);
1923   }
1924
1925   pcop = pic16_newpCodeOp(str,PO_STR);
1926
1927   return pcop;
1928 }
1929
1930 /*-----------------------------------------------------------------*/
1931 /* pic16_popRegFromString -                                        */
1932 /*-----------------------------------------------------------------*/
1933 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1934 {
1935
1936   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1937   pcop->type = PO_DIR;
1938
1939   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1940   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1941
1942   if(!str)
1943     str = "BAD_STRING";
1944
1945   pcop->name = Safe_calloc(1,strlen(str)+1);
1946   strcpy(pcop->name,str);
1947
1948   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1949
1950   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1951 //  PCOR(pcop)->r->wasUsed = 1;
1952
1953   /* make sure that register doesn't exist,
1954    * and operand isn't NULL
1955    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1956   if((PCOR(pcop)->r == NULL) 
1957     && (op)
1958     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1959 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1960 //              __FUNCTION__, __LINE__, str, size, offset);
1961
1962     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1963     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1964
1965   }
1966   PCOR(pcop)->instance = offset;
1967
1968   return pcop;
1969 }
1970
1971 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1972 {
1973   pCodeOp *pcop;
1974
1975 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1976 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1977         
1978         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1979         PCOR(pcop)->rIdx = rIdx;
1980         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1981         if(!PCOR(pcop)->r)
1982                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1983                 
1984         PCOR(pcop)->r->isFree = 0;
1985         PCOR(pcop)->r->wasUsed = 1;
1986
1987         pcop->type = PCOR(pcop)->r->pc_type;
1988
1989   return pcop;
1990 }
1991
1992 /*---------------------------------------------------------------------------------*/
1993 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1994 /*                 VR 030601                                                       */
1995 /*---------------------------------------------------------------------------------*/
1996 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1997 {
1998   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1999         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2000   return PCOP(pcop2);
2001 }
2002
2003
2004
2005 /*--------------------------------------------------------------------------------.-*/
2006 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2007 /*                  VR 030601 , adapted by Hans Dorn                                */
2008 /*--------------------------------------------------------------------------------.-*/
2009 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2010 {
2011   pCodeOp2 *pcop2;
2012   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2013   return PCOP(pcop2);
2014 }
2015
2016 /*---------------------------------------------------------------------------------*/
2017 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2018 /*                     movff instruction                                           */
2019 /*---------------------------------------------------------------------------------*/
2020 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2021 {
2022   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2023         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2024
2025   return PCOP(pcop2);
2026 }
2027
2028
2029 /*-----------------------------------------------------------------*/
2030 /* pic16_popGet - asm operator to pcode operator conversion              */
2031 /*-----------------------------------------------------------------*/
2032 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2033 {
2034 //  char *s = buffer ;
2035 //  char *rs;
2036   pCodeOp *pcop;
2037
2038         FENTRY2;
2039                 /* offset is greater than
2040                  * size then zero */
2041
2042 //    if (offset > (aop->size - 1) &&
2043 //        aop->type != AOP_LIT)
2044 //      return NULL;  //zero;
2045
2046     /* depending on type */
2047     switch (aop->type) {
2048                 case AOP_R0:
2049                 case AOP_R1:
2050                 case AOP_DPTR:
2051                 case AOP_DPTR2:
2052                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2053                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2054                         assert( 0 );
2055                         return NULL;
2056
2057                 case AOP_FSR0:
2058                 case AOP_FSR2:
2059                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2060                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2061                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2062                         PCOR(pcop)->r->wasUsed = 1;
2063                         PCOR(pcop)->r->isFree = 0;
2064       
2065                         PCOR(pcop)->instance = offset;
2066                         pcop->type = PCOR(pcop)->r->pc_type;
2067                         return (pcop);
2068
2069                 case AOP_IMMD:
2070                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2071                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2072
2073                 case AOP_STA:
2074                         /* pCodeOp is already allocated from aopForSym */
2075                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2076                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2077                         return (pcop);
2078       
2079                 case AOP_ACC:
2080                         {
2081                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2082
2083                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2084
2085                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2086         
2087                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2088                                 PCOR(pcop)->rIdx = rIdx;
2089                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2090                                 PCOR(pcop)->r->wasUsed=1;
2091                                 PCOR(pcop)->r->isFree=0;
2092
2093                                 PCOR(pcop)->instance = offset;
2094                                 pcop->type = PCOR(pcop)->r->pc_type;
2095 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2096                                 return pcop;
2097
2098
2099 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2100 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2101
2102 //      assert( 0 );
2103                         }
2104         
2105     case AOP_DIR:
2106       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2107       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2108         
2109 #if 0
2110     case AOP_PAGED:
2111       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2112       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2113 #endif
2114
2115     case AOP_REG:
2116       {
2117         int rIdx;
2118         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2119         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2120
2121         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2122         
2123         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2124 //      pcop->type = PO_GPR_REGISTER;
2125         PCOR(pcop)->rIdx = rIdx;
2126         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2127         PCOR(pcop)->r->wasUsed=1;
2128         PCOR(pcop)->r->isFree=0;
2129
2130         PCOR(pcop)->instance = offset;
2131         pcop->type = PCOR(pcop)->r->pc_type;
2132         
2133         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2134 //      rs = aop->aopu.aop_reg[offset]->name;
2135 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2136         return pcop;
2137       }
2138
2139     case AOP_CRY:
2140         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2141
2142       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2143       PCOR(pcop)->instance = offset;
2144       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2145       //if(PCOR(pcop)->r == NULL)
2146       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2147       return pcop;
2148         
2149     case AOP_LIT:
2150         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2151       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2152
2153     case AOP_STR:
2154       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2155       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2156
2157       /*
2158       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2159       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2160       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2161       pcop->type = PCOR(pcop)->r->pc_type;
2162       pcop->name = PCOR(pcop)->r->name;
2163
2164       return pcop;
2165       */
2166
2167     case AOP_PCODE:
2168       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2169                           __LINE__, 
2170                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2171       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2172       switch( aop->aopu.pcop->type ) {
2173         case PO_DIR: PCOR(pcop)->instance += offset; break;
2174         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2175         case PO_WREG:
2176             assert (offset==0);
2177             break;
2178         default:
2179           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2180           assert( 0 );  /* should never reach here */;
2181       }
2182       return pcop;
2183     }
2184
2185     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2186            "pic16_popGet got unsupported aop->type");
2187     exit(0);
2188 }
2189 /*-----------------------------------------------------------------*/
2190 /* pic16_aopPut - puts a string for a aop                                */
2191 /*-----------------------------------------------------------------*/
2192 void pic16_aopPut (asmop *aop, char *s, int offset)
2193 {
2194     char *d = buffer ;
2195     symbol *lbl ;
2196
2197     return;
2198
2199     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2200
2201     if (aop->size && offset > ( aop->size - 1)) {
2202         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2203                "pic16_aopPut got offset > aop->size");
2204         exit(0);
2205     }
2206
2207     /* will assign value to value */
2208     /* depending on where it is ofcourse */
2209     switch (aop->type) {
2210     case AOP_DIR:
2211       if (offset) {
2212         sprintf(d,"(%s + %d)",
2213                 aop->aopu.aop_dir,offset);
2214         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2215
2216       } else
2217             sprintf(d,"%s",aop->aopu.aop_dir);
2218         
2219         if (strcmp(d,s)) {
2220           DEBUGpic16_emitcode(";","%d",__LINE__);
2221           if(strcmp(s,"W"))
2222             pic16_emitcode("movf","%s,w",s);
2223           pic16_emitcode("movwf","%s",d);
2224
2225           if(strcmp(s,"W")) {
2226             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2227             if(offset >= aop->size) {
2228               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2229               break;
2230             } else
2231               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2232           }
2233
2234           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2235
2236
2237         }
2238         break;
2239         
2240     case AOP_REG:
2241       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2242         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2243           /*
2244             if (*s == '@'           ||
2245                 strcmp(s,"r0") == 0 ||
2246                 strcmp(s,"r1") == 0 ||
2247                 strcmp(s,"r2") == 0 ||
2248                 strcmp(s,"r3") == 0 ||
2249                 strcmp(s,"r4") == 0 ||
2250                 strcmp(s,"r5") == 0 ||
2251                 strcmp(s,"r6") == 0 || 
2252                 strcmp(s,"r7") == 0 )
2253                 pic16_emitcode("mov","%s,%s  ; %d",
2254                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2255             else
2256           */
2257
2258           if(strcmp(s,"W")==0 )
2259             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2260
2261           pic16_emitcode("movwf","%s",
2262                    aop->aopu.aop_reg[offset]->name);
2263
2264           if(strcmp(s,zero)==0) {
2265             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2266
2267           } else if(strcmp(s,"W")==0) {
2268             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2269             pcop->type = PO_GPR_REGISTER;
2270
2271             PCOR(pcop)->rIdx = -1;
2272             PCOR(pcop)->r = NULL;
2273
2274             DEBUGpic16_emitcode(";","%d",__LINE__);
2275             pcop->name = Safe_strdup(s);
2276             pic16_emitpcode(POC_MOVFW,pcop);
2277             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2278           } else if(strcmp(s,one)==0) {
2279             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2280             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2281           } else {
2282             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2283           }
2284         }
2285         break;
2286         
2287     case AOP_DPTR:
2288     case AOP_DPTR2:
2289     
2290     if (aop->type == AOP_DPTR2)
2291     {
2292         genSetDPTR(1);
2293     }
2294     
2295         if (aop->code) {
2296             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2297                    "pic16_aopPut writting to code space");
2298             exit(0);
2299         }
2300         
2301         while (offset > aop->coff) {
2302             aop->coff++;
2303             pic16_emitcode ("inc","dptr");
2304         }
2305         
2306         while (offset < aop->coff) {
2307             aop->coff-- ;
2308             pic16_emitcode("lcall","__decdptr");
2309         }
2310         
2311         aop->coff = offset;
2312         
2313         /* if not in accumulater */
2314         MOVA(s);        
2315         
2316         pic16_emitcode ("movx","@dptr,a");
2317         
2318     if (aop->type == AOP_DPTR2)
2319     {
2320         genSetDPTR(0);
2321     }
2322         break;
2323         
2324     case AOP_R0:
2325     case AOP_R1:
2326         while (offset > aop->coff) {
2327             aop->coff++;
2328             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2329         }
2330         while (offset < aop->coff) {
2331             aop->coff-- ;
2332             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2333         }
2334         aop->coff = offset;
2335         
2336         if (aop->paged) {
2337             MOVA(s);           
2338             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2339             
2340         } else
2341             if (*s == '@') {
2342                 MOVA(s);
2343                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2344             } else
2345                 if (strcmp(s,"r0") == 0 ||
2346                     strcmp(s,"r1") == 0 ||
2347                     strcmp(s,"r2") == 0 ||
2348                     strcmp(s,"r3") == 0 ||
2349                     strcmp(s,"r4") == 0 ||
2350                     strcmp(s,"r5") == 0 ||
2351                     strcmp(s,"r6") == 0 || 
2352                     strcmp(s,"r7") == 0 ) {
2353                     char buffer[10];
2354                     sprintf(buffer,"a%s",s);
2355                     pic16_emitcode("mov","@%s,%s",
2356                              aop->aopu.aop_ptr->name,buffer);
2357                 } else
2358                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2359         
2360         break;
2361         
2362     case AOP_STK:
2363         if (strcmp(s,"a") == 0)
2364             pic16_emitcode("push","acc");
2365         else
2366             pic16_emitcode("push","%s",s);
2367         
2368         break;
2369         
2370     case AOP_CRY:
2371         /* if bit variable */
2372         if (!aop->aopu.aop_dir) {
2373             pic16_emitcode("clr","a");
2374             pic16_emitcode("rlc","a");
2375         } else {
2376             if (s == zero) 
2377                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2378             else
2379                 if (s == one)
2380                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2381                 else
2382                     if (!strcmp(s,"c"))
2383                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2384                     else {
2385                         lbl = newiTempLabel(NULL);
2386                         
2387                         if (strcmp(s,"a")) {
2388                             MOVA(s);
2389                         }
2390                         pic16_emitcode("clr","c");
2391                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2392                         pic16_emitcode("cpl","c");
2393                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2394                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2395                     }
2396         }
2397         break;
2398         
2399     case AOP_STR:
2400         aop->coff = offset;
2401         if (strcmp(aop->aopu.aop_str[offset],s))
2402             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2403         break;
2404         
2405     case AOP_ACC:
2406         aop->coff = offset;
2407         if (!offset && (strcmp(s,"acc") == 0))
2408             break;
2409         
2410         if (strcmp(aop->aopu.aop_str[offset],s))
2411             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2412         break;
2413
2414     default :
2415         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2416 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2417 //             "pic16_aopPut got unsupported aop->type");
2418 //      exit(0);    
2419     }    
2420
2421 }
2422
2423 /*-----------------------------------------------------------------*/
2424 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2425 /*-----------------------------------------------------------------*/
2426 void pic16_mov2w (asmop *aop, int offset)
2427 {
2428   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2429
2430   if(is_LitAOp(aop))
2431     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2432   else
2433     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2434 }
2435
2436 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2437 {
2438   if(is_LitAOp(src)) {
2439     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2440     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2441   } else {
2442     if(pic16_sameRegsOfs(src, dst, offset))return;
2443     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2444                       pic16_popGet(dst, offset)));
2445   }
2446 }
2447
2448 static void pic16_movLit2f(pCodeOp *pc, int lit)
2449 {
2450   if (0 == (lit & 0x00ff))
2451   {
2452     pic16_emitpcode (POC_CLRF, pc);
2453   } else if (0xff == (lit & 0x00ff))
2454   {
2455     pic16_emitpcode (POC_SETF, pc);
2456   } else {
2457     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2458     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2459   }
2460 }
2461
2462 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2463 {
2464   if(is_LitAOp(src)) {
2465     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2466     pic16_emitpcode(POC_MOVWF, dst);
2467   } else {
2468     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2469   }
2470 }
2471
2472 void pic16_testStackOverflow(void)
2473 {
2474 #define GSTACK_TEST_NAME        "_gstack_test"
2475
2476   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2477   
2478   {
2479     symbol *sym;
2480
2481       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2482       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2483 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2484       checkAddSym(&externs, sym);
2485   }
2486
2487 }
2488
2489 /* push pcop into stack */
2490 void pic16_pushpCodeOp(pCodeOp *pcop)
2491 {
2492 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2493   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2494   if(pic16_options.gstack)
2495     pic16_testStackOverflow();
2496     
2497 }
2498
2499 /* pop pcop from stack */
2500 void pic16_poppCodeOp(pCodeOp *pcop)
2501 {
2502   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2503   if(pic16_options.gstack)
2504     pic16_testStackOverflow();
2505 }
2506
2507
2508 /*-----------------------------------------------------------------*/
2509 /* pushw - pushes wreg to stack                                    */
2510 /*-----------------------------------------------------------------*/
2511 void pushw(void)
2512 {
2513   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2514   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2515   if(pic16_options.gstack)
2516     pic16_testStackOverflow();
2517 }
2518
2519                 
2520 /*-----------------------------------------------------------------*/
2521 /* pushaop - pushes aop to stack                                   */
2522 /*-----------------------------------------------------------------*/
2523 void pushaop(asmop *aop, int offset)
2524 {
2525   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2526
2527   if(_G.resDirect)return;
2528   
2529   if(is_LitAOp(aop)) {
2530     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2531     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2532   } else {
2533     pic16_emitpcode(POC_MOVFF,
2534       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2535   }
2536
2537   if(pic16_options.gstack)
2538     pic16_testStackOverflow();
2539 }
2540
2541 /*-----------------------------------------------------------------*/
2542 /* popaop - pops aop from stack                                    */
2543 /*-----------------------------------------------------------------*/
2544 void popaop(asmop *aop, int offset)
2545 {
2546   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2547   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2548   if(pic16_options.gstack)
2549     pic16_testStackOverflow();
2550 }
2551
2552 void popaopidx(asmop *aop, int offset, int index)
2553 {
2554   int ofs=1;
2555
2556     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2557
2558     if(STACK_MODEL_LARGE)ofs++;
2559
2560     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2561     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2562     if(pic16_options.gstack)
2563       pic16_testStackOverflow();
2564 }
2565
2566 #if !(USE_GENERIC_SIGNED_SHIFT)
2567 /*-----------------------------------------------------------------*/
2568 /* reAdjustPreg - points a register back to where it should        */
2569 /*-----------------------------------------------------------------*/
2570 static void reAdjustPreg (asmop *aop)
2571 {
2572     int size ;
2573
2574     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2575     aop->coff = 0;
2576     if ((size = aop->size) <= 1)
2577         return ;
2578     size-- ;
2579     switch (aop->type) {
2580         case AOP_R0 :
2581         case AOP_R1 :
2582             while (size--)
2583                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2584             break;          
2585         case AOP_DPTR :
2586         case AOP_DPTR2:
2587             if (aop->type == AOP_DPTR2)
2588             {
2589                 genSetDPTR(1);
2590             } 
2591             while (size--)
2592             {
2593                 pic16_emitcode("lcall","__decdptr");
2594             }
2595                 
2596             if (aop->type == AOP_DPTR2)
2597             {
2598                 genSetDPTR(0);
2599             }                
2600             break;  
2601
2602     }   
2603
2604 }
2605 #endif
2606
2607 #if 0
2608 /*-----------------------------------------------------------------*/
2609 /* opIsGptr: returns non-zero if the passed operand is             */   
2610 /* a generic pointer type.                                         */
2611 /*-----------------------------------------------------------------*/ 
2612 static int opIsGptr(operand *op)
2613 {
2614     sym_link *type = operandType(op);
2615     
2616     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2617     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2618     {
2619         return 1;
2620     }
2621     return 0;        
2622 }
2623 #endif
2624
2625 /*-----------------------------------------------------------------*/
2626 /* pic16_getDataSize - get the operand data size                         */
2627 /*-----------------------------------------------------------------*/
2628 int pic16_getDataSize(operand *op)
2629 {
2630     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2631
2632
2633     return AOP_SIZE(op);
2634
2635     // tsd- in the pic port, the genptr size is 1, so this code here
2636     // fails. ( in the 8051 port, the size was 4).
2637 #if 0
2638     int size;
2639     size = AOP_SIZE(op);
2640     if (size == GPTRSIZE)
2641     {
2642         sym_link *type = operandType(op);
2643         if (IS_GENPTR(type))
2644         {
2645             /* generic pointer; arithmetic operations
2646              * should ignore the high byte (pointer type).
2647              */
2648             size--;
2649     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2650         }
2651     }
2652     return size;
2653 #endif
2654 }
2655
2656 /*-----------------------------------------------------------------*/
2657 /* pic16_outAcc - output Acc                                             */
2658 /*-----------------------------------------------------------------*/
2659 void pic16_outAcc(operand *result)
2660 {
2661   int size,offset;
2662   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2663   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2664
2665
2666   size = pic16_getDataSize(result);
2667   if(size){
2668     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2669     size--;
2670     offset = 1;
2671     /* unsigned or positive */
2672     while(size--)
2673       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2674   }
2675
2676 }
2677
2678 /*-----------------------------------------------------------------*/
2679 /* pic16_outBitC - output a bit C                                  */
2680 /*                 Move to result the value of Carry flag -- VR    */
2681 /*-----------------------------------------------------------------*/
2682 void pic16_outBitC(operand *result)
2683 {
2684   int i;
2685
2686     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2687
2688     /* if the result is bit */
2689     if (AOP_TYPE(result) == AOP_CRY) {
2690         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2691         pic16_aopPut(AOP(result),"c",0);
2692     } else {
2693
2694         i = AOP_SIZE(result);
2695         while(i--) {
2696                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2697         }
2698         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2699     }
2700 }
2701
2702 /*-----------------------------------------------------------------*/
2703 /* pic16_outBitOp - output a bit from Op                           */
2704 /*                 Move to result the value of set/clr op -- VR    */
2705 /*-----------------------------------------------------------------*/
2706 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2707 {
2708   int i;
2709
2710     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2711
2712     /* if the result is bit */
2713     if (AOP_TYPE(result) == AOP_CRY) {
2714         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2715         pic16_aopPut(AOP(result),"c",0);
2716     } else {
2717
2718         i = AOP_SIZE(result);
2719         while(i--) {
2720                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2721         }
2722         pic16_emitpcode(POC_RRCF, pcop);          
2723         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2724     }
2725 }
2726
2727 /*-----------------------------------------------------------------*/
2728 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2729 /*-----------------------------------------------------------------*/
2730 void pic16_toBoolean(operand *oper)
2731 {
2732     int size = AOP_SIZE(oper) - 1;
2733     int offset = 1;
2734
2735     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2736
2737     if ( AOP_TYPE(oper) != AOP_ACC) {
2738       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2739     }
2740     while (size--) {
2741       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2742     }
2743 }
2744
2745 /*-----------------------------------------------------------------*/
2746 /* genUminusFloat - unary minus for floating points                */
2747 /*-----------------------------------------------------------------*/
2748 static void genUminusFloat(operand *op,operand *result)
2749 {
2750   int size ,offset =0 ;
2751   
2752     FENTRY;
2753     /* for this we just need to flip the 
2754     first it then copy the rest in place */
2755     size = AOP_SIZE(op);
2756     assert( size == AOP_SIZE(result) );
2757
2758     while(size--) {
2759       pic16_mov2f(AOP(result), AOP(op), offset);
2760       offset++;
2761     }
2762     
2763     /* toggle the MSB's highest bit */
2764     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2765 }
2766
2767 /*-----------------------------------------------------------------*/
2768 /* genUminus - unary minus code generation                         */
2769 /*-----------------------------------------------------------------*/
2770 static void genUminus (iCode *ic)
2771 {
2772   int size, i;
2773   sym_link *optype, *rtype;
2774   symbol *label;
2775   int needLabel=0;
2776
2777     FENTRY;     
2778     
2779     /* assign asmops */
2780     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2781     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2782
2783     /* if both in bit space then special case */
2784     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2785       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2786         
2787         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2788         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2789         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2790         goto release; 
2791     } 
2792
2793     optype = operandType(IC_LEFT(ic));
2794     rtype = operandType(IC_RESULT(ic));
2795
2796
2797     /* if float then do float stuff */
2798     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2799       if(IS_FIXED(optype))
2800         debugf("implement fixed16x16 type\n", 0);
2801         
2802         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2803         goto release;
2804     }
2805
2806     /* otherwise subtract from zero by taking the 2's complement */
2807     size = AOP_SIZE(IC_LEFT(ic));
2808     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2809     label = newiTempLabel ( NULL );
2810     
2811     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2812       for (i=size-1; i > 0; i--) {
2813         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2814       } // for
2815       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2816       for (i=1; i < size; i++) {
2817         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2818         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2819       } // for
2820     } else {
2821       for (i=size-1; i >= 0; i--) {
2822         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2823         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2824       } // for
2825       if (size > 1) {
2826         for (i=0; i < size-2; i++) {
2827           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2828           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2829         } // for
2830         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2831       } // if
2832       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2833     }
2834     if (needLabel)
2835       pic16_emitpLabel (label->key);
2836
2837 release:
2838     /* release the aops */
2839     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2840     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2841 }
2842
2843 #if 0
2844 /*-----------------------------------------------------------------*/
2845 /* saveRegisters - will look for a call and save the registers     */
2846 /*-----------------------------------------------------------------*/
2847 static void saveRegisters(iCode *lic) 
2848 {
2849     int i;
2850     iCode *ic;
2851     bitVect *rsave;
2852     sym_link *dtype;
2853
2854     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2855     /* look for call */
2856     for (ic = lic ; ic ; ic = ic->next) 
2857         if (ic->op == CALL || ic->op == PCALL)
2858             break;
2859
2860     if (!ic) {
2861         fprintf(stderr,"found parameter push with no function call\n");
2862         return ;
2863     }
2864
2865     /* if the registers have been saved already then
2866     do nothing */
2867     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2868         return ;
2869
2870     /* find the registers in use at this time 
2871     and push them away to safety */
2872     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2873                           ic->rUsed);
2874
2875     ic->regsSaved = 1;
2876     if (options.useXstack) {
2877         if (bitVectBitValue(rsave,R0_IDX))
2878             pic16_emitcode("mov","b,r0");
2879         pic16_emitcode("mov","r0,%s",spname);
2880         for (i = 0 ; i < pic16_nRegs ; i++) {
2881             if (bitVectBitValue(rsave,i)) {
2882                 if (i == R0_IDX)
2883                     pic16_emitcode("mov","a,b");
2884                 else
2885                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2886                 pic16_emitcode("movx","@r0,a");
2887                 pic16_emitcode("inc","r0");
2888             }
2889         }
2890         pic16_emitcode("mov","%s,r0",spname);
2891         if (bitVectBitValue(rsave,R0_IDX))
2892             pic16_emitcode("mov","r0,b");           
2893     }// else
2894     //for (i = 0 ; i < pic16_nRegs ; i++) {
2895     //    if (bitVectBitValue(rsave,i))
2896     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2897     //}
2898
2899     dtype = operandType(IC_LEFT(ic));
2900     if (currFunc && dtype && 
2901         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2902         IFFUNC_ISISR(currFunc->type) &&
2903         !ic->bankSaved) 
2904
2905         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2906
2907 }
2908 /*-----------------------------------------------------------------*/
2909 /* unsaveRegisters - pop the pushed registers                      */
2910 /*-----------------------------------------------------------------*/
2911 static void unsaveRegisters (iCode *ic)
2912 {
2913     int i;
2914     bitVect *rsave;
2915
2916     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2917     /* find the registers in use at this time 
2918     and push them away to safety */
2919     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2920                           ic->rUsed);
2921     
2922     if (options.useXstack) {
2923         pic16_emitcode("mov","r0,%s",spname);   
2924         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2925             if (bitVectBitValue(rsave,i)) {
2926                 pic16_emitcode("dec","r0");
2927                 pic16_emitcode("movx","a,@r0");
2928                 if (i == R0_IDX)
2929                     pic16_emitcode("mov","b,a");
2930                 else
2931                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2932             }       
2933
2934         }
2935         pic16_emitcode("mov","%s,r0",spname);
2936         if (bitVectBitValue(rsave,R0_IDX))
2937             pic16_emitcode("mov","r0,b");
2938     } //else
2939     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2940     //    if (bitVectBitValue(rsave,i))
2941     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2942     //}
2943
2944 }  
2945 #endif
2946
2947 #if 0  // patch 14
2948 /*-----------------------------------------------------------------*/
2949 /* pushSide -                                                      */
2950 /*-----------------------------------------------------------------*/
2951 static void pushSide(operand * oper, int size)
2952 {
2953         int offset = 0;
2954     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2955         while (size--) {
2956                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2957                 if (AOP_TYPE(oper) != AOP_REG &&
2958                     AOP_TYPE(oper) != AOP_DIR &&
2959                     strcmp(l,"a") ) {
2960                         pic16_emitcode("mov","a,%s",l);
2961                         pic16_emitcode("push","acc");
2962                 } else
2963                         pic16_emitcode("push","%s",l);
2964         }
2965 }
2966 #endif // patch 14
2967
2968 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2969 {
2970   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2971     pic16_emitpcode(POC_MOVFW, src);
2972     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2973   } else {
2974     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2975         src, pic16_popGet(AOP(op), offset)));
2976   }
2977 }
2978
2979
2980 /*-----------------------------------------------------------------*/
2981 /* assignResultValue - assign results to oper, rescall==1 is       */
2982 /*                     called from genCall() or genPcall()         */
2983 /*-----------------------------------------------------------------*/
2984 static void assignResultValue(operand * oper, int rescall)
2985 {
2986   int size = AOP_SIZE(oper);
2987   int offset=0;
2988   
2989     FENTRY2;
2990 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2991     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2992
2993     if(rescall) {
2994       /* assign result from a call/pcall function() */
2995                 
2996       /* function results are stored in a special order,
2997        * see top of file with Function return policy, or manual */
2998
2999       if(size <= 4) {
3000         /* 8-bits, result in WREG */
3001         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3002                         
3003         if(size>1) {
3004           /* 16-bits, result in PRODL:WREG */
3005           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3006         }
3007                         
3008         if(size>2) {
3009           /* 24-bits, result in PRODH:PRODL:WREG */
3010           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3011         }
3012                         
3013         if(size>3) {
3014           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3015           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3016         }
3017       
3018       } else {
3019         /* >32-bits, result on stack, and FSR0 points to beginning.
3020          * Fix stack when done */
3021         /* FIXME FIXME */
3022 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3023         while (size--) {
3024 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3025 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3026                 
3027           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3028           GpsuedoStkPtr++;
3029         }
3030                         
3031         /* fix stack */
3032         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3033         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3034         if(STACK_MODEL_LARGE) {
3035           emitSKPNC;
3036           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3037         }
3038       }                 
3039     } else {
3040       int areg = 0;             /* matching argument register */
3041       
3042 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3043       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3044
3045
3046       /* its called from genReceive (probably) -- VR */
3047       /* I hope this code will not be called from somewhere else in the future! 
3048        * We manually set the pseudo stack pointer in genReceive. - dw
3049        */
3050       if(!GpsuedoStkPtr && _G.useWreg) {
3051 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3052
3053         /* The last byte in the assignment is in W */
3054         if(areg <= GpsuedoStkPtr) {
3055           size--;
3056           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3057           offset++;
3058 //          debugf("receive from WREG\n", 0);
3059         }
3060         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3061       }
3062 //      GpsuedoStkPtr++;
3063       _G.stack_lat = AOP_SIZE(oper)-1;
3064
3065       while (size) {
3066         size--;
3067         GpsuedoStkPtr++;
3068         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3069 //        debugf("receive from STACK\n", 0);
3070         offset++;
3071       }
3072     }
3073 }
3074
3075
3076 /*-----------------------------------------------------------------*/
3077 /* genIpush - generate code for pushing this gets a little complex */
3078 /*-----------------------------------------------------------------*/
3079 static void genIpush (iCode *ic)
3080 {
3081 //  int size, offset=0;
3082
3083   FENTRY;
3084   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3085
3086   if(ic->parmPush) {
3087     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3088
3089     /* send to stack as normal */
3090     addSet(&_G.sendSet,ic);
3091 //    addSetHead(&_G.sendSet,ic);
3092     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3093   }
3094
3095         
3096 #if 0
3097     int size, offset = 0 ;
3098     char *l;
3099
3100
3101     /* if this is not a parm push : ie. it is spill push 
3102     and spill push is always done on the local stack */
3103     if (!ic->parmPush) {
3104
3105         /* and the item is spilt then do nothing */
3106         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3107             return ;
3108
3109         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3110         size = AOP_SIZE(IC_LEFT(ic));
3111         /* push it on the stack */
3112         while(size--) {
3113             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3114             if (*l == '#') {
3115                 MOVA(l);
3116                 l = "acc";
3117             }
3118             pic16_emitcode("push","%s",l);
3119         }
3120         return ;        
3121     }
3122
3123     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3124 #endif
3125 }
3126
3127 /*-----------------------------------------------------------------*/
3128 /* genIpop - recover the registers: can happen only for spilling   */
3129 /*-----------------------------------------------------------------*/
3130 static void genIpop (iCode *ic)
3131 {
3132   FENTRY;
3133   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3134 #if 0
3135     int size,offset ;
3136
3137
3138     /* if the temp was not pushed then */
3139     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3140         return ;
3141
3142     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3143     size = AOP_SIZE(IC_LEFT(ic));
3144     offset = (size-1);
3145     while (size--) 
3146         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3147                                    FALSE,TRUE));
3148
3149     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3150 #endif
3151 }
3152
3153 #if 0
3154 /*-----------------------------------------------------------------*/
3155 /* unsaverbank - restores the resgister bank from stack            */
3156 /*-----------------------------------------------------------------*/
3157 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3158 {
3159   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3160 #if 0
3161     int i;
3162     asmop *aop ;
3163     regs *r = NULL;
3164
3165     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3166     if (popPsw) {
3167         if (options.useXstack) {
3168             aop = newAsmop(0);
3169             r = getFreePtr(ic,&aop,FALSE);
3170             
3171             
3172             pic16_emitcode("mov","%s,_spx",r->name);
3173             pic16_emitcode("movx","a,@%s",r->name);
3174             pic16_emitcode("mov","psw,a");
3175             pic16_emitcode("dec","%s",r->name);
3176             
3177         }else
3178             pic16_emitcode ("pop","psw");
3179     }
3180
3181     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3182         if (options.useXstack) {       
3183             pic16_emitcode("movx","a,@%s",r->name);
3184             //pic16_emitcode("mov","(%s+%d),a",
3185             //       regspic16[i].base,8*bank+regspic16[i].offset);
3186             pic16_emitcode("dec","%s",r->name);
3187
3188         } else 
3189           pic16_emitcode("pop",""); //"(%s+%d)",
3190         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3191     }
3192
3193     if (options.useXstack) {
3194
3195         pic16_emitcode("mov","_spx,%s",r->name);
3196         pic16_freeAsmop(NULL,aop,ic,TRUE);
3197
3198     }
3199 #endif 
3200 }
3201
3202 /*-----------------------------------------------------------------*/
3203 /* saverbank - saves an entire register bank on the stack          */
3204 /*-----------------------------------------------------------------*/
3205 static void saverbank (int bank, iCode *ic, bool pushPsw)
3206 {
3207   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3208 #if 0
3209     int i;
3210     asmop *aop ;
3211     regs *r = NULL;
3212
3213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3214     if (options.useXstack) {
3215
3216         aop = newAsmop(0);
3217         r = getFreePtr(ic,&aop,FALSE);  
3218         pic16_emitcode("mov","%s,_spx",r->name);
3219
3220     }
3221
3222     for (i = 0 ; i < pic16_nRegs ;i++) {
3223         if (options.useXstack) {
3224             pic16_emitcode("inc","%s",r->name);
3225             //pic16_emitcode("mov","a,(%s+%d)",
3226             //         regspic16[i].base,8*bank+regspic16[i].offset);
3227             pic16_emitcode("movx","@%s,a",r->name);           
3228         } else 
3229           pic16_emitcode("push","");// "(%s+%d)",
3230                      //regspic16[i].base,8*bank+regspic16[i].offset);
3231     }
3232     
3233     if (pushPsw) {
3234         if (options.useXstack) {
3235             pic16_emitcode("mov","a,psw");
3236             pic16_emitcode("movx","@%s,a",r->name);     
3237             pic16_emitcode("inc","%s",r->name);
3238             pic16_emitcode("mov","_spx,%s",r->name);       
3239             pic16_freeAsmop (NULL,aop,ic,TRUE);
3240             
3241         } else
3242             pic16_emitcode("push","psw");
3243         
3244         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3245     }
3246     ic->bankSaved = 1;
3247 #endif
3248 }
3249 #endif  /* 0 */
3250
3251
3252 static int wparamCmp(void *p1, void *p2)
3253 {
3254   return (!strcmp((char *)p1, (char *)p2));
3255 }
3256
3257 int inWparamList(char *s)
3258 {
3259   return isinSetWith(wparamList, s, wparamCmp);
3260
3261
3262
3263 /*-----------------------------------------------------------------*/
3264 /* genCall - generates a call statement                            */
3265 /*-----------------------------------------------------------------*/
3266 static void genCall (iCode *ic)
3267 {
3268   sym_link *ftype;   
3269   int stackParms=0;
3270   int use_wreg=0;
3271   int inwparam=0;
3272   char *fname;
3273   
3274     FENTRY;
3275
3276     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3277     /* if caller saves & we have not saved then */
3278 //    if (!ic->regsSaved)
3279 //      saveRegisters(ic);
3280
3281         /* initialise stackParms for IPUSH pushes */
3282 //      stackParms = psuedoStkPtr;
3283 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3284     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3285     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3286
3287 #if 0
3288     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3289 #endif
3290
3291     /* if send set is not empty the assign */
3292     if (_G.sendSet) {
3293       iCode *sic;
3294       int psuedoStkPtr=-1; 
3295       int firstTimeThruLoop = 1;
3296
3297
3298         /* reverse sendSet if function is not reentrant */
3299         if(!IFFUNC_ISREENT(ftype))
3300           _G.sendSet = reverseSet(_G.sendSet);
3301
3302         /* First figure how many parameters are getting passed */
3303         stackParms = 0;
3304         use_wreg = 0;
3305         
3306         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3307           int size;
3308 //          int offset = 0;
3309
3310             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3311             size = AOP_SIZE(IC_LEFT(sic));
3312
3313             stackParms += size;
3314
3315             /* pass the last byte through WREG */
3316             if(inwparam) {
3317
3318               while (size--) {
3319                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3320                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3321                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3322
3323                 if(!firstTimeThruLoop) {
3324                   /* If this is not the first time we've been through the loop
3325                    * then we need to save the parameter in a temporary
3326                    * register. The last byte of the last parameter is
3327                    * passed in W. */
3328
3329                   pushw();
3330 //                  --psuedoStkPtr;             // sanity check
3331                   use_wreg = 1;
3332                 }
3333                 
3334                 firstTimeThruLoop=0;
3335
3336                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3337
3338 //                offset++;
3339               }
3340             } else {
3341               /* all arguments are passed via stack */
3342               use_wreg = 0;
3343
3344               while (size--) {
3345                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3346                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3347                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3348
3349 //                pushaop(AOP(IC_LEFT(sic)), size);
3350                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3351                                 
3352                 if(!_G.resDirect)
3353                   pushw();
3354               }
3355             }
3356
3357             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3358           }
3359
3360           if(inwparam) {
3361             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3362               pushw();  /* save last parameter to stack if functions has varargs */
3363               use_wreg = 0;
3364             } else
3365               use_wreg = 1;
3366           } else use_wreg = 0;
3367
3368           _G.stackRegSet = _G.sendSet;
3369           _G.sendSet = NULL;
3370     }
3371
3372     /* make the call */
3373     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3374
3375     GpsuedoStkPtr=0;
3376     
3377     /* if we need to assign a result value */
3378     if ((IS_ITEMP(IC_RESULT(ic))
3379           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3380               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3381         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3382
3383       _G.accInUse++;
3384       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3385       _G.accInUse--;
3386
3387       assignResultValue(IC_RESULT(ic), 1);
3388
3389       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3390                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3391                 
3392       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3393     }
3394
3395     if(!stackParms && ic->parmBytes) {
3396       stackParms = ic->parmBytes;
3397     }
3398       
3399     stackParms -= use_wreg;
3400     
3401     if(stackParms>0) {
3402       if(stackParms == 1) {
3403         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3404       } else {
3405         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3406         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3407       }
3408       if(STACK_MODEL_LARGE) {
3409         emitSKPNC;
3410         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3411       }
3412     }
3413
3414 #if 0
3415     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3416 #endif
3417
3418     /* adjust the stack for parameters if required */
3419 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3420
3421 #if 0
3422       /* if register bank was saved then pop them */
3423       if (ic->bankSaved)
3424         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3425
3426       /* if we hade saved some registers then unsave them */
3427       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3428         unsaveRegisters (ic);
3429 #endif
3430 }
3431
3432
3433
3434 /*-----------------------------------------------------------------*/
3435 /* genPcall - generates a call by pointer statement                */
3436 /*            new version, created from genCall - HJD              */
3437 /*-----------------------------------------------------------------*/
3438 static void genPcall (iCode *ic)
3439 {
3440   sym_link *fntype;
3441   int stackParms=0;
3442   symbol *retlbl = newiTempLabel(NULL);
3443   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3444   
3445     FENTRY;
3446
3447     fntype = operandType( IC_LEFT(ic) )->next;
3448
3449     /* if send set is not empty the assign */
3450     if (_G.sendSet) {
3451       iCode *sic;
3452       int psuedoStkPtr=-1; 
3453
3454       /* reverse sendSet if function is not reentrant */
3455       if(!IFFUNC_ISREENT(fntype))
3456         _G.sendSet = reverseSet(_G.sendSet);
3457
3458       stackParms = 0;
3459       
3460       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3461         int size;
3462
3463           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3464           size = AOP_SIZE(IC_LEFT(sic));
3465           stackParms += size;
3466
3467           /* all parameters are passed via stack, since WREG is clobbered
3468            * by the calling sequence */
3469           while (size--) {
3470             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3471             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3472             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3473
3474             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3475             pushw();
3476           }
3477
3478           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3479       }
3480
3481       _G.stackRegSet = _G.sendSet;
3482       _G.sendSet = NULL;
3483     }
3484
3485     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3486
3487     // push return address
3488     // push $ on return stack, then replace with retlbl
3489
3490     /* Thanks to Thorsten Klose for pointing out that the following
3491      * snippet should be interrupt safe */
3492     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3493     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3494
3495     pic16_emitpcodeNULLop(POC_PUSH);
3496
3497     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3498     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3499     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3500     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3501     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3502     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3503
3504
3505     /* restore interrupt control register */
3506     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3507     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3508
3509     /* make the call by writing the pointer into pc */
3510     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3511     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3512
3513     // note: MOVFF to PCL not allowed
3514     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3515     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3516
3517
3518     /* return address is here: (X) */
3519     pic16_emitpLabelFORCE(retlbl->key);
3520
3521     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3522
3523     GpsuedoStkPtr=0;
3524     /* if we need assign a result value */
3525     if ((IS_ITEMP(IC_RESULT(ic))
3526           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3527               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3528         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3529
3530       _G.accInUse++;
3531       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3532       _G.accInUse--;
3533
3534       assignResultValue(IC_RESULT(ic), 1);
3535
3536       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3537               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3538                 
3539       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3540     }
3541
3542 //    stackParms -= use_wreg;
3543     
3544     if(stackParms>0) {
3545       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3546       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3547       if(STACK_MODEL_LARGE) {
3548         emitSKPNC;
3549         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3550       }
3551     }
3552 }
3553
3554 /*-----------------------------------------------------------------*/
3555 /* resultRemat - result  is rematerializable                       */
3556 /*-----------------------------------------------------------------*/
3557 static int resultRemat (iCode *ic)
3558 {
3559   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3560   if (SKIP_IC(ic) || ic->op == IFX)
3561     return 0;
3562
3563   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3564     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3565     if (sym->remat && !POINTER_SET(ic)) 
3566       return 1;
3567   }
3568
3569   return 0;
3570 }
3571
3572 #if defined(__BORLANDC__) || defined(_MSC_VER)
3573 #define STRCASECMP stricmp
3574 #else
3575 #define STRCASECMP strcasecmp
3576 #endif
3577
3578 #if 0
3579 /*-----------------------------------------------------------------*/
3580 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3581 /*-----------------------------------------------------------------*/
3582 static bool inExcludeList(char *s)
3583 {
3584   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3585     int i =0;
3586     
3587     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3588     if (options.excludeRegs[i] &&
3589     STRCASECMP(options.excludeRegs[i],"none") == 0)
3590         return FALSE ;
3591
3592     for ( i = 0 ; options.excludeRegs[i]; i++) {
3593         if (options.excludeRegs[i] &&
3594         STRCASECMP(s,options.excludeRegs[i]) == 0)
3595             return TRUE;
3596     }
3597     return FALSE ;
3598 }
3599 #endif
3600
3601 /*-----------------------------------------------------------------*/
3602 /* genFunction - generated code for function entry                 */
3603 /*-----------------------------------------------------------------*/
3604 static void genFunction (iCode *ic)
3605 {
3606   symbol *sym;
3607   sym_link *ftype;
3608   
3609     FENTRY;
3610     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3611
3612     pic16_labelOffset += (max_key+4);
3613     max_key=0;
3614     GpsuedoStkPtr=0;
3615     _G.nRegsSaved = 0;
3616         
3617     ftype = operandType(IC_LEFT(ic));
3618     sym = OP_SYMBOL(IC_LEFT(ic));
3619
3620     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3621       /* create an absolute section at the interrupt vector:
3622        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3623       symbol *asym;
3624       char asymname[128];
3625       pBlock *apb;
3626
3627 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3628
3629         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3630           sprintf(asymname, "ivec_%s", sym->name);
3631         else
3632           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3633   
3634         /* when an interrupt is declared as naked, do not emit the special
3635          * wrapper segment at vector address. The user should take care for
3636          * this instead. -- VR */
3637
3638         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3639           asym = newSymbol(asymname, 0);
3640           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3641           pic16_addpBlock( apb );
3642
3643           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3644           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3645           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3646           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3647           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3648                 
3649           /* mark the end of this tiny function */
3650           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3651         } else {
3652           sprintf(asymname, "%s", sym->rname);
3653         }
3654
3655         {
3656           absSym *abSym;
3657
3658             abSym = Safe_calloc(1, sizeof(absSym));
3659             strcpy(abSym->name, asymname);
3660
3661             switch( FUNC_INTNO(sym->type) ) {
3662               case 0: abSym->address = 0x000000; break;
3663               case 1: abSym->address = 0x000008; break;
3664               case 2: abSym->address = 0x000018; break;
3665               
3666               default:
3667 //                fprintf(stderr, "no interrupt number is given\n");
3668                 abSym->address = -1; break;
3669             }
3670
3671             /* relocate interrupt vectors if needed */
3672             if(abSym->address != -1)
3673               abSym->address += pic16_options.ivt_loc;
3674
3675             addSet(&absSymSet, abSym);
3676         }
3677     }
3678
3679     /* create the function header */
3680     pic16_emitcode(";","-----------------------------------------");
3681     pic16_emitcode(";"," function %s",sym->name);
3682     pic16_emitcode(";","-----------------------------------------");
3683
3684     pic16_emitcode("","%s:",sym->rname);
3685     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3686
3687     {
3688       absSym *ab;
3689
3690         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3691           if(!strcmp(ab->name, sym->rname)) {
3692             pic16_pBlockConvert2Absolute(pb);
3693             break;
3694           }
3695         }
3696     }
3697
3698     if(IFFUNC_ISNAKED(ftype)) {
3699       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3700       return;
3701     }
3702         
3703     /* if critical function then turn interrupts off */
3704     if (IFFUNC_ISCRITICAL(ftype)) {
3705       //pic16_emitcode("clr","ea");
3706     }
3707
3708     currFunc = sym;             /* update the currFunc symbol */
3709     _G.fregsUsed = sym->regsUsed;
3710     _G.sregsAlloc = newBitVect(128);
3711     
3712
3713     /* if this is an interrupt service routine then
3714      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3715     if (IFFUNC_ISISR(sym->type)) {
3716         _G.usefastretfie = 1;   /* use shadow registers by default */
3717         
3718         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3719         if(!FUNC_ISSHADOWREGS(sym->type)) {
3720           /* do not save WREG,STATUS,BSR for high priority interrupts
3721            * because they are stored in the hardware shadow registers already */
3722           _G.usefastretfie = 0;
3723           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3724           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3725           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3726         }
3727
3728         /* these should really be optimized somehow, because not all
3729          * interrupt handlers modify them */
3730         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3731         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3732         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3733         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3734         
3735 //        pic16_pBlockConvert2ISR(pb);
3736     }
3737
3738     /* emit code to setup stack frame if user enabled,
3739      * and function is not main() */
3740     
3741 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3742     if(strcmp(sym->name, "main")) {
3743       if(0 
3744         || !options.ommitFramePtr 
3745 //        || sym->regsUsed
3746         || IFFUNC_ARGS(sym->type)
3747         || FUNC_HASSTACKPARM(sym->etype)
3748         ) {
3749         /* setup the stack frame */
3750         if(STACK_MODEL_LARGE)
3751           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3752         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3753
3754         if(STACK_MODEL_LARGE)
3755           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3756         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3757       }
3758     }
3759
3760     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3761           && sym->stack) {
3762
3763       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3764
3765       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3766       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3767       emitSKPC;
3768       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3769     }
3770           
3771     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3772       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3773         _G.useWreg = 0;
3774       else
3775         _G.useWreg = 1;
3776     } else
3777       _G.useWreg = 0;
3778
3779     /* if callee-save to be used for this function
3780      * then save the registers being used in this function */
3781 //    if (IFFUNC_CALLEESAVES(sym->type))
3782     if(strcmp(sym->name, "main")) {
3783       int i;
3784
3785         /* if any registers used */
3786         if (sym->regsUsed) {
3787                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3788
3789           if(!xinst) {
3790             /* save the registers used */
3791             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3792             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3793               if (bitVectBitValue(sym->regsUsed,i)) {
3794 #if 0
3795                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3796 #endif
3797                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3798                 _G.nRegsSaved++;
3799
3800                 if(!pic16_regWithIdx(i)->wasUsed) {
3801                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3802                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3803                   pic16_regWithIdx(i)->wasUsed = 1;
3804                 }
3805               }
3806             }
3807           } else {
3808             
3809             /* xinst */
3810             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3811             for(i=0;i<sym->regsUsed->size;i++) {
3812               if(bitVectBitValue(sym->regsUsed, i)) {
3813                 _G.nRegsSaved++;
3814               }
3815             }
3816                         
3817 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3818           }
3819
3820           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3821
3822         }
3823     }
3824         
3825     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3826 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3827 }
3828
3829 /*-----------------------------------------------------------------*/
3830 /* genEndFunction - generates epilogue for functions               */
3831 /*-----------------------------------------------------------------*/
3832 static void genEndFunction (iCode *ic)
3833 {
3834   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3835
3836     FENTRY;
3837
3838     if(IFFUNC_ISNAKED(sym->type)) {
3839       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3840       return;
3841     }
3842
3843     _G.stack_lat = 0;
3844
3845     /* add code for ISCRITICAL */
3846     if(IFFUNC_ISCRITICAL(sym->type)) {
3847       /* if critical function, turn on interrupts */
3848       
3849       /* TODO: add code here -- VR */
3850     }
3851     
3852 //    sym->regsUsed = _G.fregsUsed;
3853     
3854     /* now we need to restore the registers */
3855     /* if any registers used */
3856
3857     /* first restore registers that might be used for stack access */
3858     if(_G.sregsAllocSet) {
3859     regs *sr;
3860     
3861       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3862       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3863         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3864       }
3865     }
3866
3867     if (strcmp(sym->name, "main") && sym->regsUsed) {
3868       int i;
3869
3870         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3871         /* restore registers used */
3872         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3873         for ( i = sym->regsUsed->size; i >= 0; i--) {
3874           if (bitVectBitValue(sym->regsUsed,i)) {
3875             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3876             _G.nRegsSaved--;
3877           }
3878         }
3879         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3880     }
3881
3882       
3883
3884     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3885           && sym->stack) {
3886       if (sym->stack == 1) {
3887         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3888         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3889       } else {
3890         // we have to add more than one...
3891         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3892         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3893         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3894         emitSKPNC;
3895         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3896         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3897         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3898       }
3899     }
3900
3901     if(strcmp(sym->name, "main")) {
3902       if(0
3903         || !options.ommitFramePtr
3904 //        || sym->regsUsed
3905         || IFFUNC_ARGS(sym->type)
3906         || FUNC_HASSTACKPARM(sym->etype)
3907         ) {
3908         /* restore stack frame */
3909         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3910         if(STACK_MODEL_LARGE)
3911           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3912       }
3913     }
3914
3915     _G.useWreg = 0;
3916
3917     if (IFFUNC_ISISR(sym->type)) {
3918       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3919       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3920       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3921       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3922
3923       if(!FUNC_ISSHADOWREGS(sym->type)) {
3924         /* do not restore interrupt vector for WREG,STATUS,BSR
3925          * for high priority interrupt, see genFunction */
3926         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3927         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3928         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3929       }
3930 //      _G.interruptvector = 0;         /* sanity check */
3931
3932
3933       /* if debug then send end of function */
3934 /*      if (options.debug && currFunc)  */
3935       if (currFunc) {
3936         debugFile->writeEndFunction (currFunc, ic, 1);
3937       }
3938         
3939       if(_G.usefastretfie)
3940         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3941       else
3942         pic16_emitpcodeNULLop(POC_RETFIE);
3943
3944       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3945       
3946       _G.usefastretfie = 0;
3947       return;
3948     }
3949
3950     if (IFFUNC_ISCRITICAL(sym->type)) {
3951       pic16_emitcode("setb","ea");
3952     }
3953
3954     /* if debug then send end of function */
3955     if (currFunc) {
3956       debugFile->writeEndFunction (currFunc, ic, 1);
3957     }
3958
3959     /* insert code to restore stack frame, if user enabled it
3960      * and function is not main() */
3961          
3962
3963     pic16_emitpcodeNULLop(POC_RETURN);
3964
3965     /* Mark the end of a function */
3966     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3967 }
3968
3969
3970 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3971 {
3972   unsigned long lit=1;
3973   operand *op;
3974
3975     op = IC_LEFT(ic);
3976   
3977     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3978     if(AOP_TYPE(op) == AOP_LIT) {
3979       if(!IS_FLOAT(operandType( op ))) {
3980         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3981       } else {
3982         union {
3983           unsigned long lit_int;
3984           float lit_float;
3985         } info;
3986         
3987         /* take care if literal is a float */
3988         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3989         lit = info.lit_int;
3990       }
3991     }
3992
3993     if (AOP_TYPE(op) == AOP_LIT) {
3994       /* FIXME: broken for
3995        *   char __at(0x456) foo;
3996        *   return &foo;
3997        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3998       pic16_movLit2f(dest, (lit >> (8ul*offset)));
3999     } else if (AOP_TYPE(op) == AOP_PCODE
4000                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4001       /* char *s= "aaa"; return s; */
4002       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4003        *      that the generic pointer is interpreted correctly
4004        *      as referring to __code space, but this is fragile! */
4005       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4006       /* XXX: should check that dest != WREG */
4007       pic16_emitpcode(POC_MOVWF, dest);
4008     } else {
4009       if(dest->type == PO_WREG && (offset == 0)) {
4010         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4011         return;
4012       }
4013       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4014     }
4015 }
4016
4017 /*-----------------------------------------------------------------*/
4018 /* genRet - generate code for return statement                     */
4019 /*-----------------------------------------------------------------*/
4020 static void genRet (iCode *ic)
4021 {
4022   int size;
4023   operand *left;
4024
4025     FENTRY;
4026         /* if we have no return value then
4027          * just generate the "ret" */
4028         
4029         if (!IC_LEFT(ic)) 
4030                 goto jumpret;       
4031     
4032         /* we have something to return then
4033          * move the return value into place */
4034         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4035         size = AOP_SIZE(IC_LEFT(ic));
4036
4037         if(size <= 4) {
4038           if(size>3)
4039             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4040           
4041           if(size>2)
4042             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4043
4044           if(size>1)
4045             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4046           
4047           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4048
4049         } else {
4050                 /* >32-bits, setup stack and FSR0 */
4051                 while (size--) {
4052 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4053 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4054
4055                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4056
4057 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4058                         GpsuedoStkPtr++;
4059                 }
4060                         
4061                 /* setup FSR0 */
4062                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4063                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4064
4065                 if(STACK_MODEL_LARGE) {
4066                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4067                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4068                 } else {
4069                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4070                 }
4071         }
4072                                 
4073 #if 0
4074         /* old code, left here for reference -- VR */    
4075         while (size--) {
4076           char *l ;
4077
4078                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4079                         /* #NOCHANGE */
4080                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4081                         pic16_emitpcomment("push %s",l);
4082                         pushed++;
4083                 } else {
4084                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4085                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4086                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4087                         
4088                         if (strcmp(fReturn[offset],l)) {
4089                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4090                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4091                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4092                                 } else {
4093                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4094                                 }
4095                                 
4096                                 if(size) {
4097                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4098                                 }
4099                                 offset++;
4100                         }
4101                 }
4102         }    
4103
4104         if (pushed) {
4105                 while(pushed) {
4106                         pushed--;
4107                         if (strcmp(fReturn[pushed],"a"))
4108                                 pic16_emitcode("pop",fReturn[pushed]);
4109                         else
4110                                 pic16_emitcode("pop","acc");
4111                 }
4112         }
4113 #endif
4114
4115
4116         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4117     
4118 jumpret:
4119         /* generate a jump to the return label
4120          * if the next is not the return statement */
4121         if (!(ic->next && ic->next->op == LABEL
4122                 && IC_LABEL(ic->next) == returnLabel)) {
4123         
4124                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4125                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4126         }
4127 }
4128
4129 /*-----------------------------------------------------------------*/
4130 /* genLabel - generates a label                                    */
4131 /*-----------------------------------------------------------------*/
4132 static void genLabel (iCode *ic)
4133 {
4134   FENTRY;
4135
4136   /* special case never generate */
4137   if (IC_LABEL(ic) == entryLabel)
4138     return ;
4139
4140   pic16_emitpLabel(IC_LABEL(ic)->key);
4141 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4142 }
4143
4144 /*-----------------------------------------------------------------*/
4145 /* genGoto - generates a goto                                      */
4146 /*-----------------------------------------------------------------*/
4147 //tsd
4148 static void genGoto (iCode *ic)
4149 {
4150   FENTRY;
4151   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4152 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4153 }
4154
4155
4156 /*-----------------------------------------------------------------*/
4157 /* genMultbits :- multiplication of bits                           */
4158 /*-----------------------------------------------------------------*/
4159 static void genMultbits (operand *left, 
4160                          operand *right, 
4161                          operand *result)
4162 {
4163   FENTRY;
4164
4165   if(!pic16_sameRegs(AOP(result),AOP(right)))
4166     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4167
4168   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4169   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4170   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4171
4172 }
4173
4174
4175 /*-----------------------------------------------------------------*/
4176 /* genMultOneByte : 8 bit multiplication & division                */
4177 /*-----------------------------------------------------------------*/
4178 static void genMultOneByte (operand *left,
4179                             operand *right,
4180                             operand *result)
4181 {
4182
4183   FENTRY;
4184   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4185   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4186
4187   /* (if two literals, the value is computed before) */
4188   /* if one literal, literal on the right */
4189   if (AOP_TYPE(left) == AOP_LIT){
4190     operand *t = right;
4191     right = left;
4192     left = t;
4193   }
4194
4195         /* size is already checked in genMult == 1 */
4196 //      size = AOP_SIZE(result);
4197
4198         if (AOP_TYPE(right) == AOP_LIT){
4199                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4200                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4201                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4202                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4203         } else {
4204                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4205                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4206                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4207                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4208         }
4209         
4210         pic16_genMult8X8_8 (left, right,result);
4211 }
4212
4213 /*-----------------------------------------------------------------*/
4214 /* genMultOneWord : 16 bit multiplication                          */
4215 /*-----------------------------------------------------------------*/
4216 static void genMultOneWord (operand *left,
4217                             operand *right,
4218                             operand *result)
4219 {
4220   FENTRY;
4221   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4222   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4223
4224   /* (if two literals, the value is computed before)
4225    * if one literal, literal on the right */
4226   if (AOP_TYPE(left) == AOP_LIT){
4227     operand *t = right;
4228     right = left;
4229     left = t;
4230   }
4231
4232   /* size is checked already == 2 */
4233 //  size = AOP_SIZE(result);
4234
4235   if (AOP_TYPE(right) == AOP_LIT) {
4236     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4237       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4238       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4239       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4240   } else {
4241     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4242       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4243       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4244       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4245   }
4246         
4247   pic16_genMult16X16_16(left, right,result);
4248 }
4249
4250 /*-----------------------------------------------------------------*/
4251 /* genMultOneLong : 32 bit multiplication                          */
4252 /*-----------------------------------------------------------------*/
4253 static void genMultOneLong (operand *left,
4254                             operand *right,
4255                             operand *result)
4256 {
4257   FENTRY;
4258   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4259   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4260
4261   /* (if two literals, the value is computed before)
4262    * if one literal, literal on the right */
4263   if (AOP_TYPE(left) == AOP_LIT){
4264     operand *t = right;
4265     right = left;
4266     left = t;
4267   }
4268
4269   /* size is checked already == 4 */
4270 //  size = AOP_SIZE(result);
4271
4272   if (AOP_TYPE(right) == AOP_LIT) {
4273     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4274         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4275         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4276         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4277   } else {
4278     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4279         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4280         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4281         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4282   }
4283         
4284   pic16_genMult32X32_32(left, right,result);
4285 }
4286
4287
4288
4289 /*-----------------------------------------------------------------*/
4290 /* genMult - generates code for multiplication                     */
4291 /*-----------------------------------------------------------------*/
4292 static void genMult (iCode *ic)
4293 {
4294   operand *left = IC_LEFT(ic);
4295   operand *right = IC_RIGHT(ic);
4296   operand *result= IC_RESULT(ic);   
4297
4298     FENTRY;
4299         /* assign the amsops */
4300         pic16_aopOp (left,ic,FALSE);
4301         pic16_aopOp (right,ic,FALSE);
4302         pic16_aopOp (result,ic,TRUE);
4303
4304         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4305
4306         /* special cases first *
4307         * both are bits */
4308         if (AOP_TYPE(left) == AOP_CRY
4309                 && AOP_TYPE(right)== AOP_CRY) {
4310                 genMultbits(left,right,result);
4311           goto release ;
4312         }
4313
4314         /* if both are of size == 1 */
4315         if(AOP_SIZE(left) == 1
4316                 && AOP_SIZE(right) == 1) {
4317                 genMultOneByte(left,right,result);
4318           goto release ;
4319         }
4320
4321         /* if both are of size == 2 */
4322         if(AOP_SIZE(left) == 2
4323                 && AOP_SIZE(right) == 2) {
4324                 genMultOneWord(left, right, result);
4325           goto release;
4326         }
4327         
4328         /* if both are of size == 4 */
4329         if(AOP_SIZE(left) == 4
4330                 && AOP_SIZE(right) == 4) {
4331                 genMultOneLong(left, right, result);
4332           goto release;
4333         }
4334         
4335         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4336
4337
4338         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4339         /* should have been converted to function call */
4340         assert(0) ;
4341
4342 release :
4343         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4344         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4345         pic16_freeAsmop(result,NULL,ic,TRUE); 
4346 }
4347
4348 /*-----------------------------------------------------------------*/
4349 /* genDivbits :- division of bits                                  */
4350 /*-----------------------------------------------------------------*/
4351 static void genDivbits (operand *left, 
4352                         operand *right, 
4353                         operand *result)
4354 {
4355   char *l;
4356
4357     FENTRY;
4358     /* the result must be bit */    
4359     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4360     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4361
4362     MOVA(l);    
4363
4364     pic16_emitcode("div","ab");
4365     pic16_emitcode("rrc","a");
4366     pic16_aopPut(AOP(result),"c",0);
4367 }
4368
4369 /*-----------------------------------------------------------------*/
4370 /* genDivOneByte : 8 bit division                                  */
4371 /*-----------------------------------------------------------------*/
4372 static void genDivOneByte (operand *left,
4373                            operand *right,
4374                            operand *result)
4375 {
4376   sym_link *opetype = operandType(result);
4377   char *l ;
4378   symbol *lbl ;
4379   int size,offset;
4380
4381         /* result = divident / divisor
4382          * - divident may be a register or a literal,
4383          * - divisor may be a register or a literal,
4384          * so there are 3 cases (literal / literal is optimized
4385          * by the front-end) to handle.
4386          * In addition we must handle signed and unsigned, which
4387          * result in 6 final different cases -- VR */
4388
4389     FENTRY;
4390     
4391     size = AOP_SIZE(result) - 1;
4392     offset = 1;
4393     /* signed or unsigned */
4394     if (SPEC_USIGN(opetype)) {
4395       pCodeOp *pct1,    /* count */
4396                 *pct2,  /* reste */
4397                 *pct3;  /* temp */
4398       symbol *label1, *label2, *label3;;
4399
4400
4401         /* unsigned is easy */
4402
4403         pct1 = pic16_popGetTempReg(1);
4404         pct2 = pic16_popGetTempReg(1);
4405         pct3 = pic16_popGetTempReg(1);
4406         
4407         label1 = newiTempLabel(NULL);
4408         label2 = newiTempLabel(NULL);
4409         label3 = newiTempLabel(NULL);
4410
4411         /* the following algorithm is extracted from divuint.c */
4412
4413         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4414         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4415         
4416         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4417
4418         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4419         
4420         pic16_emitpLabel(label1->key);
4421         
4422         emitCLRC;
4423         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4424
4425
4426         emitCLRC;
4427         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4428         
4429
4430         emitSKPNC;
4431         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4432         
4433         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4434         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4435         
4436         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4437         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4438         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4439         
4440         pic16_emitpLabel( label3->key );
4441         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4442         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4443         
4444         
4445
4446         pic16_emitpLabel(label2->key);
4447         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4448         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4449         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4450         
4451         /* result is in wreg */
4452         if(AOP_TYPE(result) != AOP_ACC)
4453                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4454
4455         pic16_popReleaseTempReg( pct3, 1);
4456         pic16_popReleaseTempReg( pct2, 1);
4457         pic16_popReleaseTempReg( pct1, 1);
4458
4459         return ;
4460     }
4461
4462     /* signed is a little bit more difficult */
4463
4464     /* save the signs of the operands */
4465     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4466     MOVA(l);    
4467     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4468     pic16_emitcode("push","acc"); /* save it on the stack */
4469
4470     /* now sign adjust for both left & right */
4471     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4472     MOVA(l);       
4473     lbl = newiTempLabel(NULL);
4474     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4475     pic16_emitcode("cpl","a");   
4476     pic16_emitcode("inc","a");
4477     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4478     pic16_emitcode("mov","b,a");
4479
4480     /* sign adjust left side */
4481     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4482     MOVA(l);
4483
4484     lbl = newiTempLabel(NULL);
4485     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4486     pic16_emitcode("cpl","a");
4487     pic16_emitcode("inc","a");
4488     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4489
4490     /* now the division */
4491     pic16_emitcode("div","ab");
4492     /* we are interested in the lower order
4493     only */
4494     pic16_emitcode("mov","b,a");
4495     lbl = newiTempLabel(NULL);
4496     pic16_emitcode("pop","acc");   
4497     /* if there was an over flow we don't 
4498     adjust the sign of the result */
4499     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4500     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4501     CLRC;
4502     pic16_emitcode("clr","a");
4503     pic16_emitcode("subb","a,b");
4504     pic16_emitcode("mov","b,a");
4505     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4506
4507     /* now we are done */
4508     pic16_aopPut(AOP(result),"b",0);
4509     if(size > 0){
4510         pic16_emitcode("mov","c,b.7");
4511         pic16_emitcode("subb","a,acc");   
4512     }
4513     while (size--)
4514         pic16_aopPut(AOP(result),"a",offset++);
4515
4516 }
4517
4518 /*-----------------------------------------------------------------*/
4519 /* genDiv - generates code for division                            */
4520 /*-----------------------------------------------------------------*/
4521 static void genDiv (iCode *ic)
4522 {
4523     operand *left = IC_LEFT(ic);
4524     operand *right = IC_RIGHT(ic);
4525     operand *result= IC_RESULT(ic);   
4526
4527
4528         /* Division is a very lengthy algorithm, so it is better
4529          * to call support routines than inlining algorithm.
4530          * Division functions written here just in case someone
4531          * wants to inline and not use the support libraries -- VR */
4532
4533     FENTRY;
4534     
4535     /* assign the amsops */
4536     pic16_aopOp (left,ic,FALSE);
4537     pic16_aopOp (right,ic,FALSE);
4538     pic16_aopOp (result,ic,TRUE);
4539
4540     /* special cases first */
4541     /* both are bits */
4542     if (AOP_TYPE(left) == AOP_CRY &&
4543         AOP_TYPE(right)== AOP_CRY) {
4544         genDivbits(left,right,result);
4545         goto release ;
4546     }
4547
4548     /* if both are of size == 1 */
4549     if (AOP_SIZE(left) == 1 &&
4550         AOP_SIZE(right) == 1 ) {
4551         genDivOneByte(left,right,result);
4552         goto release ;
4553     }
4554
4555     /* should have been converted to function call */
4556     assert(0);
4557 release :
4558     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4559     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4560     pic16_freeAsmop(result,NULL,ic,TRUE); 
4561 }
4562
4563 /*-----------------------------------------------------------------*/
4564 /* genModbits :- modulus of bits                                   */
4565 /*-----------------------------------------------------------------*/
4566 static void genModbits (operand *left, 
4567                         operand *right, 
4568                         operand *result)
4569 {
4570   char *l;
4571
4572     FENTRY;  
4573     
4574     werror(W_POSSBUG2, __FILE__, __LINE__);
4575     /* the result must be bit */    
4576     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4577     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4578
4579     MOVA(l);       
4580
4581     pic16_emitcode("div","ab");
4582     pic16_emitcode("mov","a,b");
4583     pic16_emitcode("rrc","a");
4584     pic16_aopPut(AOP(result),"c",0);
4585 }
4586
4587 /*-----------------------------------------------------------------*/
4588 /* genModOneByte : 8 bit modulus                                   */
4589 /*-----------------------------------------------------------------*/
4590 static void genModOneByte (operand *left,
4591                            operand *right,
4592                            operand *result)
4593 {
4594   sym_link *opetype = operandType(result);
4595   char *l ;
4596   symbol *lbl ;
4597
4598     FENTRY;
4599     werror(W_POSSBUG2, __FILE__, __LINE__);
4600
4601     /* signed or unsigned */
4602     if (SPEC_USIGN(opetype)) {
4603         /* unsigned is easy */
4604         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4605         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4606         MOVA(l);    
4607         pic16_emitcode("div","ab");
4608         pic16_aopPut(AOP(result),"b",0);
4609         return ;
4610     }
4611
4612     /* signed is a little bit more difficult */
4613
4614     /* save the signs of the operands */
4615     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4616     MOVA(l);
4617
4618     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4619     pic16_emitcode("push","acc"); /* save it on the stack */
4620
4621     /* now sign adjust for both left & right */
4622     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4623     MOVA(l);
4624
4625     lbl = newiTempLabel(NULL);
4626     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4627     pic16_emitcode("cpl","a");   
4628     pic16_emitcode("inc","a");
4629     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4630     pic16_emitcode("mov","b,a"); 
4631
4632     /* sign adjust left side */
4633     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4634     MOVA(l);
4635
4636     lbl = newiTempLabel(NULL);
4637     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4638     pic16_emitcode("cpl","a");   
4639     pic16_emitcode("inc","a");
4640     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4641
4642     /* now the multiplication */
4643     pic16_emitcode("div","ab");
4644     /* we are interested in the lower order
4645     only */
4646     lbl = newiTempLabel(NULL);
4647     pic16_emitcode("pop","acc");   
4648     /* if there was an over flow we don't 
4649     adjust the sign of the result */
4650     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4651     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4652     CLRC ;
4653     pic16_emitcode("clr","a");
4654     pic16_emitcode("subb","a,b");
4655     pic16_emitcode("mov","b,a");
4656     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4657
4658     /* now we are done */
4659     pic16_aopPut(AOP(result),"b",0);
4660
4661 }
4662
4663 /*-----------------------------------------------------------------*/
4664 /* genMod - generates code for division                            */
4665 /*-----------------------------------------------------------------*/
4666 static void genMod (iCode *ic)
4667 {
4668   operand *left = IC_LEFT(ic);
4669   operand *right = IC_RIGHT(ic);
4670   operand *result= IC_RESULT(ic);  
4671
4672     FENTRY;
4673     
4674     /* assign the amsops */
4675     pic16_aopOp (left,ic,FALSE);
4676     pic16_aopOp (right,ic,FALSE);
4677     pic16_aopOp (result,ic,TRUE);
4678
4679     /* special cases first */
4680     /* both are bits */
4681     if (AOP_TYPE(left) == AOP_CRY &&
4682         AOP_TYPE(right)== AOP_CRY) {
4683         genModbits(left,right,result);
4684         goto release ;
4685     }
4686
4687     /* if both are of size == 1 */
4688     if (AOP_SIZE(left) == 1 &&
4689         AOP_SIZE(right) == 1 ) {
4690         genModOneByte(left,right,result);
4691         goto release ;
4692     }
4693
4694     /* should have been converted to function call */
4695     assert(0);
4696
4697 release :
4698     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4699     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4700     pic16_freeAsmop(result,NULL,ic,TRUE); 
4701 }
4702
4703 /*-----------------------------------------------------------------*/
4704 /* genIfxJump :- will create a jump depending on the ifx           */
4705 /*-----------------------------------------------------------------*/
4706 /*
4707   note: May need to add parameter to indicate when a variable is in bit space.
4708 */
4709 static void genIfxJump (iCode *ic, char *jval)
4710 {
4711   FENTRY;
4712   
4713     /* if true label then we jump if condition
4714     supplied is true */
4715     if ( IC_TRUE(ic) ) {
4716
4717         if(strcmp(jval,"a") == 0)
4718           emitSKPZ;
4719         else if (strcmp(jval,"c") == 0)
4720           emitSKPNC;
4721         else {
4722           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4723           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4724         }
4725
4726         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4727         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4728
4729     }
4730     else {
4731         /* false label is present */
4732         if(strcmp(jval,"a") == 0)
4733           emitSKPNZ;
4734         else if (strcmp(jval,"c") == 0)
4735           emitSKPC;
4736         else {
4737           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4738           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4739         }
4740
4741         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4742         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4743
4744     }
4745
4746
4747     /* mark the icode as generated */
4748     ic->generated = 1;
4749 }
4750
4751 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4752 {
4753   FENTRY;
4754   
4755     /* if true label then we jump if condition
4756     supplied is true */
4757     if ( IC_TRUE(ic) ) {
4758       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4759       pic16_emitpcode(POC_BTFSC, jop);
4760
4761       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4762       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4763
4764     } else {
4765       /* false label is present */
4766       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4767       pic16_emitpcode(POC_BTFSS, jop);
4768           
4769       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4770       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4771     }
4772
4773
4774     /* mark the icode as generated */
4775     ic->generated = 1;
4776 }
4777
4778 #if 0
4779 // not needed ATM
4780
4781 /*-----------------------------------------------------------------*/
4782 /* genSkip                                                         */
4783 /*-----------------------------------------------------------------*/
4784 static void genSkip(iCode *ifx,int status_bit)
4785 {
4786   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4787   if(!ifx)
4788     return;
4789
4790   if ( IC_TRUE(ifx) ) {
4791     switch(status_bit) {
4792     case 'z':
4793       emitSKPNZ;
4794       break;
4795
4796     case 'c':
4797       emitSKPNC;
4798       break;
4799
4800     case 'd':
4801       emitSKPDC;
4802       break;
4803
4804     }
4805
4806     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4807     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4808
4809   } else {
4810
4811     switch(status_bit) {
4812
4813     case 'z':
4814       emitSKPZ;
4815       break;
4816
4817     case 'c':
4818       emitSKPC;
4819       break;
4820
4821     case 'd':
4822       emitSKPDC;
4823       break;
4824     }
4825     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4826     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4827
4828   }
4829
4830 }
4831 #endif
4832
4833 /*-----------------------------------------------------------------*/
4834 /* genSkipc                                                        */
4835 /*-----------------------------------------------------------------*/
4836 static void genSkipc(resolvedIfx *rifx)
4837 {
4838   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4839   
4840   if(!rifx)
4841     return;
4842
4843   if(rifx->condition)
4844     emitSKPNC;
4845   else
4846     emitSKPC;
4847
4848   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4849   rifx->generated = 1;
4850 }
4851
4852 #if !(USE_SIMPLE_GENCMP)
4853 /*-----------------------------------------------------------------*/
4854 /* genSkipz2                                                       */
4855 /*-----------------------------------------------------------------*/
4856 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4857 {
4858   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4859   
4860   if(!rifx)
4861     return;
4862
4863   if( (rifx->condition ^ invert_condition) & 1)
4864     emitSKPZ;
4865   else
4866     emitSKPNZ;
4867
4868   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4869   rifx->generated = 1;
4870 }
4871 #endif
4872
4873 #if 0
4874 /*-----------------------------------------------------------------*/
4875 /* genSkipz                                                        */
4876 /*-----------------------------------------------------------------*/
4877 static void genSkipz(iCode *ifx, int condition)
4878 {
4879   if(!ifx)
4880     return;
4881
4882   if(condition)
4883     emitSKPNZ;
4884   else
4885     emitSKPZ;
4886
4887   if ( IC_TRUE(ifx) )
4888     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4889   else
4890     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4891
4892   if ( IC_TRUE(ifx) )
4893     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4894   else
4895     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4896
4897 }
4898 #endif
4899
4900 #if !(USE_SIMPLE_GENCMP)
4901 /*-----------------------------------------------------------------*/
4902 /* genSkipCond                                                     */
4903 /*-----------------------------------------------------------------*/
4904 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4905 {
4906   if(!rifx)
4907     return;
4908
4909   if(rifx->condition)
4910     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4911   else
4912     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4913
4914
4915   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4916   rifx->generated = 1;
4917 }
4918 #endif
4919
4920 #if 0
4921 /*-----------------------------------------------------------------*/
4922 /* genChkZeroes :- greater or less than comparison                 */
4923 /*     For each byte in a literal that is zero, inclusive or the   */
4924 /*     the corresponding byte in the operand with W                */
4925 /*     returns true if any of the bytes are zero                   */
4926 /*-----------------------------------------------------------------*/
4927 static int genChkZeroes(operand *op, int lit,  int size)
4928 {
4929
4930   int i;
4931   int flag =1;
4932
4933   while(size--) {
4934     i = (lit >> (size*8)) & 0xff;
4935
4936     if(i==0) {
4937       if(flag) 
4938         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4939       else
4940         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4941       flag = 0;
4942     }
4943   }
4944
4945   return (flag==0);
4946 }
4947 #endif
4948
4949
4950 /*-----------------------------------------------------------------*/
4951 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4952 /*                  aop (if it's NOT a literal) or from lit (if    */
4953 /*                  aop is a literal)                              */
4954 /*-----------------------------------------------------------------*/
4955 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4956   if (aop->type == AOP_LIT) {
4957     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4958   } else {
4959     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4960   }
4961 }
4962
4963 /*-----------------------------------------------------------------*/
4964 /* genCmp :- greater or less than comparison                       */
4965 /*-----------------------------------------------------------------*/
4966
4967 #if USE_SIMPLE_GENCMP           /* { */
4968
4969 /* genCmp performs a left < right comparison, stores
4970  * the outcome in result (if != NULL) and generates
4971  * control flow code for the ifx (if != NULL).
4972  *
4973  * This version leaves in sequences like
4974  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4975  * which should be optmized by the peephole
4976  * optimizer - RN 2005-01-01 */
4977 static void genCmp (operand *left,operand *right,
4978                     operand *result, iCode *ifx, int sign)
4979 {
4980   resolvedIfx rIfx;
4981   int size;
4982   int offs;
4983   symbol *templbl;
4984   operand *dummy;
4985   unsigned long lit;
4986   unsigned long mask;
4987   int performedLt;
4988
4989   FENTRY;
4990   
4991   assert (left && right);
4992   assert (AOP_SIZE(left) == AOP_SIZE(right));
4993
4994   size = AOP_SIZE(right) - 1;
4995   mask = (0x100UL << (size*8)) - 1;
4996   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4997   performedLt = 1;
4998   templbl = NULL;
4999   lit = 0;
5000   
5001   resolveIfx (&rIfx, ifx);
5002
5003   /* handle for special cases */
5004   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5005       return;
5006
5007   /**********************************************************************
5008    * handle bits - bit compares are promoted to int compares seemingly! *
5009    **********************************************************************/
5010 #if 0
5011   // THIS IS COMPLETELY UNTESTED!
5012   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5013     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5014     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5015     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5016
5017     emitSETC;
5018     // 1 < {0,1} is false --> clear C by skipping the next instruction
5019     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5020     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5021     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5022     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5023     emitCLRC; // only skipped for left=0 && right=1
5024
5025     goto correct_result_in_carry;
5026   } // if
5027 #endif
5028
5029   /*************************************************
5030    * make sure that left is register (or the like) *
5031    *************************************************/
5032   if (!isAOP_REGlike(left)) {
5033     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5034     assert (isAOP_LIT(left));
5035     assert (isAOP_REGlike(right));
5036     // swap left and right
5037     // left < right <==> right > left <==> (right >= left + 1)
5038     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5039
5040     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5041       // MAXVALUE < right? always false
5042       if (performedLt) emitCLRC; else emitSETC;
5043       goto correct_result_in_carry;
5044     } // if
5045
5046     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5047     // that's why we handled it above.
5048     lit++;
5049
5050     dummy = left;
5051     left = right;
5052     right = dummy;
5053
5054     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5055   } else if (isAOP_LIT(right)) {
5056     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5057   } // if
5058
5059   assert (isAOP_REGlike(left)); // left must be register or the like
5060   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5061
5062   /*************************************************
5063    * special cases go here                         *
5064    *************************************************/
5065
5066   if (isAOP_LIT(right)) {
5067     if (!sign) {
5068       // unsigned comparison to a literal
5069       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5070       if (lit == 0) {
5071         // unsigned left < 0? always false
5072         if (performedLt) emitCLRC; else emitSETC;
5073         goto correct_result_in_carry;
5074       }
5075     } else {
5076       // signed comparison to a literal
5077       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5078       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5079         // signed left < 0x80000000? always false
5080         if (performedLt) emitCLRC; else emitSETC;
5081         goto correct_result_in_carry;
5082       } else if (lit == 0) {
5083         // compare left < 0; set CARRY if SIGNBIT(left) is set
5084         if (performedLt) emitSETC; else emitCLRC;
5085         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5086         if (performedLt) emitCLRC; else emitSETC;
5087         goto correct_result_in_carry;
5088       }
5089     } // if (!sign)
5090   } // right is literal
5091
5092   /*************************************************
5093    * perform a general case comparison             *
5094    * make sure we get CARRY==1 <==> left >= right  *
5095    *************************************************/
5096   // compare most significant bytes
5097   //DEBUGpc ("comparing bytes at offset %d", size);
5098   if (!sign) {
5099     // unsigned comparison
5100     mov2w_regOrLit (AOP(right), lit, size);
5101     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5102   } else {
5103     // signed comparison
5104     // (add 2^n to both operands then perform an unsigned comparison)
5105     if (isAOP_LIT(right)) {
5106       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5107       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5108
5109       if (litbyte == 0x80) {
5110         // left >= 0x80 -- always true, but more bytes to come
5111         pic16_mov2w (AOP(left), size);
5112         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5113         emitSETC;
5114       } else {
5115         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5116         pic16_mov2w (AOP(left), size);
5117         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5118         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5119       } // if
5120     } else {
5121       /* using PRODL as a temporary register here */
5122       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5123       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5124       pic16_mov2w (AOP(left), size);
5125       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5126       pic16_emitpcode (POC_MOVWF, pctemp);
5127       pic16_mov2w (AOP(right), size);
5128       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5129       pic16_emitpcode (POC_SUBFW, pctemp);
5130       //pic16_popReleaseTempReg(pctemp, 1);
5131     }
5132   } // if (!sign)
5133
5134   // compare remaining bytes (treat as unsigned case from above)
5135   templbl = newiTempLabel ( NULL );
5136   offs = size;
5137   while (offs--) {
5138     //DEBUGpc ("comparing bytes at offset %d", offs);
5139     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5140     mov2w_regOrLit (AOP(right), lit, offs);
5141     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5142   } // while (offs)
5143   pic16_emitpLabel (templbl->key);
5144   goto result_in_carry;
5145
5146 result_in_carry:
5147   
5148   /****************************************************
5149    * now CARRY contains the result of the comparison: *
5150    * SUBWF sets CARRY iff                             *
5151    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5152    * (F=left, W=right)                                *
5153    ****************************************************/
5154
5155   if (performedLt) {
5156     if (result && AOP_TYPE(result) != AOP_CRY) {
5157       // value will be stored
5158       emitTOGC;
5159     } else {
5160       // value wil only be used in the following genSkipc()
5161       rIfx.condition ^= 1;
5162     }
5163   } // if
5164
5165 correct_result_in_carry:
5166
5167   // assign result to variable (if neccessary)
5168   if (result && AOP_TYPE(result) != AOP_CRY) {
5169     //DEBUGpc ("assign result");
5170     size = AOP_SIZE(result);
5171     while (size--) {
5172       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5173     } // while
5174     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5175   } // if (result)
5176
5177   // perform conditional jump
5178   if (ifx) {
5179     //DEBUGpc ("generate control flow");
5180     genSkipc (&rIfx);
5181     ifx->generated = 1;
5182   } // if
5183 }
5184
5185 #elif 1         /* } */
5186                 /* { */
5187       /* original code */
5188 static void genCmp (operand *left,operand *right,
5189                     operand *result, iCode *ifx, int sign)
5190 {
5191   int size; //, offset = 0 ;
5192   unsigned long lit = 0L,i = 0;
5193   resolvedIfx rFalseIfx;
5194   //  resolvedIfx rTrueIfx;
5195   symbol *truelbl;
5196   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5197 /*
5198   if(ifx) {
5199     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5200     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5201   }
5202 */
5203
5204   FENTRY;
5205   
5206   resolveIfx(&rFalseIfx,ifx);
5207   truelbl  = newiTempLabel(NULL);
5208   size = max(AOP_SIZE(left),AOP_SIZE(right));
5209
5210   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5211
5212 #define _swapp
5213
5214   /* if literal is on the right then swap with left */
5215   if ((AOP_TYPE(right) == AOP_LIT)) {
5216     operand *tmp = right ;
5217     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5218     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5219 #ifdef _swapp
5220
5221     lit = (lit - 1) & mask;
5222     right = left;
5223     left = tmp;
5224     rFalseIfx.condition ^= 1;
5225 #endif
5226
5227   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5228     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5229   }
5230
5231
5232   //if(IC_TRUE(ifx) == NULL)
5233   /* if left & right are bit variables */
5234   if (AOP_TYPE(left) == AOP_CRY &&
5235       AOP_TYPE(right) == AOP_CRY ) {
5236     assert (0 && "bit variables used in genCmp");
5237     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5238     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5239   } else {
5240     /* subtract right from left if at the
5241        end the carry flag is set then we know that
5242        left is greater than right */
5243
5244     symbol *lbl  = newiTempLabel(NULL);
5245
5246 #if 0
5247         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5248                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5249 #endif
5250
5251 #ifndef _swapp
5252     if(AOP_TYPE(right) == AOP_LIT) {
5253
5254       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5255
5256       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5257
5258       /* special cases */
5259
5260       if(lit == 0) {
5261
5262         if(sign != 0) 
5263           genSkipCond(&rFalseIfx,left,size-1,7);
5264         else 
5265           /* no need to compare to 0...*/
5266           /* NOTE: this is a de-generate compare that most certainly 
5267            *       creates some dead code. */
5268           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5269
5270         if(ifx) ifx->generated = 1;
5271         return;
5272
5273       }
5274       size--;
5275
5276       if(size == 0) {
5277         //i = (lit >> (size*8)) & 0xff;
5278         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5279         
5280         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5281
5282         i = ((0-lit) & 0xff);
5283         if(sign) {
5284           if( i == 0x81) { 
5285             /* lit is 0x7f, all signed chars are less than
5286              * this except for 0x7f itself */
5287             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5288             genSkipz2(&rFalseIfx,0);
5289           } else {
5290             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5291             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5292             genSkipc(&rFalseIfx);
5293           }
5294
5295         } else {
5296           if(lit == 1) {
5297             genSkipz2(&rFalseIfx,1);
5298           } else {
5299             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5300             genSkipc(&rFalseIfx);
5301           }
5302         }
5303
5304         if(ifx) ifx->generated = 1;
5305         return;
5306       }
5307
5308       /* chars are out of the way. now do ints and longs */
5309
5310
5311       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5312         
5313       /* special cases */
5314
5315       if(sign) {
5316
5317         if(lit == 0) {
5318           genSkipCond(&rFalseIfx,left,size,7);
5319           if(ifx) ifx->generated = 1;
5320           return;
5321         }
5322
5323         if(lit <0x100) {
5324           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5325
5326           //rFalseIfx.condition ^= 1;
5327           //genSkipCond(&rFalseIfx,left,size,7);
5328           //rFalseIfx.condition ^= 1;
5329
5330           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5331           if(rFalseIfx.condition)
5332             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5333           else
5334             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5335
5336           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5337           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5338           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5339
5340           while(size > 1)
5341             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5342
5343           if(rFalseIfx.condition) {
5344             emitSKPZ;
5345             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5346
5347           } else {
5348             emitSKPNZ;
5349           }
5350
5351           genSkipc(&rFalseIfx);
5352           pic16_emitpLabel(truelbl->key);
5353           if(ifx) ifx->generated = 1;
5354           return;
5355
5356         }
5357
5358         if(size == 1) {
5359
5360           if( (lit & 0xff) == 0) {
5361             /* lower byte is zero */
5362             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5363             i = ((lit >> 8) & 0xff) ^0x80;
5364             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5365             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5366             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5367             genSkipc(&rFalseIfx);
5368
5369
5370             if(ifx) ifx->generated = 1;
5371             return;
5372
5373           }
5374         } else {
5375           /* Special cases for signed longs */
5376           if( (lit & 0xffffff) == 0) {
5377             /* lower byte is zero */
5378             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5379             i = ((lit >> 8*3) & 0xff) ^0x80;
5380             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5381             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5382             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5383             genSkipc(&rFalseIfx);
5384
5385
5386             if(ifx) ifx->generated = 1;
5387             return;
5388
5389           }
5390
5391         }
5392
5393
5394         if(lit & (0x80 << (size*8))) {
5395           /* lit is negative */
5396           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5397
5398           //genSkipCond(&rFalseIfx,left,size,7);
5399
5400           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5401
5402           if(rFalseIfx.condition)
5403             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5404           else
5405             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5406
5407
5408         } else {
5409           /* lit is positive */
5410           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5411           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5412           if(rFalseIfx.condition)
5413             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5414           else
5415             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5416
5417         }
5418
5419         /*
5420           This works, but is only good for ints.
5421           It also requires a "known zero" register.
5422           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5423           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5424           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5425           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5426           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5427           genSkipc(&rFalseIfx);
5428
5429           pic16_emitpLabel(truelbl->key);
5430           if(ifx) ifx->generated = 1;
5431           return;
5432         **/
5433           
5434         /* There are no more special cases, so perform a general compare */
5435   
5436         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5437         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5438
5439         while(size--) {
5440
5441           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5442           emitSKPNZ;
5443           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5444         }
5445         //rFalseIfx.condition ^= 1;
5446         genSkipc(&rFalseIfx);
5447
5448         pic16_emitpLabel(truelbl->key);
5449
5450         if(ifx) ifx->generated = 1;
5451         return;
5452
5453
5454       }
5455
5456
5457       /* sign is out of the way. So now do an unsigned compare */
5458       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5459
5460
5461       /* General case - compare to an unsigned literal on the right.*/
5462
5463       i = (lit >> (size*8)) & 0xff;
5464       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5465       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5466       while(size--) {
5467         i = (lit >> (size*8)) & 0xff;
5468
5469         if(i) {
5470           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5471           emitSKPNZ;
5472           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5473         } else {
5474           /* this byte of the lit is zero, 
5475            *if it's not the last then OR in the variable */
5476           if(size)
5477             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5478         }
5479       }
5480
5481
5482       pic16_emitpLabel(lbl->key);
5483 //      pic16_emitpLabel(truelbl->key);
5484       //if(emitFinalCheck)
5485       genSkipc(&rFalseIfx);
5486       if(sign)
5487         pic16_emitpLabel(truelbl->key);
5488
5489       if(ifx) ifx->generated = 1;
5490       return;
5491
5492
5493     }
5494 #endif  // _swapp
5495
5496     if(AOP_TYPE(left) == AOP_LIT) {
5497       //symbol *lbl = newiTempLabel(NULL);
5498
5499       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5500
5501
5502       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5503
5504       /* Special cases */
5505       if((lit == 0) && (sign == 0)){
5506
5507         size--;
5508         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5509         while(size) 
5510           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5511
5512         genSkipz2(&rFalseIfx,0);
5513         if(ifx) ifx->generated = 1;
5514         return;
5515       }
5516
5517       if(size==1) {
5518         /* Special cases */
5519         lit &= 0xff;
5520         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5521           /* degenerate compare can never be true */
5522           if(rFalseIfx.condition == 0)
5523             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5524
5525           if(ifx) ifx->generated = 1;
5526           return;
5527         }
5528
5529         if(sign) {
5530           /* signed comparisons to a literal byte */
5531
5532           int lp1 = (lit+1) & 0xff;
5533
5534           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5535           switch (lp1) {
5536           case 0:
5537             rFalseIfx.condition ^= 1;
5538             genSkipCond(&rFalseIfx,right,0,7);
5539             break;
5540           case 0x7f:
5541             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5542             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5543             genSkipz2(&rFalseIfx,1);
5544             break;
5545           default:
5546             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5547             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5548             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5549             rFalseIfx.condition ^= 1;
5550             genSkipc(&rFalseIfx);
5551             break;
5552           }
5553         } else {
5554           /* unsigned comparisons to a literal byte */
5555
5556           switch(lit & 0xff ) {
5557           case 0:
5558             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5559             genSkipz2(&rFalseIfx,0);
5560             break;
5561           case 0x7f:
5562             rFalseIfx.condition ^= 1;
5563             genSkipCond(&rFalseIfx,right,0,7);
5564             break;
5565
5566           default:
5567             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5568             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5569             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5570             rFalseIfx.condition ^= 1;
5571             if (AOP_TYPE(result) == AOP_CRY)
5572               genSkipc(&rFalseIfx);
5573             else {
5574               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5575               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5576             }         
5577             break;
5578           }
5579         }
5580
5581         if(ifx) ifx->generated = 1;
5582         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5583                 goto check_carry;
5584         return;
5585
5586       } else {
5587
5588         /* Size is greater than 1 */
5589
5590         if(sign) {
5591           int lp1 = lit+1;
5592
5593           size--;
5594
5595           if(lp1 == 0) {
5596             /* this means lit = 0xffffffff, or -1 */
5597
5598
5599             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5600             rFalseIfx.condition ^= 1;
5601             genSkipCond(&rFalseIfx,right,size,7);
5602             if(ifx) ifx->generated = 1;
5603
5604             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5605               goto check_carry;
5606
5607             return;
5608           }
5609
5610           if(lit == 0) {
5611             int s = size;
5612
5613             if(rFalseIfx.condition) {
5614               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5615               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5616             }
5617
5618             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5619             while(size--)
5620               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5621
5622
5623             emitSKPZ;
5624             if(rFalseIfx.condition) {
5625               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5626               pic16_emitpLabel(truelbl->key);
5627             }else {
5628               rFalseIfx.condition ^= 1;
5629               genSkipCond(&rFalseIfx,right,s,7);
5630             }
5631
5632             if(ifx) ifx->generated = 1;
5633
5634             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5635               goto check_carry;
5636
5637             return;
5638           }
5639
5640           if((size == 1) &&  (0 == (lp1&0xff))) {
5641             /* lower byte of signed word is zero */
5642             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5643             i = ((lp1 >> 8) & 0xff) ^0x80;
5644             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5645             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5646             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5647
5648             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5649               emitTOGC;
5650               if(ifx) ifx->generated = 1;
5651               goto check_carry;
5652             } else {
5653               rFalseIfx.condition ^= 1;
5654               genSkipc(&rFalseIfx);
5655               if(ifx) ifx->generated = 1;
5656             }
5657
5658             return;
5659           }
5660
5661           if(lit & (0x80 << (size*8))) {
5662             /* Lit is less than zero */
5663             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5664             //rFalseIfx.condition ^= 1;
5665             //genSkipCond(&rFalseIfx,left,size,7);
5666             //rFalseIfx.condition ^= 1;
5667             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5668             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5669
5670             if(rFalseIfx.condition)
5671               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5672             else
5673               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5674
5675
5676           } else {
5677             /* Lit is greater than or equal to zero */
5678             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5679             //rFalseIfx.condition ^= 1;
5680             //genSkipCond(&rFalseIfx,right,size,7);
5681             //rFalseIfx.condition ^= 1;
5682
5683             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5684             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5685
5686             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5687             if(rFalseIfx.condition)
5688               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5689             else
5690               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5691
5692           }
5693
5694           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5695           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5696
5697           while(size--) {
5698
5699             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5700             emitSKPNZ;
5701             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5702           }
5703           rFalseIfx.condition ^= 1;
5704           //rFalseIfx.condition = 1;
5705           genSkipc(&rFalseIfx);
5706
5707           pic16_emitpLabel(truelbl->key);
5708
5709           if(ifx) ifx->generated = 1;
5710
5711
5712           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5713             goto check_carry;
5714
5715           return;
5716           // end of if (sign)
5717         } else {
5718
5719           /* compare word or long to an unsigned literal on the right.*/
5720
5721
5722           size--;
5723           if(lit < 0xff) {
5724             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5725             switch (lit) {
5726             case 0:
5727               break; /* handled above */
5728 /*
5729             case 0xff:
5730               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5731               while(size--)
5732                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5733               genSkipz2(&rFalseIfx,0);
5734               break;
5735 */
5736             default:
5737               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5738               while(--size)
5739                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5740
5741               emitSKPZ;
5742               if(rFalseIfx.condition)
5743                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5744               else
5745                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5746
5747
5748               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5749               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5750
5751               rFalseIfx.condition ^= 1;
5752               genSkipc(&rFalseIfx);
5753             }
5754
5755             pic16_emitpLabel(truelbl->key);
5756
5757             if(ifx) ifx->generated = 1;
5758
5759             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5760               goto check_carry;
5761
5762             return;
5763           }
5764
5765
5766           lit++;
5767           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5768           i = (lit >> (size*8)) & 0xff;
5769
5770           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5771           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5772
5773           while(size--) {
5774             i = (lit >> (size*8)) & 0xff;
5775
5776             if(i) {
5777               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5778               emitSKPNZ;
5779               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5780             } else {
5781               /* this byte of the lit is zero, 
5782                * if it's not the last then OR in the variable */
5783               if(size)
5784                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5785             }
5786           }
5787
5788
5789           pic16_emitpLabel(lbl->key);
5790
5791           rFalseIfx.condition ^= 1;
5792
5793           genSkipc(&rFalseIfx);
5794         }
5795
5796         if(sign)
5797           pic16_emitpLabel(truelbl->key);
5798         if(ifx) ifx->generated = 1;
5799
5800             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5801               goto check_carry;
5802
5803         return;
5804       }
5805     }
5806     /* Compare two variables */
5807
5808     DEBUGpic16_emitcode(";sign","%d",sign);
5809
5810     size--;
5811     if(sign) {
5812       /* Sigh. thus sucks... */
5813       if(size) {
5814         pCodeOp *pctemp;
5815         
5816         pctemp = pic16_popGetTempReg(1);
5817         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5818         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5819         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5820         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5821         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5822         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5823         pic16_popReleaseTempReg(pctemp, 1);
5824       } else {
5825         /* Signed char comparison */
5826         /* Special thanks to Nikolai Golovchenko for this snippet */
5827         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5828         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5829         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5830         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5831         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5832         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5833
5834         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5835         genSkipc(&rFalseIfx);
5836           
5837         if(ifx) ifx->generated = 1;
5838
5839             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5840               goto check_carry;
5841
5842         return;
5843       }
5844
5845     } else {
5846
5847       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5848       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5849     }
5850
5851
5852     /* The rest of the bytes of a multi-byte compare */
5853     while (size) {
5854
5855       emitSKPZ;
5856       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5857       size--;
5858
5859       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5860       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5861
5862
5863     }
5864
5865     pic16_emitpLabel(lbl->key);
5866
5867     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5868     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5869         (AOP_TYPE(result) == AOP_REG)) {
5870       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5871       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5872     } else {
5873       genSkipc(&rFalseIfx);
5874     }         
5875     //genSkipc(&rFalseIfx);
5876     if(ifx) ifx->generated = 1;
5877
5878
5879             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5880               goto check_carry;
5881
5882     return;
5883
5884   }
5885
5886 check_carry:
5887   if ((AOP_TYPE(result) != AOP_CRY) 
5888         && AOP_SIZE(result)) {
5889     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5890
5891     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5892
5893     pic16_outBitC(result);
5894   } else {
5895     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5896     /* if the result is used in the next
5897        ifx conditional branch then generate
5898        code a little differently */
5899     if (ifx )
5900       genIfxJump (ifx,"c");
5901     else
5902       pic16_outBitC(result);
5903     /* leave the result in acc */
5904   }
5905
5906 }
5907
5908 #elif 0 /* VR version of genCmp() */    /* } else { */
5909
5910 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5911 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5912         operand *result, int offset, int invert_op)
5913 {
5914   /* add code here */
5915   
5916   /* check condition, > or < ?? */
5917   if(rIfx->condition != 0)invert_op ^= 1;
5918   
5919   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5920
5921   if(!ifx)invert_op ^= 1;
5922
5923   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5924       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5925   
5926   /* do selection */
5927   if(!invert_op)return POC_CPFSGT;
5928   else return POC_CPFSLT;
5929 }
5930
5931 static int compareAopfirstpass=1;
5932
5933 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5934             operand *oper, int offset, operand *result,
5935             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5936             symbol *tlbl)
5937 {
5938   int op;
5939   symbol *truelbl;
5940
5941   /* invert if there is a result to be loaded, in order to fit,
5942    * SETC/CLRC sequence */
5943   if(AOP_SIZE(result))invert_op ^= 1;
5944
5945 //  if(sign && !offset)invert_op ^= 1;
5946   
5947 //  if(sign)invert_op ^= 1;
5948   
5949   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5950
5951   if(AOP_SIZE(result) && compareAopfirstpass) {
5952     if(!ifx) {
5953       if(pcop2)
5954         pic16_emitpcode(POC_SETF, pcop2);
5955       else
5956         emitSETC;
5957     } else {
5958       if(pcop2)
5959         pic16_emitpcode(POC_CLRF, pcop2);
5960       else
5961         emitCLRC;
5962     }
5963   }
5964
5965   compareAopfirstpass = 0;
5966
5967       /* there is a bug when comparing operands with size > 1,
5968        * because higher bytes can be equal and test should be performed
5969        * to the next lower byte, current algorithm, considers operands
5970        * inequal in these cases! -- VR 20041107 */
5971
5972     
5973   if(pcop)
5974     pic16_emitpcode(op, pcop);
5975   else
5976     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5977
5978
5979   if((!sign || !offset) && AOP_SIZE(result)) {
5980     if(!ifx) {
5981       if(pcop2)
5982         pic16_emitpcode(POC_CLRF, pcop2);
5983         else
5984         emitCLRC;
5985     } else {
5986       if(pcop2)
5987         pic16_emitpcode(POC_SETF, pcop2);
5988       else
5989         emitSETC;
5990     }
5991     
5992     /* don't emit final branch (offset == 0) */
5993     if(offset) {
5994
5995       if(pcop2)
5996         pic16_emitpcode(POC_RRCF, pcop2);
5997
5998       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5999     }
6000   } else {
6001     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6002       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6003             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6004
6005       truelbl = newiTempLabel( NULL );
6006       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6007       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6008         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6009       else
6010         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6011       pic16_emitpLabel(truelbl->key);
6012     } else {
6013       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6014     }
6015   }
6016 }
6017
6018 static void genCmp (operand *left, operand *right,
6019                     operand *result, iCode *ifx, int sign)
6020 {
6021   int size, cmpop=1;
6022   long lit = 0L;
6023   resolvedIfx rFalseIfx;
6024   symbol *falselbl, *tlbl;
6025
6026     FENTRY;
6027     
6028     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6029
6030     resolveIfx(&rFalseIfx, ifx);
6031     size = max(AOP_SIZE(left), AOP_SIZE(right));
6032     
6033     /* if left & right are bit variables */
6034     if(AOP_TYPE(left) == AOP_CRY
6035       && AOP_TYPE(right) == AOP_CRY ) {
6036
6037         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6038         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6039         
6040         werror(W_POSSBUG2, __FILE__, __LINE__);
6041         exit(-1);
6042     }
6043     
6044     /* if literal is on the right then swap with left */
6045     if((AOP_TYPE(right) == AOP_LIT)) {
6046       operand *tmp = right ;
6047 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6048
6049         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6050
6051 //      lit = (lit - 1) & mask;
6052         right = left;
6053         left = tmp;
6054         rFalseIfx.condition ^= 1;               /* reverse compare */
6055     } else
6056     if ((AOP_TYPE(left) == AOP_LIT)) {
6057       /* float compares are handled by support functions */
6058       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6059     }
6060
6061     /* actual comparing algorithm */
6062 //    size = AOP_SIZE( right );
6063
6064     falselbl = newiTempLabel( NULL );
6065     if(AOP_TYPE(left) == AOP_LIT) {
6066       /* compare to literal */
6067       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6068       
6069       if(sign) {
6070         pCodeOp *pct, *pct2;
6071         symbol *tlbl1;
6072
6073         /* signed compare */
6074         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6075
6076         /* using PRODL:PRODH as a temporary register here */
6077         pct = pic16_popCopyReg(&pic16_pc_prodl);
6078         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6079         tlbl = newiTempLabel( NULL );
6080         
6081         /* first compare signs:
6082          *  a. if both are positive, compare just like unsigned
6083          *  b. if both are negative, invert cmpop, compare just like unsigned
6084          *  c. if different signs, determine the result directly */
6085
6086         size--;
6087
6088 #if 1
6089         /* { */
6090         tlbl1 = newiTempLabel( NULL );
6091 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6092
6093         if(lit > 0) {
6094
6095           /* literal is zero or positive:
6096            *  a. if carry is zero, too, continue compare,
6097            *  b. if carry is set, then continue depending on cmpop ^ condition:
6098            *    1. '<' return false (literal < variable),
6099            *    2. '>' return true (literal > variable) */
6100 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6101           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6102           
6103           
6104           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6105           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6106         } else 
6107         if(lit < 0) {
6108           
6109           /* literal is negative:
6110            *  a. if carry is set, too, continue compare,
6111            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6112            *    1. '<' return true (literal < variable),
6113            *    2. '>' return false (literal > variable) */
6114 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6115           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6116           
6117           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6118           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6119         }
6120 #if 1
6121         else {
6122           /* lit == 0 */
6123           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6124           
6125           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6126           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6127         }
6128 #endif
6129         
6130         
6131         pic16_emitpLabel( tlbl1->key );
6132 #endif  /* } */
6133
6134         compareAopfirstpass=1;
6135 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6136 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6137 //        pic16_emitpcode(POC_MOVWF, pct);
6138
6139 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6140         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6141 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6142         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6143
6144         /* generic case */        
6145           while( size-- ) {
6146 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6147 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6148 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6149 //            pic16_emitpcode(POC_MOVWF, pct);
6150
6151 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6152             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6153             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6154 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6155 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6156           }
6157         
6158         if(ifx)ifx->generated = 1;
6159
6160         if(AOP_SIZE(result)) {
6161           pic16_emitpLabel(tlbl->key);
6162           pic16_emitpLabel(falselbl->key);
6163           pic16_outBitOp( result, pct2 );
6164         } else {
6165           pic16_emitpLabel(tlbl->key);
6166         }
6167       } else {
6168
6169         /* unsigned compare */      
6170         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6171     
6172         compareAopfirstpass=1;
6173         while(size--) {
6174           
6175           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6176           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6177
6178         }
6179         if(ifx)ifx->generated = 1;
6180
6181         if(AOP_SIZE(result)) {
6182           pic16_emitpLabel(falselbl->key);
6183           pic16_outBitC( result );
6184         }
6185
6186       }
6187     } else {
6188       /* compare registers */
6189       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6190
6191
6192       if(sign) {
6193         pCodeOp *pct, *pct2;
6194         
6195         /* signed compare */
6196         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6197
6198         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6199         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6200         tlbl = newiTempLabel( NULL );
6201         
6202         compareAopfirstpass=1;
6203
6204         size--;
6205         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6206 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6207         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6208         pic16_emitpcode(POC_MOVWF, pct);
6209
6210         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6211 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6212         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6213
6214         /* WREG already holds left + 0x80 */
6215         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6216         
6217         while( size-- ) {
6218           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6219 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6220           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6221           pic16_emitpcode(POC_MOVWF, pct);
6222                 
6223           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6224 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6225           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6226
6227           /* WREG already holds left + 0x80 */
6228           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6229 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6230         }
6231         
6232         if(ifx)ifx->generated = 1;
6233
6234         if(AOP_SIZE(result)) {
6235           pic16_emitpLabel(tlbl->key);
6236           pic16_emitpLabel(falselbl->key);
6237           pic16_outBitOp( result, pct2 );
6238         } else {
6239           pic16_emitpLabel(tlbl->key);
6240         }
6241
6242       } else {
6243         /* unsigned compare */      
6244         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6245
6246         compareAopfirstpass=1;
6247         while(size--) {
6248           
6249           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6250           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6251
6252         }
6253
6254         if(ifx)ifx->generated = 1;
6255         if(AOP_SIZE(result)) {
6256
6257           pic16_emitpLabel(falselbl->key);
6258           pic16_outBitC( result );
6259         }
6260
6261       }
6262     }
6263 }
6264
6265 #endif  /* } */
6266
6267
6268
6269 /*-----------------------------------------------------------------*/
6270 /* genCmpGt :- greater than comparison                             */
6271 /*-----------------------------------------------------------------*/
6272 static void genCmpGt (iCode *ic, iCode *ifx)
6273 {
6274   operand *left, *right, *result;
6275   sym_link *letype , *retype;
6276   int sign ;
6277
6278     FENTRY;
6279     
6280     left = IC_LEFT(ic);
6281     right= IC_RIGHT(ic);
6282     result = IC_RESULT(ic);
6283
6284     letype = getSpec(operandType(left));
6285     retype =getSpec(operandType(right));
6286     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6287     /* assign the amsops */
6288     pic16_aopOp (left,ic,FALSE);
6289     pic16_aopOp (right,ic,FALSE);
6290     pic16_aopOp (result,ic,TRUE);
6291
6292     genCmp(right, left, result, ifx, sign);
6293
6294     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6295     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6296     pic16_freeAsmop(result,NULL,ic,TRUE); 
6297 }
6298
6299 /*-----------------------------------------------------------------*/
6300 /* genCmpLt - less than comparisons                                */
6301 /*-----------------------------------------------------------------*/
6302 static void genCmpLt (iCode *ic, iCode *ifx)
6303 {
6304   operand *left, *right, *result;
6305   sym_link *letype , *retype;
6306   int sign ;
6307
6308     FENTRY;
6309
6310     left = IC_LEFT(ic);
6311     right= IC_RIGHT(ic);
6312     result = IC_RESULT(ic);
6313
6314     letype = getSpec(operandType(left));
6315     retype =getSpec(operandType(right));
6316     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6317
6318     /* assign the amsops */
6319     pic16_aopOp (left,ic,FALSE);
6320     pic16_aopOp (right,ic,FALSE);
6321     pic16_aopOp (result,ic,TRUE);
6322
6323     genCmp(left, right, result, ifx, sign);
6324
6325     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6326     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6327     pic16_freeAsmop(result,NULL,ic,TRUE); 
6328 }
6329
6330 #if 0
6331 // not needed ATM
6332 // FIXME reenable literal optimisation when the pic16 port is stable
6333
6334 /*-----------------------------------------------------------------*/
6335 /* genc16bit2lit - compare a 16 bit value to a literal             */
6336 /*-----------------------------------------------------------------*/
6337 static void genc16bit2lit(operand *op, int lit, int offset)
6338 {
6339   int i;
6340
6341   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6342   if( (lit&0xff) == 0) 
6343     i=1;
6344   else
6345     i=0;
6346
6347   switch( BYTEofLONG(lit,i)) { 
6348   case 0:
6349     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6350     break;
6351   case 1:
6352     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6353     break;
6354   case 0xff:
6355     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6356     break;
6357   default:
6358     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6359     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6360   }
6361
6362   i ^= 1;
6363
6364   switch( BYTEofLONG(lit,i)) { 
6365   case 0:
6366     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6367     break;
6368   case 1:
6369     emitSKPNZ;
6370     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6371     break;
6372   case 0xff:
6373     emitSKPNZ;
6374     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6375     break;
6376   default:
6377     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6378     emitSKPNZ;
6379     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6380
6381   }
6382
6383 }
6384 #endif
6385
6386 #if 0
6387 // not needed ATM
6388 /*-----------------------------------------------------------------*/
6389 /* gencjneshort - compare and jump if not equal                    */
6390 /*-----------------------------------------------------------------*/
6391 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6392 {
6393   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6394   int offset = 0;
6395   int res_offset = 0;  /* the result may be a different size then left or right */
6396   int res_size = AOP_SIZE(result);
6397   resolvedIfx rIfx;
6398   symbol *lbl, *lbl_done;
6399
6400   unsigned long lit = 0L;
6401   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6402
6403   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6404   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6405   if(result)
6406     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6407   resolveIfx(&rIfx,ifx);
6408   lbl =  newiTempLabel(NULL);
6409   lbl_done =  newiTempLabel(NULL);
6410
6411
6412   /* if the left side is a literal or 
6413      if the right is in a pointer register and left 
6414      is not */
6415   if ((AOP_TYPE(left) == AOP_LIT) || 
6416       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6417     operand *t = right;
6418     right = left;
6419     left = t;
6420   }
6421   if(AOP_TYPE(right) == AOP_LIT)
6422     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6423
6424   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6425     preserve_result = 1;
6426
6427   if(result && !preserve_result)
6428     {
6429       int i;
6430       for(i = 0; i < AOP_SIZE(result); i++)
6431         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6432     }
6433
6434
6435   /* if the right side is a literal then anything goes */
6436   if (AOP_TYPE(right) == AOP_LIT &&
6437       AOP_TYPE(left) != AOP_DIR ) {
6438     switch(size) {
6439     case 2:
6440       genc16bit2lit(left, lit, 0);
6441       emitSKPZ;
6442       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6443       break;
6444     default:
6445       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6446       while (size--) {
6447         if(lit & 0xff) {
6448           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6449           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6450         } else {
6451           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6452         }
6453
6454         emitSKPZ;
6455         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6456         offset++;
6457         if(res_offset < res_size-1)
6458           res_offset++;
6459         lit >>= 8;
6460       }
6461       break;
6462     }
6463   }
6464
6465   /* if the right side is in a register or in direct space or
6466      if the left is a pointer register & right is not */    
6467   else if (AOP_TYPE(right) == AOP_REG ||
6468            AOP_TYPE(right) == AOP_DIR || 
6469            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6470            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6471     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6472     int lbl_key = lbl->key;
6473
6474     if(result) {
6475       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6476       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6477     }else {
6478       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6479       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6480               __FUNCTION__,__LINE__);
6481       return;
6482     }
6483    
6484 /*     switch(size) { */
6485 /*     case 2: */
6486 /*       genc16bit2lit(left, lit, 0); */
6487 /*       emitSKPNZ; */
6488 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6489 /*       break; */
6490 /*     default: */
6491     while (size--) {
6492       int emit_skip=1;
6493       if((AOP_TYPE(left) == AOP_DIR) && 
6494          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6495
6496         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6497         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6498
6499       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6500             
6501         switch (lit & 0xff) {
6502         case 0:
6503           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6504           break;
6505         case 1:
6506           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6507           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6508           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6509           emit_skip=0;
6510           break;
6511         case 0xff:
6512           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6513           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6514           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6515           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6516           emit_skip=0;
6517           break;
6518         default:
6519           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6520           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6521         }
6522         lit >>= 8;
6523
6524       } else {
6525         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6526       }
6527       if(emit_skip) {
6528         if(AOP_TYPE(result) == AOP_CRY) {
6529           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6530           if(rIfx.condition)
6531             emitSKPNZ;
6532           else
6533             emitSKPZ;
6534           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6535         } else {
6536           /* fix me. probably need to check result size too */
6537           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6538           if(rIfx.condition)
6539             emitSKPZ;
6540           else
6541             emitSKPNZ;
6542           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6543           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6544         }
6545         if(ifx)
6546           ifx->generated=1;
6547       }
6548       emit_skip++;
6549       offset++;
6550       if(res_offset < res_size-1)
6551         res_offset++;
6552     }
6553 /*       break; */
6554 /*     } */
6555   } else if(AOP_TYPE(right) == AOP_REG &&
6556             AOP_TYPE(left) != AOP_DIR){
6557
6558     while(size--) {
6559       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6560       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6561       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6562       if(rIfx.condition)
6563         emitSKPNZ;
6564       else
6565         emitSKPZ;
6566       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6567       offset++;
6568       if(res_offset < res_size-1)
6569         res_offset++;
6570     }
6571       
6572   }else{
6573     /* right is a pointer reg need both a & b */
6574     while(size--) {
6575       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6576       if(strcmp(l,"b"))
6577         pic16_emitcode("mov","b,%s",l);
6578       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6579       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6580       offset++;
6581     }
6582   }
6583
6584   if(result && preserve_result)
6585     {
6586       int i;
6587       for(i = 0; i < AOP_SIZE(result); i++)
6588         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6589     }
6590
6591   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6592
6593   if(result && preserve_result)
6594     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6595
6596   if(!rIfx.condition)
6597     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6598
6599   pic16_emitpLabel(lbl->key);
6600
6601   if(result && preserve_result)
6602     {
6603       int i;
6604       for(i = 0; i < AOP_SIZE(result); i++)
6605         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6606
6607       pic16_emitpLabel(lbl_done->key);
6608    }
6609
6610   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6611
6612   if(ifx)
6613     ifx->generated = 1;
6614 }
6615 #endif
6616
6617 #if 0
6618 /*-----------------------------------------------------------------*/
6619 /* gencjne - compare and jump if not equal                         */
6620 /*-----------------------------------------------------------------*/
6621 static void gencjne(operand *left, operand *right, iCode *ifx)
6622 {
6623     symbol *tlbl  = newiTempLabel(NULL);
6624
6625     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6626     gencjneshort(left, right, lbl);
6627
6628     pic16_emitcode("mov","a,%s",one);
6629     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6630     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6631     pic16_emitcode("clr","a");
6632     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6633
6634     pic16_emitpLabel(lbl->key);
6635     pic16_emitpLabel(tlbl->key);
6636
6637 }
6638 #endif
6639
6640
6641 /*-----------------------------------------------------------------*/
6642 /* is_LitOp - check if operand has to be treated as literal        */
6643 /*-----------------------------------------------------------------*/
6644 static bool is_LitOp(operand *op)
6645 {
6646   return ((AOP_TYPE(op) == AOP_LIT)
6647       || ( (AOP_TYPE(op) == AOP_PCODE)
6648           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6649               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6650 }
6651
6652 /*-----------------------------------------------------------------*/
6653 /* is_LitAOp - check if operand has to be treated as literal        */
6654 /*-----------------------------------------------------------------*/
6655 static bool is_LitAOp(asmop *aop)
6656 {
6657   return ((aop->type == AOP_LIT)
6658       || ( (aop->type == AOP_PCODE)
6659           && ( (aop->aopu.pcop->type == PO_LITERAL)
6660               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6661 }
6662
6663
6664
6665 /*-----------------------------------------------------------------*/
6666 /* genCmpEq - generates code for equal to                          */
6667 /*-----------------------------------------------------------------*/
6668 static void genCmpEq (iCode *ic, iCode *ifx)
6669 {
6670   operand *left, *right, *result;
6671   symbol *falselbl = newiTempLabel(NULL);
6672   symbol *donelbl = newiTempLabel(NULL);
6673
6674   int preserve_result = 0;
6675   int generate_result = 0;
6676   int i=0;
6677   unsigned long lit = -1;
6678
6679   FENTRY;
6680   
6681   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6682   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6683   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6684  
6685   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6686
6687   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6688     {
6689       werror(W_POSSBUG2, __FILE__, __LINE__);
6690       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6691       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6692       goto release;
6693     }
6694
6695   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6696     {
6697       operand *tmp = right ;
6698       right = left;
6699       left = tmp;
6700     }
6701
6702   if (AOP_TYPE(right) == AOP_LIT) {
6703     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6704   }
6705
6706   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6707     preserve_result = 1;
6708
6709   if(result && AOP_SIZE(result))
6710     generate_result = 1;
6711
6712   if(generate_result && !preserve_result)
6713     {
6714       for(i = 0; i < AOP_SIZE(result); i++)
6715         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6716     }
6717
6718   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6719   for(i=0; i < AOP_SIZE(left); i++)
6720     {
6721       if(AOP_TYPE(left) != AOP_ACC)
6722         {
6723           if(is_LitOp(left))
6724             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6725           else
6726             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6727         }
6728       if(is_LitOp(right)) {
6729         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6730           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6731         }
6732       } else
6733         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6734
6735       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6736     }
6737
6738   // result == true
6739
6740   if(generate_result && preserve_result)
6741     {
6742       for(i = 0; i < AOP_SIZE(result); i++)
6743         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6744     }
6745
6746   if(generate_result)
6747     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6748
6749   if(generate_result && preserve_result)
6750     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6751
6752   if(ifx && IC_TRUE(ifx))
6753     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6754
6755   if(ifx && IC_FALSE(ifx))
6756     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6757
6758   pic16_emitpLabel(falselbl->key);
6759
6760   // result == false
6761
6762   if(ifx && IC_FALSE(ifx))
6763     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6764
6765   if(generate_result && preserve_result)
6766     {
6767       for(i = 0; i < AOP_SIZE(result); i++)
6768         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6769     }
6770
6771   pic16_emitpLabel(donelbl->key);
6772
6773   if(ifx)
6774     ifx->generated = 1;
6775
6776 release:
6777   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6778   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6779   pic16_freeAsmop(result,NULL,ic,TRUE);
6780
6781 }
6782
6783
6784 #if 0
6785 // old version kept for reference
6786
6787 /*-----------------------------------------------------------------*/
6788 /* genCmpEq - generates code for equal to                          */
6789 /*-----------------------------------------------------------------*/
6790 static void genCmpEq (iCode *ic, iCode *ifx)
6791 {
6792     operand *left, *right, *result;
6793     unsigned long lit = 0L;
6794     int size,offset=0;
6795     symbol *falselbl  = newiTempLabel(NULL);
6796
6797
6798     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6799
6800     if(ifx)
6801       DEBUGpic16_emitcode ("; ifx is non-null","");
6802     else
6803       DEBUGpic16_emitcode ("; ifx is null","");
6804
6805     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6806     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6807     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6808
6809     size = max(AOP_SIZE(left),AOP_SIZE(right));
6810
6811     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6812
6813     /* if literal, literal on the right or 
6814     if the right is in a pointer register and left 
6815     is not */
6816     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6817         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6818       operand *tmp = right ;
6819       right = left;
6820       left = tmp;
6821     }
6822
6823
6824     if(ifx && !AOP_SIZE(result)){
6825         symbol *tlbl;
6826         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6827         /* if they are both bit variables */
6828         if (AOP_TYPE(left) == AOP_CRY &&
6829             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6830                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6831             if(AOP_TYPE(right) == AOP_LIT){
6832                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6833                 if(lit == 0L){
6834                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6835                     pic16_emitcode("cpl","c");
6836                 } else if(lit == 1L) {
6837                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6838                 } else {
6839                     pic16_emitcode("clr","c");
6840                 }
6841                 /* AOP_TYPE(right) == AOP_CRY */
6842             } else {
6843                 symbol *lbl = newiTempLabel(NULL);
6844                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6845                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6846                 pic16_emitcode("cpl","c");
6847                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6848             }
6849             /* if true label then we jump if condition
6850             supplied is true */
6851             tlbl = newiTempLabel(NULL);
6852             if ( IC_TRUE(ifx) ) {
6853                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6854                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6855             } else {
6856                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6857                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6858             }
6859             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6860
6861                 {
6862                 /* left and right are both bit variables, result is carry */
6863                         resolvedIfx rIfx;
6864               
6865                         resolveIfx(&rIfx,ifx);
6866
6867                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6868                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6869                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6870                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6871                         genSkipz2(&rIfx,0);
6872                 }
6873         } else {
6874
6875                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6876
6877                         /* They're not both bit variables. Is the right a literal? */
6878                         if(AOP_TYPE(right) == AOP_LIT) {
6879                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6880             
6881                         switch(size) {
6882
6883                                 case 1:
6884                                         switch(lit & 0xff) {
6885                                                 case 1:
6886                                                                 if ( IC_TRUE(ifx) ) {
6887                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6888                                                                         emitSKPNZ;
6889                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6890                                                                 } else {
6891                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6892                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6893                                                                 }
6894                                                                 break;
6895                                                 case 0xff:
6896                                                                 if ( IC_TRUE(ifx) ) {
6897                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6898                                                                         emitSKPNZ;
6899                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6900                                                                 } else {
6901                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6902                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6903                                                                 }
6904                                                                 break;
6905                                                 default:
6906                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6907                                                                 if(lit)
6908                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6909                                                                 genSkip(ifx,'z');
6910                                         } // switch lit
6911
6912
6913                                         /* end of size == 1 */
6914                                         break;
6915               
6916                                 case 2:
6917                                         genc16bit2lit(left,lit,offset);
6918                                         genSkip(ifx,'z');
6919                                         break;
6920                                         /* end of size == 2 */
6921
6922                                 default:
6923                                         /* size is 4 */
6924                                         if(lit==0) {
6925                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6926                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6927                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6928                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6929                                                 genSkip(ifx,'z');
6930                                         } else {
6931                                                 /* search for patterns that can be optimized */
6932
6933                                                 genc16bit2lit(left,lit,0);
6934                                                 lit >>= 16;
6935                                                 if(lit) {
6936                                                                 if(IC_TRUE(ifx))
6937                                                                 emitSKPZ; // if hi word unequal
6938                                                                 else
6939                                                                 emitSKPNZ; // if hi word equal
6940                                                                 // fail early
6941                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6942                                                         genc16bit2lit(left,lit,2);
6943                                                         genSkip(ifx,'z');
6944                                                 } else {
6945                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6946                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6947                                                         genSkip(ifx,'z');
6948                                                 }
6949                                         }
6950                                                 pic16_emitpLabel(falselbl->key);
6951                                                 break;
6952
6953                         } // switch size
6954           
6955                         ifx->generated = 1;
6956                         goto release ;
6957             
6958
6959           } else if(AOP_TYPE(right) == AOP_CRY ) {
6960             /* we know the left is not a bit, but that the right is */
6961             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6962             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6963                       pic16_popGet(AOP(right),offset));
6964             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6965
6966             /* if the two are equal, then W will be 0 and the Z bit is set
6967              * we could test Z now, or go ahead and check the high order bytes if
6968              * the variable we're comparing is larger than a byte. */
6969
6970             while(--size)
6971               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6972
6973             if ( IC_TRUE(ifx) ) {
6974               emitSKPNZ;
6975               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6976               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6977             } else {
6978               emitSKPZ;
6979               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6980               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6981             }
6982
6983           } else {
6984             /* They're both variables that are larger than bits */
6985             int s = size;
6986
6987             tlbl = newiTempLabel(NULL);
6988
6989             while(size--) {
6990               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6991               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6992
6993               if ( IC_TRUE(ifx) ) {
6994                 if(size) {
6995                   emitSKPZ;
6996                 
6997                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6998
6999                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7000                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7001                 } else {
7002                   emitSKPNZ;
7003
7004                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7005
7006
7007                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7008                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7009                 }
7010               } else {
7011                 emitSKPZ;
7012
7013                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7014
7015                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7016                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7017               }
7018               offset++;
7019             }
7020             if(s>1 && IC_TRUE(ifx)) {
7021               pic16_emitpLabel(tlbl->key);
7022               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7023             }
7024           }
7025         }
7026         /* mark the icode as generated */
7027         ifx->generated = 1;
7028         goto release ;
7029     }
7030
7031     /* if they are both bit variables */
7032     if (AOP_TYPE(left) == AOP_CRY &&
7033         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7034         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7035         if(AOP_TYPE(right) == AOP_LIT){
7036             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7037             if(lit == 0L){
7038                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7039                 pic16_emitcode("cpl","c");
7040             } else if(lit == 1L) {
7041                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7042             } else {
7043                 pic16_emitcode("clr","c");
7044             }
7045             /* AOP_TYPE(right) == AOP_CRY */
7046         } else {
7047             symbol *lbl = newiTempLabel(NULL);
7048             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7049             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7050             pic16_emitcode("cpl","c");
7051             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7052         }
7053         /* c = 1 if egal */
7054         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7055             pic16_outBitC(result);
7056             goto release ;
7057         }
7058         if (ifx) {
7059             genIfxJump (ifx,"c");
7060             goto release ;
7061         }
7062         /* if the result is used in an arithmetic operation
7063         then put the result in place */
7064         pic16_outBitC(result);
7065     } else {
7066       
7067       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7068       gencjne(left,right,result,ifx);
7069 /*
7070       if(ifx) 
7071         gencjne(left,right,newiTempLabel(NULL));
7072       else {
7073         if(IC_TRUE(ifx)->key)
7074           gencjne(left,right,IC_TRUE(ifx)->key);
7075         else
7076           gencjne(left,right,IC_FALSE(ifx)->key);
7077         ifx->generated = 1;
7078         goto release ;
7079       }
7080       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7081         pic16_aopPut(AOP(result),"a",0);
7082         goto release ;
7083       }
7084
7085       if (ifx) {
7086         genIfxJump (ifx,"a");
7087         goto release ;
7088       }
7089 */
7090       /* if the result is used in an arithmetic operation
7091          then put the result in place */
7092 /*
7093       if (AOP_TYPE(result) != AOP_CRY) 
7094         pic16_outAcc(result);
7095 */
7096       /* leave the result in acc */
7097     }
7098
7099 release:
7100     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7101     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7102     pic16_freeAsmop(result,NULL,ic,TRUE);
7103 }
7104 #endif
7105
7106 /*-----------------------------------------------------------------*/
7107 /* ifxForOp - returns the icode containing the ifx for operand     */
7108 /*-----------------------------------------------------------------*/
7109 static iCode *ifxForOp ( operand *op, iCode *ic )
7110 {
7111   FENTRY2;
7112
7113     /* if true symbol then needs to be assigned */
7114     if (IS_TRUE_SYMOP(op))
7115         return NULL ;
7116
7117     /* if this has register type condition and
7118     the next instruction is ifx with the same operand
7119     and live to of the operand is upto the ifx only then */
7120     if (ic->next
7121         && ic->next->op == IFX
7122         && IC_COND(ic->next)->key == op->key
7123         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7124         ) {
7125                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7126           return ic->next;
7127     }
7128
7129     /*
7130     if (ic->next &&
7131         ic->next->op == IFX &&
7132         IC_COND(ic->next)->key == op->key) {
7133       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7134       return ic->next;
7135     }
7136     */
7137
7138     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7139     if (ic->next &&
7140         ic->next->op == IFX)
7141       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7142
7143     if (ic->next &&
7144         ic->next->op == IFX &&
7145         IC_COND(ic->next)->key == op->key) {
7146       DEBUGpic16_emitcode ("; "," key is okay");
7147       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7148                            OP_SYMBOL(op)->liveTo,
7149                            ic->next->seq);
7150     }
7151
7152 #if 0
7153     /* the code below is completely untested
7154      * it just allows ulong2fs.c compile -- VR */
7155          
7156     ic = ic->next;
7157     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7158                                         __FILE__, __FUNCTION__, __LINE__);
7159         
7160     /* if this has register type condition and
7161     the next instruction is ifx with the same operand
7162     and live to of the operand is upto the ifx only then */
7163     if (ic->next &&
7164         ic->next->op == IFX &&
7165         IC_COND(ic->next)->key == op->key &&
7166         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7167         return ic->next;
7168
7169     if (ic->next &&
7170         ic->next->op == IFX &&
7171         IC_COND(ic->next)->key == op->key) {
7172       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7173       return ic->next;
7174     }
7175
7176     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7177                                         __FILE__, __FUNCTION__, __LINE__);
7178
7179 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7180 #endif
7181
7182     return NULL;
7183 }
7184 /*-----------------------------------------------------------------*/
7185 /* genAndOp - for && operation                                     */
7186 /*-----------------------------------------------------------------*/
7187 static void genAndOp (iCode *ic)
7188 {
7189   operand *left,*right, *result;
7190 /*     symbol *tlbl; */
7191
7192     FENTRY;
7193
7194     /* note here that && operations that are in an
7195     if statement are taken away by backPatchLabels
7196     only those used in arthmetic operations remain */
7197     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7198     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7199     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7200
7201     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7202
7203     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7204     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7205     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7206
7207     /* if both are bit variables */
7208 /*     if (AOP_TYPE(left) == AOP_CRY && */
7209 /*         AOP_TYPE(right) == AOP_CRY ) { */
7210 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7211 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7212 /*         pic16_outBitC(result); */
7213 /*     } else { */
7214 /*         tlbl = newiTempLabel(NULL); */
7215 /*         pic16_toBoolean(left);     */
7216 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7217 /*         pic16_toBoolean(right); */
7218 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7219 /*         pic16_outBitAcc(result); */
7220 /*     } */
7221
7222     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7223     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7224     pic16_freeAsmop(result,NULL,ic,TRUE);
7225 }
7226
7227
7228 /*-----------------------------------------------------------------*/
7229 /* genOrOp - for || operation                                      */
7230 /*-----------------------------------------------------------------*/
7231 /*
7232   tsd pic port -
7233   modified this code, but it doesn't appear to ever get called
7234 */
7235
7236 static void genOrOp (iCode *ic)
7237 {
7238   operand *left,*right, *result;
7239   symbol *tlbl;
7240
7241     FENTRY;  
7242
7243   /* note here that || operations that are in an
7244     if statement are taken away by backPatchLabels
7245     only those used in arthmetic operations remain */
7246     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7247     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7248     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7249
7250     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7251
7252     /* if both are bit variables */
7253     if (AOP_TYPE(left) == AOP_CRY &&
7254         AOP_TYPE(right) == AOP_CRY ) {
7255       pic16_emitcode("clrc","");
7256       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7257                AOP(left)->aopu.aop_dir,
7258                AOP(left)->aopu.aop_dir);
7259       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7260                AOP(right)->aopu.aop_dir,
7261                AOP(right)->aopu.aop_dir);
7262       pic16_emitcode("setc","");
7263
7264     } else {
7265         tlbl = newiTempLabel(NULL);
7266         pic16_toBoolean(left);
7267         emitSKPZ;
7268         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7269         pic16_toBoolean(right);
7270         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7271
7272         pic16_outBitAcc(result);
7273     }
7274
7275     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7276     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7277     pic16_freeAsmop(result,NULL,ic,TRUE);            
7278 }
7279
7280 /*-----------------------------------------------------------------*/
7281 /* isLiteralBit - test if lit == 2^n                               */
7282 /*-----------------------------------------------------------------*/
7283 static int isLiteralBit(unsigned long lit)
7284 {
7285     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7286     0x100L,0x200L,0x400L,0x800L,
7287     0x1000L,0x2000L,0x4000L,0x8000L,
7288     0x10000L,0x20000L,0x40000L,0x80000L,
7289     0x100000L,0x200000L,0x400000L,0x800000L,
7290     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7291     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7292     int idx;
7293     
7294     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7295     for(idx = 0; idx < 32; idx++)
7296         if(lit == pw[idx])
7297             return idx+1;
7298     return 0;
7299 }
7300
7301 /*-----------------------------------------------------------------*/
7302 /* continueIfTrue -                                                */
7303 /*-----------------------------------------------------------------*/
7304 static void continueIfTrue (iCode *ic)
7305 {
7306   FENTRY;
7307   if(IC_TRUE(ic))
7308     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7309   ic->generated = 1;
7310 }
7311
7312 /*-----------------------------------------------------------------*/
7313 /* jmpIfTrue -                                                     */
7314 /*-----------------------------------------------------------------*/
7315 static void jumpIfTrue (iCode *ic)
7316 {
7317   FENTRY;
7318   if(!IC_TRUE(ic))
7319     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7320   ic->generated = 1;
7321 }
7322
7323 /*-----------------------------------------------------------------*/
7324 /* jmpTrueOrFalse -                                                */
7325 /*-----------------------------------------------------------------*/
7326 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7327 {
7328   // ugly but optimized by peephole
7329   FENTRY;
7330   if(IC_TRUE(ic)){
7331     symbol *nlbl = newiTempLabel(NULL);
7332       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7333       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7334       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7335       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7336   } else {
7337     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7338     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7339   }
7340   ic->generated = 1;
7341 }
7342
7343 /*-----------------------------------------------------------------*/
7344 /* genAnd  - code for and                                          */
7345 /*-----------------------------------------------------------------*/
7346 static void genAnd (iCode *ic, iCode *ifx)
7347 {
7348   operand *left, *right, *result;
7349   int size, offset=0;  
7350   unsigned long lit = 0L;
7351   int bytelit = 0;
7352   resolvedIfx rIfx;
7353
7354     FENTRY;
7355     
7356   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7357   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7358   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7359
7360   resolveIfx(&rIfx,ifx);
7361
7362   /* if left is a literal & right is not then exchange them */
7363   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7364       AOP_NEEDSACC(left)) {
7365     operand *tmp = right ;
7366     right = left;
7367     left = tmp;
7368   }
7369
7370   /* if result = right then exchange them */
7371   if(pic16_sameRegs(AOP(result),AOP(right))){
7372     operand *tmp = right ;
7373     right = left;
7374     left = tmp;
7375   }
7376
7377   /* if right is bit then exchange them */
7378   if (AOP_TYPE(right) == AOP_CRY &&
7379       AOP_TYPE(left) != AOP_CRY){
7380     operand *tmp = right ;
7381     right = left;
7382     left = tmp;
7383   }
7384   if(AOP_TYPE(right) == AOP_LIT)
7385     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7386
7387   size = AOP_SIZE(result);
7388
7389   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7390
7391   // if(bit & yy)
7392   // result = bit & yy;
7393   if (AOP_TYPE(left) == AOP_CRY){
7394     // c = bit & literal;
7395     if(AOP_TYPE(right) == AOP_LIT){
7396       if(lit & 1) {
7397         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7398           // no change
7399           goto release;
7400         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7401       } else {
7402         // bit(result) = 0;
7403         if(size && (AOP_TYPE(result) == AOP_CRY)){
7404           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7405           goto release;
7406         }
7407         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7408           jumpIfTrue(ifx);
7409           goto release;
7410         }
7411         pic16_emitcode("clr","c");
7412       }
7413     } else {
7414       if (AOP_TYPE(right) == AOP_CRY){
7415         // c = bit & bit;
7416         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7417         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7418       } else {
7419         // c = bit & val;
7420         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7421         // c = lsb
7422         pic16_emitcode("rrc","a");
7423         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7424       }
7425     }
7426     // bit = c
7427     // val = c
7428     if(size)
7429       pic16_outBitC(result);
7430     // if(bit & ...)
7431     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7432       genIfxJump(ifx, "c");           
7433     goto release ;
7434   }
7435
7436   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7437   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7438   if((AOP_TYPE(right) == AOP_LIT) &&
7439      (AOP_TYPE(result) == AOP_CRY) &&
7440      (AOP_TYPE(left) != AOP_CRY)){
7441     int posbit = isLiteralBit(lit);
7442     /* left &  2^n */
7443     if(posbit){
7444       posbit--;
7445       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7446       // bit = left & 2^n
7447       if(size)
7448         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7449       // if(left &  2^n)
7450       else{
7451         if(ifx){
7452 /*
7453           if(IC_TRUE(ifx)) {
7454             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7455             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7456           } else {
7457             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7458             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7459           }
7460 */
7461         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7462         size = AOP_SIZE(left);
7463
7464         {
7465           int bp = posbit, ofs=0;
7466           
7467             while(bp > 7) {
7468               bp -= 8;
7469               ofs++;
7470             }
7471
7472           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7473                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7474
7475         }
7476 /*
7477           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7478                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7479 */
7480           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7481           
7482           ifx->generated = 1;
7483         }
7484         goto release;
7485       }
7486     } else {
7487       symbol *tlbl = newiTempLabel(NULL);
7488       int sizel = AOP_SIZE(left);
7489
7490       if(size)
7491         emitSETC;
7492
7493       while(sizel--) {
7494         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7495
7496           /* patch provided by Aaron Colwell */
7497           if((posbit = isLiteralBit(bytelit)) != 0) {
7498               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7499                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7500                                                 (posbit-1),0, PO_GPR_REGISTER));
7501
7502               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7503 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7504           } else {
7505               if (bytelit == 0xff) {
7506                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7507                    * a peephole could optimize it out -- VR */
7508                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7509               } else {
7510                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7511                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7512               }
7513
7514               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7515                             pic16_popGetLabel(tlbl->key));
7516           }
7517         
7518 #if 0
7519           /* old code, left here for reference -- VR 09/2004 */
7520           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7521           // byte ==  2^n ?
7522           if((posbit = isLiteralBit(bytelit)) != 0)
7523             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7524           else{
7525             if(bytelit != 0x0FFL)
7526               pic16_emitcode("anl","a,%s",
7527                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7528             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7529           }
7530 #endif
7531         }
7532         offset++;
7533       }
7534       // bit = left & literal
7535       if(size) {
7536         emitCLRC;
7537         pic16_emitpLabel(tlbl->key);
7538       }
7539       // if(left & literal)
7540       else {
7541         if(ifx) {
7542           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7543           ifx->generated = 1;
7544         }
7545         pic16_emitpLabel(tlbl->key);
7546         goto release;
7547       }
7548     }
7549
7550     pic16_outBitC(result);
7551     goto release ;
7552   }
7553
7554   /* if left is same as result */
7555   if(pic16_sameRegs(AOP(result),AOP(left))){
7556     int know_W = -1;
7557     for(;size--; offset++,lit>>=8) {
7558       if(AOP_TYPE(right) == AOP_LIT){
7559         switch(lit & 0xff) {
7560         case 0x00:
7561           /*  and'ing with 0 has clears the result */
7562 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7563           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7564           break;
7565         case 0xff:
7566           /* and'ing with 0xff is a nop when the result and left are the same */
7567           break;
7568
7569         default:
7570           {
7571             int p = pic16_my_powof2( (~lit) & 0xff );
7572             if(p>=0) {
7573               /* only one bit is set in the literal, so use a bcf instruction */
7574 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7575               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7576
7577             } else {
7578               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7579               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7580               if(know_W != (lit&0xff))
7581                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7582               know_W = lit &0xff;
7583               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7584             }
7585           }    
7586         }
7587       } else {
7588         if (AOP_TYPE(left) == AOP_ACC) {
7589           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7590         } else {                    
7591           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7592           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7593
7594         }
7595       }
7596     }
7597
7598   } else {
7599     // left & result in different registers
7600     if(AOP_TYPE(result) == AOP_CRY){
7601       // result = bit
7602       // if(size), result in bit
7603       // if(!size && ifx), conditional oper: if(left & right)
7604       symbol *tlbl = newiTempLabel(NULL);
7605       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7606       if(size)
7607         pic16_emitcode("setb","c");
7608       while(sizer--){
7609         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7610         pic16_emitcode("anl","a,%s",
7611                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7612         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7613         offset++;
7614       }
7615       if(size){
7616         CLRC;
7617         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7618         pic16_outBitC(result);
7619       } else if(ifx)
7620         jmpTrueOrFalse(ifx, tlbl);
7621     } else {
7622       for(;(size--);offset++) {
7623         // normal case
7624         // result = left & right
7625         if(AOP_TYPE(right) == AOP_LIT){
7626           int t = (lit >> (offset*8)) & 0x0FFL;
7627           switch(t) { 
7628           case 0x00:
7629             pic16_emitcode("clrf","%s",
7630                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7631             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7632             break;
7633           case 0xff:
7634             pic16_emitcode("movf","%s,w",
7635                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7636             pic16_emitcode("movwf","%s",
7637                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7638             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7639             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7640             break;
7641           default:
7642             pic16_emitcode("movlw","0x%x",t);
7643             pic16_emitcode("andwf","%s,w",
7644                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7645             pic16_emitcode("movwf","%s",
7646                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7647               
7648             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7649             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7650             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7651           }
7652           continue;
7653         }
7654
7655         if (AOP_TYPE(left) == AOP_ACC) {
7656           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7657           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7658         } else {
7659           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7660           pic16_emitcode("andwf","%s,w",
7661                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7662           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7663           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7664         }
7665         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7666         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7667       }
7668     }
7669   }
7670
7671   release :
7672     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7673   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7674   pic16_freeAsmop(result,NULL,ic,TRUE);     
7675 }
7676
7677 /*-----------------------------------------------------------------*/
7678 /* genOr  - code for or                                            */
7679 /*-----------------------------------------------------------------*/
7680 static void genOr (iCode *ic, iCode *ifx)
7681 {
7682     operand *left, *right, *result;
7683     int size, offset=0;
7684     unsigned long lit = 0L;
7685
7686     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7687
7688     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7689     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7690     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7691
7692     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7693
7694     /* if left is a literal & right is not then exchange them */
7695     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7696         AOP_NEEDSACC(left)) {
7697         operand *tmp = right ;
7698         right = left;
7699         left = tmp;
7700     }
7701
7702     /* if result = right then exchange them */
7703     if(pic16_sameRegs(AOP(result),AOP(right))){
7704         operand *tmp = right ;
7705         right = left;
7706         left = tmp;
7707     }
7708
7709     /* if right is bit then exchange them */
7710     if (AOP_TYPE(right) == AOP_CRY &&
7711         AOP_TYPE(left) != AOP_CRY){
7712         operand *tmp = right ;
7713         right = left;
7714         left = tmp;
7715     }
7716
7717     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7718
7719     if(AOP_TYPE(right) == AOP_LIT)
7720         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7721
7722     size = AOP_SIZE(result);
7723
7724     // if(bit | yy)
7725     // xx = bit | yy;
7726     if (AOP_TYPE(left) == AOP_CRY){
7727         if(AOP_TYPE(right) == AOP_LIT){
7728             // c = bit & literal;
7729             if(lit){
7730                 // lit != 0 => result = 1
7731                 if(AOP_TYPE(result) == AOP_CRY){
7732                   if(size)
7733                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7734                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7735                   //     AOP(result)->aopu.aop_dir,
7736                   //     AOP(result)->aopu.aop_dir);
7737                     else if(ifx)
7738                         continueIfTrue(ifx);
7739                     goto release;
7740                 }
7741             } else {
7742                 // lit == 0 => result = left
7743                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7744                     goto release;
7745                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7746             }
7747         } else {
7748             if (AOP_TYPE(right) == AOP_CRY){
7749               if(pic16_sameRegs(AOP(result),AOP(left))){
7750                 // c = bit | bit;
7751                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7752                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7753                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7754
7755                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7756                          AOP(result)->aopu.aop_dir,
7757                          AOP(result)->aopu.aop_dir);
7758                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7759                          AOP(right)->aopu.aop_dir,
7760                          AOP(right)->aopu.aop_dir);
7761                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7762                          AOP(result)->aopu.aop_dir,
7763                          AOP(result)->aopu.aop_dir);
7764               } else {
7765                 if( AOP_TYPE(result) == AOP_ACC) {
7766                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7767                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7768                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7769                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7770
7771                 } else {
7772
7773                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),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_BSF,   pic16_popGet(AOP(result),0));
7777
7778                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7779                                  AOP(result)->aopu.aop_dir,
7780                                  AOP(result)->aopu.aop_dir);
7781                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7782                                  AOP(right)->aopu.aop_dir,
7783                                  AOP(right)->aopu.aop_dir);
7784                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7785                                  AOP(left)->aopu.aop_dir,
7786                                  AOP(left)->aopu.aop_dir);
7787                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7788                                  AOP(result)->aopu.aop_dir,
7789                                  AOP(result)->aopu.aop_dir);
7790                 }
7791               }
7792             } else {
7793                 // c = bit | val;
7794                 symbol *tlbl = newiTempLabel(NULL);
7795                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7796
7797
7798                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7799                 if( AOP_TYPE(right) == AOP_ACC) {
7800                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7801                   emitSKPNZ;
7802                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7803                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7804                 }
7805
7806
7807
7808                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7809                     pic16_emitcode(";XXX setb","c");
7810                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7811                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7812                 pic16_toBoolean(right);
7813                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7814                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7815                     jmpTrueOrFalse(ifx, tlbl);
7816                     goto release;
7817                 } else {
7818                     CLRC;
7819                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7820                 }
7821             }
7822         }
7823         // bit = c
7824         // val = c
7825         if(size)
7826             pic16_outBitC(result);
7827         // if(bit | ...)
7828         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7829             genIfxJump(ifx, "c");           
7830         goto release ;
7831     }
7832
7833     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7834     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7835     if((AOP_TYPE(right) == AOP_LIT) &&
7836        (AOP_TYPE(result) == AOP_CRY) &&
7837        (AOP_TYPE(left) != AOP_CRY)){
7838         if(lit){
7839           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7840             // result = 1
7841             if(size)
7842                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7843             else 
7844                 continueIfTrue(ifx);
7845             goto release;
7846         } else {
7847           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7848             // lit = 0, result = boolean(left)
7849             if(size)
7850                 pic16_emitcode(";XXX setb","c");
7851             pic16_toBoolean(right);
7852             if(size){
7853                 symbol *tlbl = newiTempLabel(NULL);
7854                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7855                 CLRC;
7856                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7857             } else {
7858                 genIfxJump (ifx,"a");
7859                 goto release;
7860             }
7861         }
7862         pic16_outBitC(result);
7863         goto release ;
7864     }
7865
7866     /* if left is same as result */
7867     if(pic16_sameRegs(AOP(result),AOP(left))){
7868       int know_W = -1;
7869       for(;size--; offset++,lit>>=8) {
7870         if(AOP_TYPE(right) == AOP_LIT){
7871           if((lit & 0xff) == 0)
7872             /*  or'ing with 0 has no effect */
7873             continue;
7874           else {
7875             int p = pic16_my_powof2(lit & 0xff);
7876             if(p>=0) {
7877               /* only one bit is set in the literal, so use a bsf instruction */
7878               pic16_emitpcode(POC_BSF,
7879                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7880             } else {
7881               if(know_W != (lit & 0xff))
7882                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7883               know_W = lit & 0xff;
7884               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7885             }
7886                     
7887           }
7888         } else {
7889           if (AOP_TYPE(left) == AOP_ACC) {
7890             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7891 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7892           } else {                  
7893             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7894             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7895
7896 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7897 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7898
7899           }
7900         }
7901       }
7902     } else {
7903         // left & result in different registers
7904         if(AOP_TYPE(result) == AOP_CRY){
7905             // result = bit
7906             // if(size), result in bit
7907             // if(!size && ifx), conditional oper: if(left | right)
7908             symbol *tlbl = newiTempLabel(NULL);
7909             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7910             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7911
7912
7913             if(size)
7914                 pic16_emitcode(";XXX setb","c");
7915             while(sizer--){
7916                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7917                 pic16_emitcode(";XXX orl","a,%s",
7918                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7919                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7920                 offset++;
7921             }
7922             if(size){
7923                 CLRC;
7924                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7925                 pic16_outBitC(result);
7926             } else if(ifx)
7927                 jmpTrueOrFalse(ifx, tlbl);
7928         } else for(;(size--);offset++){
7929           // normal case
7930           // result = left & right
7931           if(AOP_TYPE(right) == AOP_LIT){
7932             int t = (lit >> (offset*8)) & 0x0FFL;
7933             switch(t) { 
7934             case 0x00:
7935               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7936               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7937
7938 //            pic16_emitcode("movf","%s,w",
7939 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7940 //            pic16_emitcode("movwf","%s",
7941 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7942               break;
7943             default:
7944               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7945               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7946               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7947
7948 //            pic16_emitcode("movlw","0x%x",t);
7949 //            pic16_emitcode("iorwf","%s,w",
7950 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7951 //            pic16_emitcode("movwf","%s",
7952 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7953               
7954             }
7955             continue;
7956           }
7957
7958           // faster than result <- left, anl result,right
7959           // and better if result is SFR
7960           if (AOP_TYPE(left) == AOP_ACC) {
7961             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7962 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7963           } else {
7964             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7965             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7966
7967 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7968 //          pic16_emitcode("iorwf","%s,w",
7969 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7970           }
7971           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7972 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7973         }
7974     }
7975
7976 release :
7977     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7978     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7979     pic16_freeAsmop(result,NULL,ic,TRUE);     
7980 }
7981
7982 /*-----------------------------------------------------------------*/
7983 /* genXor - code for xclusive or                                   */
7984 /*-----------------------------------------------------------------*/
7985 static void genXor (iCode *ic, iCode *ifx)
7986 {
7987   operand *left, *right, *result;
7988   int size, offset=0;
7989   unsigned long lit = 0L;
7990
7991   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7992
7993   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7994   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7995   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7996
7997   /* if left is a literal & right is not ||
7998      if left needs acc & right does not */
7999   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8000       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8001     operand *tmp = right ;
8002     right = left;
8003     left = tmp;
8004   }
8005
8006   /* if result = right then exchange them */
8007   if(pic16_sameRegs(AOP(result),AOP(right))){
8008     operand *tmp = right ;
8009     right = left;
8010     left = tmp;
8011   }
8012
8013   /* if right is bit then exchange them */
8014   if (AOP_TYPE(right) == AOP_CRY &&
8015       AOP_TYPE(left) != AOP_CRY){
8016     operand *tmp = right ;
8017     right = left;
8018     left = tmp;
8019   }
8020   if(AOP_TYPE(right) == AOP_LIT)
8021     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8022
8023   size = AOP_SIZE(result);
8024
8025   // if(bit ^ yy)
8026   // xx = bit ^ yy;
8027   if (AOP_TYPE(left) == AOP_CRY){
8028     if(AOP_TYPE(right) == AOP_LIT){
8029       // c = bit & literal;
8030       if(lit>>1){
8031         // lit>>1  != 0 => result = 1
8032         if(AOP_TYPE(result) == AOP_CRY){
8033           if(size)
8034             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8035             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8036           else if(ifx)
8037             continueIfTrue(ifx);
8038           goto release;
8039         }
8040         pic16_emitcode("setb","c");
8041       } else{
8042         // lit == (0 or 1)
8043         if(lit == 0){
8044           // lit == 0, result = left
8045           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8046             goto release;
8047           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8048         } else{
8049           // lit == 1, result = not(left)
8050           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8051             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8052             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8053             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8054             goto release;
8055           } else {
8056             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8057             pic16_emitcode("cpl","c");
8058           }
8059         }
8060       }
8061
8062     } else {
8063       // right != literal
8064       symbol *tlbl = newiTempLabel(NULL);
8065       if (AOP_TYPE(right) == AOP_CRY){
8066         // c = bit ^ bit;
8067         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8068       }
8069       else{
8070         int sizer = AOP_SIZE(right);
8071         // c = bit ^ val
8072         // if val>>1 != 0, result = 1
8073         pic16_emitcode("setb","c");
8074         while(sizer){
8075           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8076           if(sizer == 1)
8077             // test the msb of the lsb
8078             pic16_emitcode("anl","a,#0xfe");
8079           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8080           sizer--;
8081         }
8082         // val = (0,1)
8083         pic16_emitcode("rrc","a");
8084       }
8085       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8086       pic16_emitcode("cpl","c");
8087       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8088     }
8089     // bit = c
8090     // val = c
8091     if(size)
8092       pic16_outBitC(result);
8093     // if(bit | ...)
8094     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8095       genIfxJump(ifx, "c");           
8096     goto release ;
8097   }
8098
8099   if(pic16_sameRegs(AOP(result),AOP(left))){
8100     /* if left is same as result */
8101     for(;size--; offset++) {
8102       if(AOP_TYPE(right) == AOP_LIT){
8103         int t  = (lit >> (offset*8)) & 0x0FFL;
8104         if(t == 0x00L)
8105           continue;
8106         else
8107           if (IS_AOP_PREG(left)) {
8108             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8109             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8110             pic16_aopPut(AOP(result),"a",offset);
8111           } else {
8112             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8113             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8114             pic16_emitcode("xrl","%s,%s",
8115                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8116                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8117           }
8118       } else {
8119         if (AOP_TYPE(left) == AOP_ACC)
8120           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8121         else {
8122           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8123           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8124 /*
8125           if (IS_AOP_PREG(left)) {
8126             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8127             pic16_aopPut(AOP(result),"a",offset);
8128           } else
8129             pic16_emitcode("xrl","%s,a",
8130                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8131 */
8132         }
8133       }
8134     }
8135   } else {
8136     // left & result in different registers
8137     if(AOP_TYPE(result) == AOP_CRY){
8138       // result = bit
8139       // if(size), result in bit
8140       // if(!size && ifx), conditional oper: if(left ^ right)
8141       symbol *tlbl = newiTempLabel(NULL);
8142       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8143       if(size)
8144         pic16_emitcode("setb","c");
8145       while(sizer--){
8146         if((AOP_TYPE(right) == AOP_LIT) &&
8147            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8148           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8149         } else {
8150           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8151           pic16_emitcode("xrl","a,%s",
8152                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8153         }
8154         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8155         offset++;
8156       }
8157       if(size){
8158         CLRC;
8159         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8160         pic16_outBitC(result);
8161       } else if(ifx)
8162         jmpTrueOrFalse(ifx, tlbl);
8163     } else for(;(size--);offset++){
8164       // normal case
8165       // result = left & right
8166       if(AOP_TYPE(right) == AOP_LIT){
8167         int t = (lit >> (offset*8)) & 0x0FFL;
8168         switch(t) { 
8169         case 0x00:
8170           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8171           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8172           pic16_emitcode("movf","%s,w",
8173                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8174           pic16_emitcode("movwf","%s",
8175                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8176           break;
8177         case 0xff:
8178           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8179           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8180           pic16_emitcode("comf","%s,w",
8181                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8182           pic16_emitcode("movwf","%s",
8183                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8184           break;
8185         default:
8186           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8187           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8188           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8189           pic16_emitcode("movlw","0x%x",t);
8190           pic16_emitcode("xorwf","%s,w",
8191                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8192           pic16_emitcode("movwf","%s",
8193                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8194
8195         }
8196         continue;
8197       }
8198
8199       // faster than result <- left, anl result,right
8200       // and better if result is SFR
8201       if (AOP_TYPE(left) == AOP_ACC) {
8202         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8203         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8204       } else {
8205         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8206         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8207         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8208         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8209       }
8210       if ( AOP_TYPE(result) != AOP_ACC){
8211         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8212         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8213       }
8214     }
8215   }
8216
8217   release :
8218     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8219   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8220   pic16_freeAsmop(result,NULL,ic,TRUE);     
8221 }
8222
8223 /*-----------------------------------------------------------------*/
8224 /* genInline - write the inline code out                           */
8225 /*-----------------------------------------------------------------*/
8226 static void genInline (iCode *ic)
8227 {
8228   char *buffer, *bp, *bp1;
8229     
8230         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8231
8232         _G.inLine += (!options.asmpeep);
8233
8234         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8235         strcpy(buffer,IC_INLINE(ic));
8236         
8237         while((bp1=strstr(bp, "\\n"))) {
8238           *bp1++ = '\n';
8239           *bp1++ = ' ';
8240           bp = bp1;
8241         }
8242         bp = bp1 = buffer;
8243
8244 #if 0
8245   /* This is an experimental code for #pragma inline
8246      and is temporarily disabled for 2.5.0 release */
8247         if(asmInlineMap)
8248         {
8249           symbol *sym;
8250           char *s;
8251           char *cbuf;
8252           int cblen;
8253
8254             cbuf = Safe_strdup(buffer);
8255             cblen = strlen(buffer)+1;
8256             memset(cbuf, 0, cblen);
8257
8258             bp = buffer;
8259             bp1 = cbuf;
8260             while(*bp) {
8261               if(*bp != '%')*bp1++ = *bp++;
8262               else {
8263                 int i;
8264
8265                   bp++;
8266                   i = *bp - '0';
8267                   if(i>elementsInSet(asmInlineMap))break;
8268                   
8269                   bp++;
8270                   s = indexSet(asmInlineMap, i);
8271                   DEBUGpc("searching symbol s = `%s'", s);
8272                   sym = findSym(SymbolTab, NULL, s);
8273
8274                   if(sym->reqv) {
8275                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8276                   } else {
8277                     strcat(bp1, sym->rname);
8278                   }
8279                   
8280                   while(*bp1)bp1++;
8281               }
8282               
8283               if(strlen(bp1) > cblen - 16) {
8284                 int i = strlen(cbuf);
8285                 cblen += 50;
8286                 cbuf = realloc(cbuf, cblen);
8287                 memset(cbuf+i, 0, 50);
8288                 bp1 = cbuf + i;
8289               }
8290             }
8291             
8292             free(buffer);
8293             buffer = Safe_strdup( cbuf );
8294             free(cbuf);
8295             
8296             bp = bp1 = buffer;
8297         }
8298 #endif  /* 0 */
8299
8300         /* emit each line as a code */
8301         while (*bp) {
8302                 if (*bp == '\n') {
8303                         *bp++ = '\0';
8304
8305                         if(*bp1)
8306                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8307                         bp1 = bp;
8308                 } else {
8309                         if (*bp == ':') {
8310                                 bp++;
8311                                 *bp = '\0';
8312                                 bp++;
8313
8314                                 /* print label, use this special format with NULL directive
8315                                  * to denote that the argument should not be indented with tab */
8316                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8317                                 bp1 = bp;
8318                         } if (*bp == ';') {
8319                                 /* advance to end of line (prevent splitting of comments at ':' */
8320                                 while (*bp && *bp != '\n') {
8321                                         bp++;
8322                                 } // while
8323                         } else
8324                                 bp++;
8325                 }
8326         }
8327
8328         if ((bp1 != bp) && *bp1)
8329                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8330
8331
8332     Safe_free(buffer);
8333
8334     _G.inLine -= (!options.asmpeep);
8335 }
8336
8337 /*-----------------------------------------------------------------*/
8338 /* genRRC - rotate right with carry                                */
8339 /*-----------------------------------------------------------------*/
8340 static void genRRC (iCode *ic)
8341 {
8342   operand *left , *result ;
8343   int size, offset = 0, same;
8344
8345   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8346
8347   /* rotate right with carry */
8348   left = IC_LEFT(ic);
8349   result=IC_RESULT(ic);
8350   pic16_aopOp (left,ic,FALSE);
8351   pic16_aopOp (result,ic,TRUE);
8352
8353   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8354
8355   same = pic16_sameRegs(AOP(result),AOP(left));
8356
8357   size = AOP_SIZE(result);    
8358
8359   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8360
8361   /* get the lsb and put it into the carry */
8362   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8363
8364   offset = 0 ;
8365
8366   while(size--) {
8367
8368     if(same) {
8369       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8370     } else {
8371       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8372       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8373     }
8374
8375     offset++;
8376   }
8377
8378   pic16_freeAsmop(left,NULL,ic,TRUE);
8379   pic16_freeAsmop(result,NULL,ic,TRUE);
8380 }
8381
8382 /*-----------------------------------------------------------------*/
8383 /* genRLC - generate code for rotate left with carry               */
8384 /*-----------------------------------------------------------------*/
8385 static void genRLC (iCode *ic)
8386 {    
8387   operand *left , *result ;
8388   int size, offset = 0;
8389   int same;
8390
8391   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8392   /* rotate right with carry */
8393   left = IC_LEFT(ic);
8394   result=IC_RESULT(ic);
8395   pic16_aopOp (left,ic,FALSE);
8396   pic16_aopOp (result,ic,TRUE);
8397
8398   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8399
8400   same = pic16_sameRegs(AOP(result),AOP(left));
8401
8402   /* move it to the result */
8403   size = AOP_SIZE(result);    
8404
8405   /* get the msb and put it into the carry */
8406   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8407
8408   offset = 0 ;
8409
8410   while(size--) {
8411
8412     if(same) {
8413       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8414     } else {
8415       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8416       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8417     }
8418
8419     offset++;
8420   }
8421
8422
8423   pic16_freeAsmop(left,NULL,ic,TRUE);
8424   pic16_freeAsmop(result,NULL,ic,TRUE);
8425 }
8426
8427
8428 /* gpasm can get the highest order bit with HIGH/UPPER
8429  * so the following probably is not needed -- VR */
8430  
8431 /*-----------------------------------------------------------------*/
8432 /* genGetHbit - generates code get highest order bit               */
8433 /*-----------------------------------------------------------------*/
8434 static void genGetHbit (iCode *ic)
8435 {
8436     operand *left, *result;
8437     left = IC_LEFT(ic);
8438     result=IC_RESULT(ic);
8439     pic16_aopOp (left,ic,FALSE);
8440     pic16_aopOp (result,ic,FALSE);
8441
8442     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8443     /* get the highest order byte into a */
8444     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8445     if(AOP_TYPE(result) == AOP_CRY){
8446         pic16_emitcode("rlc","a");
8447         pic16_outBitC(result);
8448     }
8449     else{
8450         pic16_emitcode("rl","a");
8451         pic16_emitcode("anl","a,#0x01");
8452         pic16_outAcc(result);
8453     }
8454
8455
8456     pic16_freeAsmop(left,NULL,ic,TRUE);
8457     pic16_freeAsmop(result,NULL,ic,TRUE);
8458 }
8459
8460 #if 0
8461 /*-----------------------------------------------------------------*/
8462 /* AccRol - rotate left accumulator by known count                 */
8463 /*-----------------------------------------------------------------*/
8464 static void AccRol (int shCount)
8465 {
8466     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8467     shCount &= 0x0007;              // shCount : 0..7
8468     switch(shCount){
8469         case 0 :
8470             break;
8471         case 1 :
8472             pic16_emitcode("rl","a");
8473             break;
8474         case 2 :
8475             pic16_emitcode("rl","a");
8476             pic16_emitcode("rl","a");
8477             break;
8478         case 3 :
8479             pic16_emitcode("swap","a");
8480             pic16_emitcode("rr","a");
8481             break;
8482         case 4 :
8483             pic16_emitcode("swap","a");
8484             break;
8485         case 5 :
8486             pic16_emitcode("swap","a");
8487             pic16_emitcode("rl","a");
8488             break;
8489         case 6 :
8490             pic16_emitcode("rr","a");
8491             pic16_emitcode("rr","a");
8492             break;
8493         case 7 :
8494             pic16_emitcode("rr","a");
8495             break;
8496     }
8497 }
8498 #endif
8499
8500 /*-----------------------------------------------------------------*/
8501 /* AccLsh - left shift accumulator by known count                  */
8502 /*-----------------------------------------------------------------*/
8503 static void AccLsh (int shCount, int doMask)
8504 {
8505         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8506         switch(shCount){
8507                 case 0 :
8508                         return;
8509                         break;
8510                 case 1 :
8511                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8512                         break;
8513                 case 2 :
8514                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8515                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8516                         break;
8517                 case 3 :
8518                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8519                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520                         break;
8521                 case 4 :
8522                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8523                         break;
8524                 case 5 :
8525                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8526                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8527                         break;
8528                 case 6 :
8529                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8530                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8531                         break;
8532                 case 7 :
8533                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8534                         break;
8535         }
8536         if (doMask) {
8537                 /* no masking is required in genPackBits */
8538                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8539         }
8540 }
8541
8542 /*-----------------------------------------------------------------*/
8543 /* AccRsh - right shift accumulator by known count                 */
8544 /*-----------------------------------------------------------------*/
8545 static void AccRsh (int shCount, int andmask)
8546 {
8547         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8548         switch(shCount){
8549                 case 0 :
8550                         return; break;
8551                 case 1 :
8552                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8553                         break;
8554                 case 2 :
8555                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8556                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8557                         break;
8558                 case 3 :
8559                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8560                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8561                         break;
8562                 case 4 :
8563                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8564                         break;
8565                 case 5 :
8566                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8567                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8568                         break;
8569                 case 6 :
8570                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8571                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8572                         break;
8573                 case 7 :
8574                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8575                         break;
8576         }
8577         
8578         if(andmask)
8579                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8580         else
8581                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8582 }
8583
8584 #if 0
8585 /*-----------------------------------------------------------------*/
8586 /* AccSRsh - signed right shift accumulator by known count                 */
8587 /*-----------------------------------------------------------------*/
8588 static void AccSRsh (int shCount)
8589 {
8590     symbol *tlbl ;
8591     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8592     if(shCount != 0){
8593         if(shCount == 1){
8594             pic16_emitcode("mov","c,acc.7");
8595             pic16_emitcode("rrc","a");
8596         } else if(shCount == 2){
8597             pic16_emitcode("mov","c,acc.7");
8598             pic16_emitcode("rrc","a");
8599             pic16_emitcode("mov","c,acc.7");
8600             pic16_emitcode("rrc","a");
8601         } else {
8602             tlbl = newiTempLabel(NULL);
8603             /* rotate right accumulator */
8604             AccRol(8 - shCount);
8605             /* and kill the higher order bits */
8606             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8607             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8608             pic16_emitcode("orl","a,#0x%02x",
8609                      (unsigned char)~SRMask[shCount]);
8610             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8611         }
8612     }
8613 }
8614 #endif
8615
8616 /*-----------------------------------------------------------------*/
8617 /* shiftR1Left2Result - shift right one byte from left to result   */
8618 /*-----------------------------------------------------------------*/
8619 static void shiftR1Left2ResultSigned (operand *left, int offl,
8620                                 operand *result, int offr,
8621                                 int shCount)
8622 {
8623   int same;
8624
8625   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8626
8627   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8628
8629   switch(shCount) {
8630   case 1:
8631     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8632     if(same) 
8633       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8634     else {
8635       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8636       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8637     }
8638
8639     break;
8640   case 2:
8641
8642     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8643     if(same) 
8644       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8645     else {
8646       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8647       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8648     }
8649     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8650     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8651
8652     break;
8653
8654   case 3:
8655     if(same)
8656       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8657     else {
8658       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8659       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8660     }
8661
8662     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8663     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8664     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8665
8666     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8667     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8668
8669     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8670     break;
8671
8672   case 4:
8673     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8674     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8675     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8676     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8677     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8678     break;
8679   case 5:
8680     if(same) {
8681       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8682     } else {
8683       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8684       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8685     }
8686     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8687     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8688     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8689     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8690     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8691     break;
8692
8693   case 6:
8694     if(same) {
8695       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8696       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8697       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8698       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8699       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8700       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8701     } else {
8702       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8703       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8704       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8705       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8706       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8707     }
8708     break;
8709
8710   case 7:
8711     if(same) {
8712       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8713       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8714       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8715       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8716     } else {
8717       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8718       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8719       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8720     }
8721
8722   default:
8723     break;
8724   }
8725 }
8726
8727 /*-----------------------------------------------------------------*/
8728 /* shiftR1Left2Result - shift right one byte from left to result   */
8729 /*-----------------------------------------------------------------*/
8730 static void shiftR1Left2Result (operand *left, int offl,
8731                                 operand *result, int offr,
8732                                 int shCount, int sign)
8733 {
8734   int same;
8735
8736   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8737
8738   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8739
8740   /* Copy the msb into the carry if signed. */
8741   if(sign) {
8742     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8743     return;
8744   }
8745
8746
8747
8748   switch(shCount) {
8749   case 1:
8750     emitCLRC;
8751     if(same) 
8752       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8753     else {
8754       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8755       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8756     }
8757     break;
8758   case 2:
8759     emitCLRC;
8760     if(same) {
8761       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8762     } else {
8763       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8764       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8765     }
8766     emitCLRC;
8767     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8768
8769     break;
8770   case 3:
8771     if(same)
8772       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8773     else {
8774       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8775       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8776     }
8777
8778     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8779     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8780     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8781     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8782     break;
8783       
8784   case 4:
8785     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8786     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8787     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8788     break;
8789
8790   case 5:
8791     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8792     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8793     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8794     //emitCLRC;
8795     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8796
8797     break;
8798   case 6:
8799
8800     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8801     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8802     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8803     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8804     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8805     break;
8806
8807   case 7:
8808
8809     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8810     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8811     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8812
8813     break;
8814
8815   default:
8816     break;
8817   }
8818 }
8819
8820 /*-----------------------------------------------------------------*/
8821 /* shiftL1Left2Result - shift left one byte from left to result    */
8822 /*-----------------------------------------------------------------*/
8823 static void shiftL1Left2Result (operand *left, int offl,
8824                                 operand *result, int offr, int shCount)
8825 {
8826   int same;
8827
8828   //    char *l;
8829   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8830
8831   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8832   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8833     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8834     //    MOVA(l);
8835     /* shift left accumulator */
8836     //AccLsh(shCount, 1); // don't comment out just yet...
8837   //    pic16_aopPut(AOP(result),"a",offr);
8838
8839   switch(shCount) {
8840   case 1:
8841     /* Shift left 1 bit position */
8842     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8843     if(same) {
8844       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8845     } else {
8846       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8847       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8848     }
8849     break;
8850   case 2:
8851     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8852     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8853     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8854     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8855     break;
8856   case 3:
8857     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8858     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8859     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8860     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8861     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8862     break;
8863   case 4:
8864     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8865     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8866     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8867     break;
8868   case 5:
8869     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8870     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8871     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8872     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8873     break;
8874   case 6:
8875     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8876     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8877     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8878     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8879     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8880     break;
8881   case 7:
8882     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8883     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8884     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8885     break;
8886
8887   default:
8888     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8889   }
8890
8891 }
8892
8893 /*-----------------------------------------------------------------*/
8894 /* movLeft2Result - move byte from left to result                  */
8895 /*-----------------------------------------------------------------*/
8896 static void movLeft2Result (operand *left, int offl,
8897                             operand *result, int offr)
8898 {
8899   char *l;
8900   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8901   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8902     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8903
8904     if (*l == '@' && (IS_AOP_PREG(result))) {
8905       pic16_emitcode("mov","a,%s",l);
8906       pic16_aopPut(AOP(result),"a",offr);
8907     } else {
8908       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8909       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8910     }
8911   }
8912 }
8913
8914 /*-----------------------------------------------------------------*/
8915 /* shiftL2Left2Result - shift left two bytes from left to result   */
8916 /*-----------------------------------------------------------------*/
8917 static void shiftL2Left2Result (operand *left, int offl,
8918                                 operand *result, int offr, int shCount)
8919 {
8920   int same = pic16_sameRegs(AOP(result), AOP(left));
8921   int i;
8922
8923   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8924
8925   if (same && (offl != offr)) { // shift bytes
8926     if (offr > offl) {
8927        for(i=1;i>-1;i--) {
8928          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8929          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8930        }
8931     } else { // just treat as different later on
8932                 same = 0;
8933     }
8934   }
8935
8936   if(same) {
8937     switch(shCount) {
8938     case 0:
8939       break;
8940     case 1:
8941     case 2:
8942     case 3:
8943
8944       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8945       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8946       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8947
8948       while(--shCount) {
8949                 emitCLRC;
8950                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8951                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8952       }
8953
8954       break;
8955     case 4:
8956     case 5:
8957       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8958       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8959       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8960       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8961       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8962       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8963       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8964       if(shCount >=5) {
8965                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8966                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8967       }
8968       break;
8969     case 6:
8970       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8971       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8973       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8974       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8975       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8976       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8977       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8978       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8979       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8980       break;
8981     case 7:
8982       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8983       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8984       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8985       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8986       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8987     }
8988
8989   } else {
8990     switch(shCount) {
8991     case 0:
8992       break;
8993     case 1:
8994     case 2:
8995     case 3:
8996       /* note, use a mov/add for the shift since the mov has a
8997          chance of getting optimized out */
8998       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8999       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9000       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9001       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9002       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9003
9004       while(--shCount) {
9005                 emitCLRC;
9006                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9007                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9008       }
9009       break;
9010
9011     case 4:
9012     case 5:
9013       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9014       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9015       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9016       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9017       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9018       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9019       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9020       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9021
9022
9023       if(shCount == 5) {
9024                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9025                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9026       }
9027       break;
9028     case 6:
9029       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9030       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9031       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9032       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9033
9034       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9035       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9036       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9037       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9038       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9039       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9040       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9041       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9042       break;
9043     case 7:
9044       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9045       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9046       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9047       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9048       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9049     }
9050   }
9051
9052 }
9053 /*-----------------------------------------------------------------*/
9054 /* shiftR2Left2Result - shift right two bytes from left to result  */
9055 /*-----------------------------------------------------------------*/
9056 static void shiftR2Left2Result (operand *left, int offl,
9057                                 operand *result, int offr,
9058                                 int shCount, int sign)
9059 {
9060   int same = pic16_sameRegs(AOP(result), AOP(left));
9061   int i;
9062   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9063
9064   if (same && (offl != offr)) { // shift right bytes
9065     if (offr < offl) {
9066        for(i=0;i<2;i++) {
9067          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9068          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9069        }
9070     } else { // just treat as different later on
9071                 same = 0;
9072     }
9073   }
9074
9075   switch(shCount) {
9076   case 0:
9077     break;
9078   case 1:
9079   case 2:
9080   case 3:
9081     if(sign)
9082       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9083     else
9084       emitCLRC;
9085
9086     if(same) {
9087       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9088       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9089     } else {
9090       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9091       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9092       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9093       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9094     }
9095
9096     while(--shCount) {
9097       if(sign)
9098                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9099       else
9100                 emitCLRC;
9101       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9102       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9103     }
9104     break;
9105   case 4:
9106   case 5:
9107     if(same) {
9108
9109       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9110       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9111       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9112
9113       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9114       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9115       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9116       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9117     } else {
9118       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9119       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9120       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9121
9122       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9123       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9124       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9125       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9126       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9127     }
9128
9129     if(shCount >=5) {
9130       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9131       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9132     }
9133
9134     if(sign) {
9135       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9136       pic16_emitpcode(POC_BTFSC, 
9137                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9138       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9139     }
9140
9141     break;
9142
9143   case 6:
9144     if(same) {
9145
9146       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9147       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9148
9149       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9150       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9151       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9152       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9153       if(sign) {
9154         pic16_emitpcode(POC_BTFSC, 
9155                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9156         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9157       }
9158       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9159       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9160       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9161       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9162     } else {
9163       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9164       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9165       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9166       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9167       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9168       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9169       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9170       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9171       if(sign) {
9172         pic16_emitpcode(POC_BTFSC, 
9173                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9174         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9175       }
9176       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9177       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9178
9179         
9180     }
9181
9182     break;
9183   case 7:
9184     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9185     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9186     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9187     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9188     if(sign) {
9189       emitSKPNC;
9190       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9191     } else 
9192       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9193   }
9194 }
9195
9196
9197 /*-----------------------------------------------------------------*/
9198 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9199 /*-----------------------------------------------------------------*/
9200 static void shiftLLeftOrResult (operand *left, int offl,
9201                                 operand *result, int offr, int shCount)
9202 {
9203     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9204
9205     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9206     /* shift left accumulator */
9207     AccLsh(shCount, 1);
9208     /* or with result */
9209     /* back to result */
9210     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9211 }
9212
9213 /*-----------------------------------------------------------------*/
9214 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9215 /*-----------------------------------------------------------------*/
9216 static void shiftRLeftOrResult (operand *left, int offl,
9217                                 operand *result, int offr, int shCount)
9218 {
9219     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9220     
9221     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9222     /* shift right accumulator */
9223     AccRsh(shCount, 1);
9224     /* or with result */
9225     /* back to result */
9226     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9227 }
9228
9229 /*-----------------------------------------------------------------*/
9230 /* genlshOne - left shift a one byte quantity by known count       */
9231 /*-----------------------------------------------------------------*/
9232 static void genlshOne (operand *result, operand *left, int shCount)
9233 {       
9234     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9235     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9236 }
9237
9238 /*-----------------------------------------------------------------*/
9239 /* genlshTwo - left shift two bytes by known amount != 0           */
9240 /*-----------------------------------------------------------------*/
9241 static void genlshTwo (operand *result,operand *left, int shCount)
9242 {
9243     int size;
9244     
9245     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9246     size = pic16_getDataSize(result);
9247
9248     /* if shCount >= 8 */
9249     if (shCount >= 8) {
9250         shCount -= 8 ;
9251
9252         if (size > 1){
9253             if (shCount)
9254                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9255             else 
9256                 movLeft2Result(left, LSB, result, MSB16);
9257         }
9258         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9259     }
9260
9261     /*  1 <= shCount <= 7 */
9262     else {  
9263         if(size == 1)
9264             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9265         else 
9266             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9267     }
9268 }
9269
9270 /*-----------------------------------------------------------------*/
9271 /* shiftLLong - shift left one long from left to result            */
9272 /* offr = LSB or MSB16                                             */
9273 /*-----------------------------------------------------------------*/
9274 static void shiftLLong (operand *left, operand *result, int offr )
9275 {
9276     int size = AOP_SIZE(result);
9277     int same = pic16_sameRegs(AOP(left),AOP(result));
9278         int i;
9279
9280     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9281
9282         if (same && (offr == MSB16)) { //shift one byte
9283                 for(i=size-1;i>=MSB16;i--) {
9284                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9285                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9286                 }
9287         } else {
9288                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9289         }
9290         
9291     if (size > LSB+offr ){
9292                 if (same) {
9293                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9294                 } else {
9295                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9296                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9297                 }
9298          }
9299
9300     if(size > MSB16+offr){
9301                 if (same) {
9302                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9303                 } else {
9304                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9305                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9306                 }
9307     }
9308
9309     if(size > MSB24+offr){
9310                 if (same) {
9311                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9312                 } else {
9313                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9314                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9315                 }
9316     }
9317
9318     if(size > MSB32+offr){
9319                 if (same) {
9320                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9321                 } else {
9322                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9323                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9324                 }
9325     }
9326     if(offr != LSB)
9327                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9328
9329 }
9330
9331 /*-----------------------------------------------------------------*/
9332 /* genlshFour - shift four byte by a known amount != 0             */
9333 /*-----------------------------------------------------------------*/
9334 static void genlshFour (operand *result, operand *left, int shCount)
9335 {
9336     int size;
9337
9338     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9339     size = AOP_SIZE(result);
9340
9341     /* if shifting more that 3 bytes */
9342     if (shCount >= 24 ) {
9343         shCount -= 24;
9344         if (shCount)
9345             /* lowest order of left goes to the highest
9346             order of the destination */
9347             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9348         else
9349             movLeft2Result(left, LSB, result, MSB32);
9350
9351                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9352                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9353                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9354
9355         return;
9356     }
9357
9358     /* more than two bytes */
9359     else if ( shCount >= 16 ) {
9360         /* lower order two bytes goes to higher order two bytes */
9361         shCount -= 16;
9362         /* if some more remaining */
9363         if (shCount)
9364             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9365         else {
9366             movLeft2Result(left, MSB16, result, MSB32);
9367             movLeft2Result(left, LSB, result, MSB24);
9368         }
9369                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9370                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9371         return;
9372     }    
9373
9374     /* if more than 1 byte */
9375     else if ( shCount >= 8 ) {
9376         /* lower order three bytes goes to higher order  three bytes */
9377         shCount -= 8;
9378         if(size == 2){
9379             if(shCount)
9380                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9381             else
9382                 movLeft2Result(left, LSB, result, MSB16);
9383         }
9384         else{   /* size = 4 */
9385             if(shCount == 0){
9386                 movLeft2Result(left, MSB24, result, MSB32);
9387                 movLeft2Result(left, MSB16, result, MSB24);
9388                 movLeft2Result(left, LSB, result, MSB16);
9389                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9390             }
9391             else if(shCount == 1)
9392                 shiftLLong(left, result, MSB16);
9393             else{
9394                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9395                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9396                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9397                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9398             }
9399         }
9400     }
9401
9402     /* 1 <= shCount <= 7 */
9403     else if(shCount <= 3)
9404     { 
9405         shiftLLong(left, result, LSB);
9406         while(--shCount >= 1)
9407             shiftLLong(result, result, LSB);
9408     }
9409     /* 3 <= shCount <= 7, optimize */
9410     else{
9411         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9412         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9413         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9414     }
9415 }
9416
9417 /*-----------------------------------------------------------------*/
9418 /* genLeftShiftLiteral - left shifting by known count              */
9419 /*-----------------------------------------------------------------*/
9420 void pic16_genLeftShiftLiteral (operand *left,
9421                                  operand *right,
9422                                  operand *result,
9423                                  iCode *ic)
9424 {    
9425     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9426     int size;
9427
9428     FENTRY;
9429     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9430     pic16_freeAsmop(right,NULL,ic,TRUE);
9431
9432     pic16_aopOp(left,ic,FALSE);
9433     pic16_aopOp(result,ic,TRUE);
9434
9435     size = getSize(operandType(result));
9436
9437 #if VIEW_SIZE
9438     pic16_emitcode("; shift left ","result %d, left %d",size,
9439              AOP_SIZE(left));
9440 #endif
9441
9442     /* I suppose that the left size >= result size */
9443     if(shCount == 0){
9444         while(size--){
9445             movLeft2Result(left, size, result, size);
9446         }
9447     }
9448
9449     else if(shCount >= (size * 8))
9450         while(size--)
9451             pic16_aopPut(AOP(result),zero,size);
9452     else{
9453         switch (size) {
9454             case 1:
9455                 genlshOne (result,left,shCount);
9456                 break;
9457
9458             case 2:
9459             case 3:
9460                 genlshTwo (result,left,shCount);
9461                 break;
9462
9463             case 4:
9464                 genlshFour (result,left,shCount);
9465                 break;
9466         }
9467     }
9468     pic16_freeAsmop(left,NULL,ic,TRUE);
9469     pic16_freeAsmop(result,NULL,ic,TRUE);
9470 }
9471
9472 /*-----------------------------------------------------------------*
9473  * genMultiAsm - repeat assembly instruction for size of register.
9474  * if endian == 1, then the high byte (i.e base address + size of 
9475  * register) is used first else the low byte is used first;
9476  *-----------------------------------------------------------------*/
9477 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9478 {
9479
9480   int offset = 0;
9481
9482   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9483
9484   if(!reg)
9485     return;
9486
9487   if(!endian) {
9488     endian = 1;
9489   } else {
9490     endian = -1;
9491     offset = size-1;
9492   }
9493
9494   while(size--) {
9495     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9496     offset += endian;
9497   }
9498
9499 }
9500
9501 #if !(USE_GENERIC_SIGNED_SHIFT)
9502 /*-----------------------------------------------------------------*/
9503 /* genLeftShift - generates code for left shifting                 */
9504 /*-----------------------------------------------------------------*/
9505 static void genLeftShift (iCode *ic)
9506 {
9507   operand *left,*right, *result;
9508   int size, offset;
9509 //  char *l;
9510   symbol *tlbl , *tlbl1;
9511   pCodeOp *pctemp;
9512
9513   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9514
9515   right = IC_RIGHT(ic);
9516   left  = IC_LEFT(ic);
9517   result = IC_RESULT(ic);
9518
9519   pic16_aopOp(right,ic,FALSE);
9520
9521   /* if the shift count is known then do it 
9522      as efficiently as possible */
9523   if (AOP_TYPE(right) == AOP_LIT) {
9524     pic16_genLeftShiftLiteral (left,right,result,ic);
9525     return ;
9526   }
9527
9528   /* shift count is unknown then we have to form
9529    * a loop. Get the loop count in WREG : Note: we take
9530    * only the lower order byte since shifting
9531    * more than 32 bits make no sense anyway, ( the
9532    * largest size of an object can be only 32 bits ) */
9533   
9534   pic16_aopOp(left,ic,FALSE);
9535   pic16_aopOp(result,ic,FALSE);
9536
9537   /* now move the left to the result if they are not the
9538    * same, and if size > 1,
9539    * and if right is not same to result (!!!) -- VR */
9540   if (!pic16_sameRegs(AOP(left),AOP(result))
9541       && (AOP_SIZE(result) > 1)) {
9542
9543     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9544
9545     size = AOP_SIZE(result);
9546     offset=0;
9547     while (size--) {
9548
9549 #if 0
9550       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9551       if (*l == '@' && (IS_AOP_PREG(result))) {
9552
9553           pic16_emitcode("mov","a,%s",l);
9554           pic16_aopPut(AOP(result),"a",offset);
9555       } else
9556 #endif
9557       {
9558         /* we don't know if left is a literal or a register, take care -- VR */
9559         pic16_mov2f(AOP(result), AOP(left), offset);
9560       }
9561       offset++;
9562     }
9563   }
9564
9565   size = AOP_SIZE(result);
9566
9567   /* if it is only one byte then */
9568   if (size == 1) {
9569     if(optimized_for_speed) {
9570       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9571       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9572       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9573       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9574       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9575       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9576       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9577       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9578       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9579       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9580       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9581       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9582     } else {
9583
9584       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9585
9586       tlbl = newiTempLabel(NULL);
9587
9588 #if 1
9589       /* this is already done, why change it? */
9590       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9591                 pic16_mov2f(AOP(result), AOP(left), 0);
9592       }
9593 #endif
9594
9595       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9596       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9597       pic16_emitpLabel(tlbl->key);
9598       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9599       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9600       emitSKPC;
9601       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9602     }
9603     goto release ;
9604   }
9605     
9606   if (pic16_sameRegs(AOP(left),AOP(result))) {
9607
9608     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9609     
9610     tlbl = newiTempLabel(NULL);
9611     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9612     genMultiAsm(POC_RRCF, result, size,1);
9613     pic16_emitpLabel(tlbl->key);
9614     genMultiAsm(POC_RLCF, result, size,0);
9615     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9616     emitSKPC;
9617     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9618     goto release;
9619   }
9620
9621   //tlbl = newiTempLabel(NULL);
9622   //offset = 0 ;   
9623   //tlbl1 = newiTempLabel(NULL);
9624
9625   //reAdjustPreg(AOP(result));    
9626     
9627   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9628   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9629   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9630   //MOVA(l);
9631   //pic16_emitcode("add","a,acc");         
9632   //pic16_aopPut(AOP(result),"a",offset++);
9633   //while (--size) {
9634   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9635   //  MOVA(l);
9636   //  pic16_emitcode("rlc","a");         
9637   //  pic16_aopPut(AOP(result),"a",offset++);
9638   //}
9639   //reAdjustPreg(AOP(result));
9640
9641   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9642   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9643
9644
9645   tlbl = newiTempLabel(NULL);
9646   tlbl1= newiTempLabel(NULL);
9647
9648   size = AOP_SIZE(result);
9649   offset = 1;
9650
9651   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9652
9653   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9654
9655   /* offset should be 0, 1 or 3 */
9656   
9657   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9658   emitSKPNZ;
9659   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9660
9661   pic16_emitpcode(POC_MOVWF, pctemp);
9662
9663
9664   pic16_emitpLabel(tlbl->key);
9665
9666   emitCLRC;
9667   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9668   while(--size)
9669     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9670
9671   pic16_emitpcode(POC_DECFSZ,  pctemp);
9672   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9673   pic16_emitpLabel(tlbl1->key);
9674
9675   pic16_popReleaseTempReg(pctemp,1);
9676
9677
9678  release:
9679   pic16_freeAsmop (right,NULL,ic,TRUE);
9680   pic16_freeAsmop(left,NULL,ic,TRUE);
9681   pic16_freeAsmop(result,NULL,ic,TRUE);
9682 }
9683 #endif
9684
9685
9686 #if 0
9687 #error old code (left here for reference)
9688 /*-----------------------------------------------------------------*/
9689 /* genLeftShift - generates code for left shifting                 */
9690 /*-----------------------------------------------------------------*/
9691 static void genLeftShift (iCode *ic)
9692 {
9693   operand *left,*right, *result;
9694   int size, offset;
9695   char *l;
9696   symbol *tlbl , *tlbl1;
9697   pCodeOp *pctemp;
9698
9699   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9700
9701   right = IC_RIGHT(ic);
9702   left  = IC_LEFT(ic);
9703   result = IC_RESULT(ic);
9704
9705   pic16_aopOp(right,ic,FALSE);
9706
9707   /* if the shift count is known then do it 
9708      as efficiently as possible */
9709   if (AOP_TYPE(right) == AOP_LIT) {
9710     pic16_genLeftShiftLiteral (left,right,result,ic);
9711     return ;
9712   }
9713
9714   /* shift count is unknown then we have to form 
9715      a loop get the loop count in B : Note: we take
9716      only the lower order byte since shifting
9717      more that 32 bits make no sense anyway, ( the
9718      largest size of an object can be only 32 bits ) */  
9719
9720     
9721   pic16_aopOp(left,ic,FALSE);
9722   pic16_aopOp(result,ic,FALSE);
9723
9724   /* now move the left to the result if they are not the
9725      same */
9726   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9727       AOP_SIZE(result) > 1) {
9728
9729     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9730
9731     size = AOP_SIZE(result);
9732     offset=0;
9733     while (size--) {
9734       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9735       if (*l == '@' && (IS_AOP_PREG(result))) {
9736
9737         pic16_emitcode("mov","a,%s",l);
9738         pic16_aopPut(AOP(result),"a",offset);
9739       } else {
9740
9741         /* we don't know if left is a literal or a register, take care -- VR */
9742         pic16_mov2f(AOP(result), AOP(left), offset);
9743       }
9744       offset++;
9745     }
9746   }
9747
9748   size = AOP_SIZE(result);
9749
9750   /* if it is only one byte then */
9751   if (size == 1) {
9752     if(optimized_for_speed) {
9753       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9754       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9755       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9756       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9757       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9758       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9759       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9760       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9761       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9762       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9763       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9764       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9765     } else {
9766
9767       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9768
9769       tlbl = newiTempLabel(NULL);
9770       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9771                 pic16_mov2f(AOP(result), AOP(left), 0);
9772                 
9773 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9774 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9775       }
9776
9777       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9778       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9779       pic16_emitpLabel(tlbl->key);
9780       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9781       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9782       emitSKPC;
9783       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9784     }
9785     goto release ;
9786   }
9787     
9788   if (pic16_sameRegs(AOP(left),AOP(result))) {
9789
9790     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9791     
9792     tlbl = newiTempLabel(NULL);
9793     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9794     genMultiAsm(POC_RRCF, result, size,1);
9795     pic16_emitpLabel(tlbl->key);
9796     genMultiAsm(POC_RLCF, result, size,0);
9797     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9798     emitSKPC;
9799     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9800     goto release;
9801   }
9802
9803   //tlbl = newiTempLabel(NULL);
9804   //offset = 0 ;   
9805   //tlbl1 = newiTempLabel(NULL);
9806
9807   //reAdjustPreg(AOP(result));    
9808     
9809   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9810   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9811   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9812   //MOVA(l);
9813   //pic16_emitcode("add","a,acc");         
9814   //pic16_aopPut(AOP(result),"a",offset++);
9815   //while (--size) {
9816   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9817   //  MOVA(l);
9818   //  pic16_emitcode("rlc","a");         
9819   //  pic16_aopPut(AOP(result),"a",offset++);
9820   //}
9821   //reAdjustPreg(AOP(result));
9822
9823   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9824   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9825
9826
9827   tlbl = newiTempLabel(NULL);
9828   tlbl1= newiTempLabel(NULL);
9829
9830   size = AOP_SIZE(result);
9831   offset = 1;
9832
9833   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9834
9835   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9836
9837   /* offset should be 0, 1 or 3 */
9838   
9839   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9840   emitSKPNZ;
9841   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9842
9843   pic16_emitpcode(POC_MOVWF, pctemp);
9844
9845
9846   pic16_emitpLabel(tlbl->key);
9847
9848   emitCLRC;
9849   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9850   while(--size)
9851     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9852
9853   pic16_emitpcode(POC_DECFSZ,  pctemp);
9854   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9855   pic16_emitpLabel(tlbl1->key);
9856
9857   pic16_popReleaseTempReg(pctemp,1);
9858
9859
9860  release:
9861   pic16_freeAsmop (right,NULL,ic,TRUE);
9862   pic16_freeAsmop(left,NULL,ic,TRUE);
9863   pic16_freeAsmop(result,NULL,ic,TRUE);
9864 }
9865 #endif
9866
9867 /*-----------------------------------------------------------------*/
9868 /* genrshOne - right shift a one byte quantity by known count      */
9869 /*-----------------------------------------------------------------*/
9870 static void genrshOne (operand *result, operand *left,
9871                        int shCount, int sign)
9872 {
9873     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9874     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9875 }
9876
9877 /*-----------------------------------------------------------------*/
9878 /* genrshTwo - right shift two bytes by known amount != 0          */
9879 /*-----------------------------------------------------------------*/
9880 static void genrshTwo (operand *result,operand *left,
9881                        int shCount, int sign)
9882 {
9883   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9884   /* if shCount >= 8 */
9885   if (shCount >= 8) {
9886     shCount -= 8 ;
9887     if (shCount)
9888       shiftR1Left2Result(left, MSB16, result, LSB,
9889                          shCount, sign);
9890     else
9891       movLeft2Result(left, MSB16, result, LSB);
9892
9893     pic16_addSign (result, 1, sign);
9894   }
9895
9896   /*  1 <= shCount <= 7 */
9897   else
9898     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9899 }
9900
9901 /*-----------------------------------------------------------------*/
9902 /* shiftRLong - shift right one long from left to result           */
9903 /* offl = LSB or MSB16                                             */
9904 /*-----------------------------------------------------------------*/
9905 static void shiftRLong (operand *left, int offl,
9906                         operand *result, int sign)
9907 {
9908     int size = AOP_SIZE(result);
9909     int same = pic16_sameRegs(AOP(left),AOP(result));
9910     int i;
9911     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9912
9913         if (same && (offl == MSB16)) { //shift one byte right
9914                 for(i=MSB16;i<size;i++) {
9915                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9916                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9917                 }
9918         }
9919
9920     if(sign)
9921                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9922         else
9923                 emitCLRC;
9924
9925         if (same) {
9926                 if (offl == LSB)
9927                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9928         } else {
9929         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9930         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9931         }
9932
9933     if(offl == MSB16) {
9934         /* add sign of "a" */
9935         pic16_addSign(result, MSB32, sign);
9936         }
9937
9938         if (same) {
9939         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9940         } else {
9941         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9942         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9943         }
9944         
9945         if (same) {
9946         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9947         } else {
9948         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9949         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9950         }
9951
9952         if (same) {
9953         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9954         } else {
9955         if(offl == LSB){
9956                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9957                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9958         }
9959         }
9960 }
9961
9962 /*-----------------------------------------------------------------*/
9963 /* genrshFour - shift four byte by a known amount != 0             */
9964 /*-----------------------------------------------------------------*/
9965 static void genrshFour (operand *result, operand *left,
9966                         int shCount, int sign)
9967 {
9968   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9969   /* if shifting more that 3 bytes */
9970   if(shCount >= 24 ) {
9971     shCount -= 24;
9972     if(shCount)
9973       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9974     else
9975       movLeft2Result(left, MSB32, result, LSB);
9976
9977     pic16_addSign(result, MSB16, sign);
9978   }
9979   else if(shCount >= 16){
9980     shCount -= 16;
9981     if(shCount)
9982       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9983     else{
9984       movLeft2Result(left, MSB24, result, LSB);
9985       movLeft2Result(left, MSB32, result, MSB16);
9986     }
9987     pic16_addSign(result, MSB24, sign);
9988   }
9989   else if(shCount >= 8){
9990     shCount -= 8;
9991     if(shCount == 1)
9992       shiftRLong(left, MSB16, result, sign);
9993     else if(shCount == 0){
9994       movLeft2Result(left, MSB16, result, LSB);
9995       movLeft2Result(left, MSB24, result, MSB16);
9996       movLeft2Result(left, MSB32, result, MSB24);
9997       pic16_addSign(result, MSB32, sign);
9998     }
9999     else{ //shcount >= 2
10000       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10001       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10002       /* the last shift is signed */
10003       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10004       pic16_addSign(result, MSB32, sign);
10005     }
10006   }
10007   else{   /* 1 <= shCount <= 7 */
10008     if(shCount <= 2){
10009       shiftRLong(left, LSB, result, sign);
10010       if(shCount == 2)
10011         shiftRLong(result, LSB, result, sign);
10012     }
10013     else{
10014       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10015       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10016       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10017     }
10018   }
10019 }
10020
10021 /*-----------------------------------------------------------------*/
10022 /* genRightShiftLiteral - right shifting by known count            */
10023 /*-----------------------------------------------------------------*/
10024 static void genRightShiftLiteral (operand *left,
10025                                   operand *right,
10026                                   operand *result,
10027                                   iCode *ic,
10028                                   int sign)
10029 {    
10030   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10031   int lsize,res_size;
10032
10033   pic16_freeAsmop(right,NULL,ic,TRUE);
10034
10035   pic16_aopOp(left,ic,FALSE);
10036   pic16_aopOp(result,ic,TRUE);
10037
10038   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10039
10040 #if VIEW_SIZE
10041   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10042                  AOP_SIZE(left));
10043 #endif
10044
10045   lsize = pic16_getDataSize(left);
10046   res_size = pic16_getDataSize(result);
10047   /* test the LEFT size !!! */
10048
10049   /* I suppose that the left size >= result size */
10050   if(shCount == 0){
10051     assert (res_size <= lsize);
10052     while (res_size--) {
10053       pic16_mov2f (AOP(result), AOP(left), res_size);
10054     } // for
10055   }
10056
10057   else if(shCount >= (lsize * 8)){
10058
10059     if(res_size == 1) {
10060       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10061       if(sign) {
10062         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10063         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10064       }
10065     } else {
10066
10067       if(sign) {
10068         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10069         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10070         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10071         while(res_size--)
10072           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10073
10074       } else {
10075
10076         while(res_size--)
10077           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10078       }
10079     }
10080   } else {
10081
10082     switch (res_size) {
10083     case 1:
10084       genrshOne (result,left,shCount,sign);
10085       break;
10086
10087     case 2:
10088       genrshTwo (result,left,shCount,sign);
10089       break;
10090
10091     case 4:
10092       genrshFour (result,left,shCount,sign);
10093       break;
10094     default :
10095       break;
10096     }
10097
10098   }
10099
10100   pic16_freeAsmop(left,NULL,ic,TRUE);
10101   pic16_freeAsmop(result,NULL,ic,TRUE);
10102 }
10103
10104 #if !(USE_GENERIC_SIGNED_SHIFT)
10105 /*-----------------------------------------------------------------*/
10106 /* genSignedRightShift - right shift of signed number              */
10107 /*-----------------------------------------------------------------*/
10108 static void genSignedRightShift (iCode *ic)
10109 {
10110   operand *right, *left, *result;
10111   int size, offset;
10112   //  char *l;
10113   symbol *tlbl, *tlbl1 ;
10114   pCodeOp *pctemp;
10115
10116   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10117
10118   /* we do it the hard way put the shift count in b
10119      and loop thru preserving the sign */
10120   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10121
10122   right = IC_RIGHT(ic);
10123   left  = IC_LEFT(ic);
10124   result = IC_RESULT(ic);
10125
10126   pic16_aopOp(right,ic,FALSE);  
10127   pic16_aopOp(left,ic,FALSE);
10128   pic16_aopOp(result,ic,FALSE);
10129
10130
10131   if ( AOP_TYPE(right) == AOP_LIT) {
10132     genRightShiftLiteral (left,right,result,ic,1);
10133     return ;
10134   }
10135   /* shift count is unknown then we have to form 
10136      a loop get the loop count in B : Note: we take
10137      only the lower order byte since shifting
10138      more that 32 bits make no sense anyway, ( the
10139      largest size of an object can be only 32 bits ) */  
10140
10141   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10142   //pic16_emitcode("inc","b");
10143   //pic16_freeAsmop (right,NULL,ic,TRUE);
10144   //pic16_aopOp(left,ic,FALSE);
10145   //pic16_aopOp(result,ic,FALSE);
10146
10147   /* now move the left to the result if they are not the
10148      same */
10149   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10150       AOP_SIZE(result) > 1) {
10151
10152     size = AOP_SIZE(result);
10153     offset=0;
10154     while (size--) { 
10155       /*
10156         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10157         if (*l == '@' && IS_AOP_PREG(result)) {
10158
10159         pic16_emitcode("mov","a,%s",l);
10160         pic16_aopPut(AOP(result),"a",offset);
10161         } else
10162         pic16_aopPut(AOP(result),l,offset);
10163       */
10164       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10165       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10166
10167       offset++;
10168     }
10169   }
10170
10171   /* mov the highest order bit to OVR */    
10172   tlbl = newiTempLabel(NULL);
10173   tlbl1= newiTempLabel(NULL);
10174
10175   size = AOP_SIZE(result);
10176   offset = size - 1;
10177
10178   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10179
10180   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10181
10182   /* offset should be 0, 1 or 3 */
10183   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10184   emitSKPNZ;
10185   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10186
10187   pic16_emitpcode(POC_MOVWF, pctemp);
10188
10189
10190   pic16_emitpLabel(tlbl->key);
10191
10192   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10193   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10194
10195   while(--size) {
10196     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10197   }
10198
10199   pic16_emitpcode(POC_DECFSZ,  pctemp);
10200   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10201   pic16_emitpLabel(tlbl1->key);
10202
10203   pic16_popReleaseTempReg(pctemp,1);
10204 #if 0
10205   size = AOP_SIZE(result);
10206   offset = size - 1;
10207   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10208   pic16_emitcode("rlc","a");
10209   pic16_emitcode("mov","ov,c");
10210   /* if it is only one byte then */
10211   if (size == 1) {
10212     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10213     MOVA(l);
10214     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10215     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10216     pic16_emitcode("mov","c,ov");
10217     pic16_emitcode("rrc","a");
10218     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10219     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10220     pic16_aopPut(AOP(result),"a",0);
10221     goto release ;
10222   }
10223
10224   reAdjustPreg(AOP(result));
10225   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10226   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10227   pic16_emitcode("mov","c,ov");
10228   while (size--) {
10229     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10230     MOVA(l);
10231     pic16_emitcode("rrc","a");         
10232     pic16_aopPut(AOP(result),"a",offset--);
10233   }
10234   reAdjustPreg(AOP(result));
10235   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10236   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10237
10238  release:
10239 #endif
10240
10241   pic16_freeAsmop(left,NULL,ic,TRUE);
10242   pic16_freeAsmop(result,NULL,ic,TRUE);
10243   pic16_freeAsmop(right,NULL,ic,TRUE);
10244 }
10245 #endif
10246
10247 #if !(USE_GENERIC_SIGNED_SHIFT)
10248 #warning This implementation of genRightShift() is incomplete!
10249 /*-----------------------------------------------------------------*/
10250 /* genRightShift - generate code for right shifting                */
10251 /*-----------------------------------------------------------------*/
10252 static void genRightShift (iCode *ic)
10253 {
10254     operand *right, *left, *result;
10255     sym_link *letype ;
10256     int size, offset;
10257     char *l;
10258     symbol *tlbl, *tlbl1 ;
10259
10260     /* if signed then we do it the hard way preserve the
10261     sign bit moving it inwards */
10262     letype = getSpec(operandType(IC_LEFT(ic)));
10263     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10264
10265     if (!SPEC_USIGN(letype)) {
10266         genSignedRightShift (ic);
10267         return ;
10268     }
10269
10270     /* signed & unsigned types are treated the same : i.e. the
10271     signed is NOT propagated inwards : quoting from the
10272     ANSI - standard : "for E1 >> E2, is equivalent to division
10273     by 2**E2 if unsigned or if it has a non-negative value,
10274     otherwise the result is implementation defined ", MY definition
10275     is that the sign does not get propagated */
10276
10277     right = IC_RIGHT(ic);
10278     left  = IC_LEFT(ic);
10279     result = IC_RESULT(ic);
10280
10281     pic16_aopOp(right,ic,FALSE);
10282
10283     /* if the shift count is known then do it 
10284     as efficiently as possible */
10285     if (AOP_TYPE(right) == AOP_LIT) {
10286         genRightShiftLiteral (left,right,result,ic, 0);
10287         return ;
10288     }
10289
10290     /* shift count is unknown then we have to form 
10291     a loop get the loop count in B : Note: we take
10292     only the lower order byte since shifting
10293     more that 32 bits make no sense anyway, ( the
10294     largest size of an object can be only 32 bits ) */  
10295
10296     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10297     pic16_emitcode("inc","b");
10298     pic16_aopOp(left,ic,FALSE);
10299     pic16_aopOp(result,ic,FALSE);
10300
10301     /* now move the left to the result if they are not the
10302     same */
10303     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10304         AOP_SIZE(result) > 1) {
10305
10306         size = AOP_SIZE(result);
10307         offset=0;
10308         while (size--) {
10309             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10310             if (*l == '@' && IS_AOP_PREG(result)) {
10311
10312                 pic16_emitcode("mov","a,%s",l);
10313                 pic16_aopPut(AOP(result),"a",offset);
10314             } else
10315                 pic16_aopPut(AOP(result),l,offset);
10316             offset++;
10317         }
10318     }
10319
10320     tlbl = newiTempLabel(NULL);
10321     tlbl1= newiTempLabel(NULL);
10322     size = AOP_SIZE(result);
10323     offset = size - 1;
10324
10325     /* if it is only one byte then */
10326     if (size == 1) {
10327
10328       tlbl = newiTempLabel(NULL);
10329       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10330         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10331         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10332       }
10333
10334       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10335       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10336       pic16_emitpLabel(tlbl->key);
10337       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10338       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10339       emitSKPC;
10340       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10341
10342       goto release ;
10343     }
10344
10345     reAdjustPreg(AOP(result));
10346     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10347     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10348     CLRC;
10349     while (size--) {
10350         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10351         MOVA(l);
10352         pic16_emitcode("rrc","a");         
10353         pic16_aopPut(AOP(result),"a",offset--);
10354     }
10355     reAdjustPreg(AOP(result));
10356
10357     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10358     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10359
10360 release:
10361     pic16_freeAsmop(left,NULL,ic,TRUE);
10362     pic16_freeAsmop (right,NULL,ic,TRUE);
10363     pic16_freeAsmop(result,NULL,ic,TRUE);
10364 }
10365 #endif
10366
10367 #if (USE_GENERIC_SIGNED_SHIFT)
10368 /*-----------------------------------------------------------------*/
10369 /* genGenericShift - generates code for left or right shifting     */
10370 /*-----------------------------------------------------------------*/
10371 static void genGenericShift (iCode *ic, int isShiftLeft) {
10372   operand *left,*right, *result;
10373   int offset;
10374   int sign, signedCount;
10375   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10376   PIC_OPCODE pos_shift, neg_shift;
10377
10378   FENTRY;
10379
10380   right = IC_RIGHT(ic);
10381   left  = IC_LEFT(ic);
10382   result = IC_RESULT(ic);
10383
10384   pic16_aopOp(right,ic,FALSE);
10385   pic16_aopOp(left,ic,FALSE);
10386   pic16_aopOp(result,ic,TRUE);
10387
10388   sign = !SPEC_USIGN(operandType (left));
10389   signedCount = !SPEC_USIGN(operandType (right));
10390
10391   /* if the shift count is known then do it 
10392      as efficiently as possible */
10393   if (AOP_TYPE(right) == AOP_LIT) {
10394     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10395     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10396     // we should modify right->aopu.aop_lit here!
10397     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10398     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10399     if (isShiftLeft)
10400       pic16_genLeftShiftLiteral (left,right,result,ic);
10401     else
10402       genRightShiftLiteral (left,right,result,ic, sign);
10403
10404     goto release;
10405   } // if (right is literal)
10406
10407   /* shift count is unknown then we have to form a loop.
10408    * Note: we take only the lower order byte since shifting
10409    * more than 32 bits make no sense anyway, ( the
10410    * largest size of an object can be only 32 bits )
10411    * Note: we perform arithmetic shifts if the left operand is
10412    * signed and we do an (effective) right shift, i. e. we
10413    * shift in the sign bit from the left. */
10414    
10415   label_complete = newiTempLabel ( NULL );
10416   label_loop_pos = newiTempLabel ( NULL );
10417   label_loop_neg = NULL;
10418   label_negative = NULL;
10419   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10420   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10421
10422   if (signedCount) {
10423     // additional labels needed
10424     label_loop_neg = newiTempLabel ( NULL );
10425     label_negative = newiTempLabel ( NULL );
10426   } // if
10427
10428   // copy source to result -- this will effectively truncate the left operand to the size of result!
10429   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10430   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10431   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10432     pic16_mov2f (AOP(result),AOP(left), offset);
10433   } // for
10434
10435   // if result is longer than left, fill with zeros (or sign)
10436   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10437     if (sign && AOP_SIZE(left) > 0) {
10438       // shift signed operand -- fill with sign
10439       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10440       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10441       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10442       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10443         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10444       } // for
10445     } else {
10446       // shift unsigned operand -- fill result with zeros
10447       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10448         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10449       } // for
10450     }
10451   } // if (size mismatch)
10452
10453   pic16_mov2w (AOP(right), 0);
10454   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10455   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10456   
10457 #if 0
10458   // perform a shift by one (shift count is positive)
10459   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10460   // 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])
10461   pic16_emitpLabel (label_loop_pos->key);
10462   emitCLRC;
10463   if (sign && (pos_shift == POC_RRCF)) {
10464     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10465     emitSETC;
10466   } // if
10467   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10468   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10469   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10470 #else
10471   // perform a shift by one (shift count is positive)
10472   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10473   // 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])
10474   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10475   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10476   emitCLRC;
10477   pic16_emitpLabel (label_loop_pos->key);
10478   if (sign && (pos_shift == POC_RRCF)) {
10479     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10480     emitSETC;
10481   } // if
10482   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10483   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10484   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10485   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10486 #endif
10487
10488   if (signedCount) {
10489     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10490
10491     pic16_emitpLabel (label_negative->key);
10492     // perform a shift by -1 (shift count is negative)
10493     // 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)
10494     emitCLRC;
10495     pic16_emitpLabel (label_loop_neg->key);
10496     if (sign && (neg_shift == POC_RRCF)) {
10497       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10498       emitSETC;
10499     } // if
10500     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10501     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10502     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10503     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10504   } // if (signedCount)
10505
10506   pic16_emitpLabel (label_complete->key);
10507
10508 release:
10509   pic16_freeAsmop (right,NULL,ic,TRUE);
10510   pic16_freeAsmop(left,NULL,ic,TRUE);
10511   pic16_freeAsmop(result,NULL,ic,TRUE);
10512 }
10513
10514 static void genLeftShift (iCode *ic) {
10515   genGenericShift (ic, 1);
10516 }
10517
10518 static void genRightShift (iCode *ic) {
10519   genGenericShift (ic, 0);
10520 }
10521 #endif
10522
10523
10524 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10525 void pic16_loadFSR0(operand *op, int lit)
10526 {
10527   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10528     if (AOP_TYPE(op) == AOP_LIT) {
10529       /* handle 12 bit integers correctly */
10530       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10531       if ((val & 0x0fff) != val) {
10532         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10533                 val, (val & 0x0fff) );
10534         val &= 0x0fff;
10535       }
10536       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10537     } else {
10538       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10539     }
10540   } else {
10541     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10542     // set up FSR0 with address of result
10543     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10544     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10545   }
10546 }
10547
10548 /*----------------------------------------------------------------*/
10549 /* pic16_derefPtr - move one byte from the location ptr points to */
10550 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10551 /*                  to the location ptr points to (doWrite != 0)   */
10552 /*----------------------------------------------------------------*/
10553 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10554 {
10555   if (!IS_PTR(operandType(ptr)))
10556   {
10557     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10558     else pic16_mov2w (AOP(ptr), 0);
10559     return;
10560   }
10561
10562   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10563   /* We might determine pointer type right here: */
10564   p_type = DCL_TYPE(operandType(ptr));
10565
10566   switch (p_type) {
10567     case FPOINTER:
10568     case POINTER:
10569       if (!fsr0_setup || !*fsr0_setup)
10570       {
10571         pic16_loadFSR0( ptr, 0 );
10572         if (fsr0_setup) *fsr0_setup = 1;
10573       }
10574       if (doWrite)
10575         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10576       else
10577         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10578       break;
10579
10580     case GPOINTER:
10581       if (AOP(ptr)->aopu.aop_reg[2]) {
10582         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10583         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10584         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10585         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10586         pic16_mov2w(AOP(ptr), 2);
10587         pic16_callGenericPointerRW(doWrite, 1);
10588       } else {
10589         // data pointer (just 2 byte given)
10590         if (!fsr0_setup || !*fsr0_setup)
10591         {
10592           pic16_loadFSR0( ptr, 0 );
10593           if (fsr0_setup) *fsr0_setup = 1;
10594         }
10595         if (doWrite)
10596           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10597         else
10598           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10599       }
10600       break;
10601
10602     default:
10603       assert (0 && "invalid pointer type specified");
10604       break;
10605   }
10606 }
10607
10608 /*-----------------------------------------------------------------*/
10609 /* genUnpackBits - generates code for unpacking bits               */
10610 /*-----------------------------------------------------------------*/
10611 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10612 {    
10613   int shCnt ;
10614   sym_link *etype, *letype;
10615   int blen=0, bstr=0;
10616   int lbstr;
10617   int same;
10618   pCodeOp *op;
10619
10620   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10621   etype = getSpec(operandType(result));
10622   letype = getSpec(operandType(left));
10623
10624   //    if(IS_BITFIELD(etype)) {
10625   blen = SPEC_BLEN(etype);
10626   bstr = SPEC_BSTR(etype);
10627   //    }
10628
10629   lbstr = SPEC_BSTR( letype );
10630
10631   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10632       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10633
10634 #if 1
10635   if((blen == 1) && (bstr < 8)
10636       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10637     /* it is a single bit, so use the appropriate bit instructions */
10638     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10639
10640     same = pic16_sameRegs(AOP(left),AOP(result));
10641     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10642     pic16_emitpcode(POC_CLRF, op);
10643
10644     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10645       /* workaround to reduce the extra lfsr instruction */
10646       pic16_emitpcode(POC_BTFSC,
10647           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10648     } else {
10649       assert (PIC_IS_DATA_PTR (operandType(left)));
10650       pic16_loadFSR0 (left, 0);
10651       pic16_emitpcode(POC_BTFSC,
10652           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10653     }
10654
10655     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10656       /* unsigned bitfields result in either 0 or 1 */
10657       pic16_emitpcode(POC_INCF, op);
10658     } else {
10659       /* signed bitfields result in either 0 or -1 */
10660       pic16_emitpcode(POC_DECF, op);
10661     }
10662     if (same) {
10663       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10664     }
10665
10666     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10667     return;
10668   }
10669
10670 #endif
10671
10672   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10673     // access symbol directly
10674     pic16_mov2w (AOP(left), 0);
10675   } else {
10676     pic16_derefPtr (left, ptype, 0, NULL);
10677   }
10678
10679   /* if we have bitdisplacement then it fits   */
10680   /* into this byte completely or if length is */
10681   /* less than a byte                          */
10682   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10683
10684     /* shift right acc */
10685     AccRsh(shCnt, 0);
10686
10687     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10688           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10689
10690     /* VR -- normally I would use the following, but since we use the hack,
10691      * to avoid the masking from AccRsh, why not mask it right now? */
10692
10693     /*
10694        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10695      */
10696
10697     /* extend signed bitfields to 8 bits */
10698     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10699     {
10700       assert (blen + bstr > 0);
10701       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10702       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10703     }
10704
10705     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10706
10707     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10708     return ;
10709   }
10710
10711   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10712   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10713   exit(-1);
10714
10715   return ;
10716 }
10717
10718
10719 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10720 {
10721   int size, offset = 0, leoffset=0 ;
10722
10723         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10724         pic16_aopOp(result, ic, TRUE);
10725
10726         FENTRY;
10727
10728         size = AOP_SIZE(result);
10729 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10730
10731
10732 #if 1
10733         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10734                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10735                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10736                 goto release;
10737         }
10738 #endif
10739
10740         if(AOP(left)->aopu.pcop->type == PO_DIR)
10741                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10742
10743         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10744
10745         while (size--) {
10746                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10747                 
10748 //              pic16_DumpOp("(result)",result);
10749                 if(is_LitAOp(AOP(result))) {
10750                         pic16_mov2w(AOP(left), offset); // patch 8
10751                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10752                 } else {
10753                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10754                                 pic16_popGet(AOP(left), offset), //patch 8
10755                                 pic16_popGet(AOP(result), offset)));
10756                 }
10757
10758                 offset++;
10759                 leoffset++;
10760         }
10761
10762 release:
10763     pic16_freeAsmop(result,NULL,ic,TRUE);
10764 }
10765
10766
10767
10768 /*-----------------------------------------------------------------*/
10769 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10770 /*-----------------------------------------------------------------*/
10771 static void genNearPointerGet (operand *left, 
10772                                operand *result, 
10773                                iCode *ic)
10774 {
10775 //  asmop *aop = NULL;
10776   //regs *preg = NULL ;
10777   sym_link *rtype, *retype;
10778   sym_link *ltype, *letype;
10779
10780     FENTRY;
10781     
10782     rtype = operandType(result);
10783     retype= getSpec(rtype);
10784     ltype = operandType(left);
10785     letype= getSpec(ltype);
10786     
10787     pic16_aopOp(left,ic,FALSE);
10788
10789 //    pic16_DumpOp("(left)",left);
10790 //    pic16_DumpOp("(result)",result);
10791
10792     /* if left is rematerialisable and
10793      * result is not bit variable type and
10794      * the left is pointer to data space i.e
10795      * lower 128 bytes of space */
10796     
10797     if (AOP_TYPE(left) == AOP_PCODE
10798       && !IS_BITFIELD(retype)
10799       && DCL_TYPE(ltype) == POINTER) {
10800
10801         genDataPointerGet (left,result,ic);
10802         pic16_freeAsmop(left, NULL, ic, TRUE);
10803         return ;
10804     }
10805     
10806     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10807     pic16_aopOp (result,ic,TRUE);
10808     
10809     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10810
10811 #if 1
10812     if(IS_BITFIELD( retype )
10813       && (SPEC_BLEN(operandType(result))==1)
10814     ) {
10815       iCode *nextic;
10816       pCodeOp *jop;
10817       int bitstrt, bytestrt;
10818
10819         /* if this is bitfield of size 1, see if we are checking the value
10820          * of a single bit in an if-statement,
10821          * if yes, then don't generate usual code, but execute the
10822          * genIfx directly -- VR */
10823
10824         nextic = ic->next;
10825
10826         /* CHECK: if next iCode is IFX
10827          * and current result operand is nextic's conditional operand
10828          * and current result operand live ranges ends at nextic's key number
10829          */
10830         if((nextic->op == IFX)
10831           && (result == IC_COND(nextic))
10832           && (OP_LIVETO(result) == nextic->seq)
10833           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10834           ) {
10835             /* everything is ok then */
10836             /* find a way to optimize the genIfx iCode */
10837
10838             bytestrt = SPEC_BSTR(operandType(result))/8;
10839             bitstrt = SPEC_BSTR(operandType(result))%8;
10840             
10841             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10842
10843             genIfxpCOpJump(nextic, jop);
10844             
10845             pic16_freeAsmop(left, NULL, ic, TRUE);
10846             pic16_freeAsmop(result, NULL, ic, TRUE);
10847             return;
10848         }
10849     }
10850 #endif
10851
10852     /* if bitfield then unpack the bits */
10853     if (IS_BITFIELD(letype)) 
10854       genUnpackBits (result, left, NULL, POINTER);
10855     else {
10856       /* we have can just get the values */
10857       int size = AOP_SIZE(result);
10858       int offset = 0;   
10859         
10860       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10861
10862       pic16_loadFSR0( left, 0 );
10863
10864       while(size--) {
10865         if(size) {
10866           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10867                 pic16_popGet(AOP(result), offset++)));
10868         } else {
10869           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10870                 pic16_popGet(AOP(result), offset++)));
10871         }
10872       }
10873     }
10874
10875 #if 0
10876     /* now some housekeeping stuff */
10877     if (aop) {
10878       /* we had to allocate for this iCode */
10879       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10880       pic16_freeAsmop(NULL,aop,ic,TRUE);
10881     } else { 
10882       /* we did not allocate which means left
10883        * already in a pointer register, then
10884        * if size > 0 && this could be used again
10885        * we have to point it back to where it 
10886        * belongs */
10887       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10888       if (AOP_SIZE(result) > 1
10889         && !OP_SYMBOL(left)->remat
10890         && ( OP_SYMBOL(left)->liveTo > ic->seq
10891             || ic->depth )) {
10892 //        int size = AOP_SIZE(result) - 1;
10893 //        while (size--)
10894 //          pic16_emitcode("dec","%s",rname);
10895         }
10896     }
10897 #endif
10898
10899     /* done */
10900     pic16_freeAsmop(left,NULL,ic,TRUE);
10901     pic16_freeAsmop(result,NULL,ic,TRUE);
10902 }
10903
10904 /*-----------------------------------------------------------------*/
10905 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10906 /*-----------------------------------------------------------------*/
10907 static void genPagedPointerGet (operand *left, 
10908                                operand *result, 
10909                                iCode *ic)
10910 {
10911     asmop *aop = NULL;
10912     regs *preg = NULL ;
10913     char *rname ;
10914     sym_link *rtype, *retype;    
10915
10916     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10917
10918     rtype = operandType(result);
10919     retype= getSpec(rtype);
10920     
10921     pic16_aopOp(left,ic,FALSE);
10922
10923   /* if the value is already in a pointer register
10924        then don't need anything more */
10925     if (!AOP_INPREG(AOP(left))) {
10926         /* otherwise get a free pointer register */
10927         aop = newAsmop(0);
10928         preg = getFreePtr(ic,&aop,FALSE);
10929         pic16_emitcode("mov","%s,%s",
10930                 preg->name,
10931                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10932         rname = preg->name ;
10933     } else
10934         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10935     
10936     pic16_freeAsmop(left,NULL,ic,TRUE);
10937     pic16_aopOp (result,ic,TRUE);
10938
10939     /* if bitfield then unpack the bits */
10940     if (IS_BITFIELD(retype)) 
10941         genUnpackBits (result,left,rname,PPOINTER);
10942     else {
10943         /* we have can just get the values */
10944         int size = AOP_SIZE(result);
10945         int offset = 0 ;        
10946         
10947         while (size--) {
10948             
10949             pic16_emitcode("movx","a,@%s",rname);
10950             pic16_aopPut(AOP(result),"a",offset);
10951             
10952             offset++ ;
10953             
10954             if (size)
10955                 pic16_emitcode("inc","%s",rname);
10956         }
10957     }
10958
10959     /* now some housekeeping stuff */
10960     if (aop) {
10961         /* we had to allocate for this iCode */
10962         pic16_freeAsmop(NULL,aop,ic,TRUE);
10963     } else { 
10964         /* we did not allocate which means left
10965            already in a pointer register, then
10966            if size > 0 && this could be used again
10967            we have to point it back to where it 
10968            belongs */
10969         if (AOP_SIZE(result) > 1 &&
10970             !OP_SYMBOL(left)->remat &&
10971             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10972               ic->depth )) {
10973             int size = AOP_SIZE(result) - 1;
10974             while (size--)
10975                 pic16_emitcode("dec","%s",rname);
10976         }
10977     }
10978
10979     /* done */
10980     pic16_freeAsmop(result,NULL,ic,TRUE);
10981     
10982         
10983 }
10984
10985 #if 0
10986 /* This code is not adjusted to PIC16 and fails utterly.
10987  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10988
10989 /*-----------------------------------------------------------------*/
10990 /* genFarPointerGet - gget value from far space                    */
10991 /*-----------------------------------------------------------------*/
10992 static void genFarPointerGet (operand *left,
10993                               operand *result, iCode *ic)
10994 {
10995     int size, offset ;
10996     sym_link *retype = getSpec(operandType(result));
10997
10998     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10999
11000     pic16_aopOp(left,ic,FALSE);
11001
11002     /* if the operand is already in dptr 
11003     then we do nothing else we move the value to dptr */
11004     if (AOP_TYPE(left) != AOP_STR) {
11005         /* if this is remateriazable */
11006         if (AOP_TYPE(left) == AOP_IMMD)
11007             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11008         else { /* we need to get it byte by byte */
11009             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11010             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11011             if (options.model == MODEL_FLAT24)
11012             {
11013                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11014             }
11015         }
11016     }
11017     /* so dptr know contains the address */
11018     pic16_freeAsmop(left,NULL,ic,TRUE);
11019     pic16_aopOp(result,ic,TRUE);
11020
11021     /* if bit then unpack */
11022     if (IS_BITFIELD(retype)) 
11023         genUnpackBits(result,left,"dptr",FPOINTER);
11024     else {
11025         size = AOP_SIZE(result);
11026         offset = 0 ;
11027
11028         while (size--) {
11029             pic16_emitcode("movx","a,@dptr");
11030             pic16_aopPut(AOP(result),"a",offset++);
11031             if (size)
11032                 pic16_emitcode("inc","dptr");
11033         }
11034     }
11035
11036     pic16_freeAsmop(result,NULL,ic,TRUE);
11037 }
11038 #endif
11039
11040 #if 0
11041 /*-----------------------------------------------------------------*/
11042 /* genCodePointerGet - get value from code space                  */
11043 /*-----------------------------------------------------------------*/
11044 static void genCodePointerGet (operand *left,
11045                                 operand *result, iCode *ic)
11046 {
11047     int size, offset ;
11048     sym_link *retype = getSpec(operandType(result));
11049
11050     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11051
11052     pic16_aopOp(left,ic,FALSE);
11053
11054     /* if the operand is already in dptr 
11055     then we do nothing else we move the value to dptr */
11056     if (AOP_TYPE(left) != AOP_STR) {
11057         /* if this is remateriazable */
11058         if (AOP_TYPE(left) == AOP_IMMD)
11059             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11060         else { /* we need to get it byte by byte */
11061             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11062             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11063             if (options.model == MODEL_FLAT24)
11064             {
11065                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11066             }
11067         }
11068     }
11069     /* so dptr know contains the address */
11070     pic16_freeAsmop(left,NULL,ic,TRUE);
11071     pic16_aopOp(result,ic,FALSE);
11072
11073     /* if bit then unpack */
11074     if (IS_BITFIELD(retype)) 
11075         genUnpackBits(result,left,"dptr",CPOINTER);
11076     else {
11077         size = AOP_SIZE(result);
11078         offset = 0 ;
11079
11080         while (size--) {
11081             pic16_emitcode("clr","a");
11082             pic16_emitcode("movc","a,@a+dptr");
11083             pic16_aopPut(AOP(result),"a",offset++);
11084             if (size)
11085                 pic16_emitcode("inc","dptr");
11086         }
11087     }
11088
11089     pic16_freeAsmop(result,NULL,ic,TRUE);
11090 }
11091 #endif
11092
11093 #if 0
11094 /*-----------------------------------------------------------------*/
11095 /* genGenPointerGet - gget value from generic pointer space        */
11096 /*-----------------------------------------------------------------*/
11097 static void genGenPointerGet (operand *left,
11098                               operand *result, iCode *ic)
11099 {
11100   int size, offset, lit;
11101   sym_link *retype = getSpec(operandType(result));
11102
11103         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11104         pic16_aopOp(left,ic,FALSE);
11105         pic16_aopOp(result,ic,FALSE);
11106         size = AOP_SIZE(result);
11107
11108         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11109
11110         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11111
11112                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11113                 // load FSR0 from immediate
11114                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11115
11116 //              pic16_loadFSR0( left );
11117
11118                 offset = 0;
11119                 while(size--) {
11120                         if(size) {
11121                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11122                         } else {
11123                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11124                         }
11125                         offset++;
11126                 }
11127                 goto release;
11128
11129         }
11130         else { /* we need to get it byte by byte */
11131                 // set up FSR0 with address from left
11132                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11133                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11134                 
11135                 offset = 0 ;
11136
11137                 while(size--) {
11138                         if(size) {
11139                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11140                         } else {
11141                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11142                         }
11143                         offset++;
11144                 }
11145                 goto release;
11146         }
11147
11148   /* if bit then unpack */
11149         if (IS_BITFIELD(retype)) 
11150                 genUnpackBits(result,left,"BAD",GPOINTER);
11151
11152         release:
11153         pic16_freeAsmop(left,NULL,ic,TRUE);
11154         pic16_freeAsmop(result,NULL,ic,TRUE);
11155
11156 }
11157 #endif
11158
11159
11160 /*-----------------------------------------------------------------*/
11161 /* genGenPointerGet - gget value from generic pointer space        */
11162 /*-----------------------------------------------------------------*/
11163 static void genGenPointerGet (operand *left,
11164                               operand *result, iCode *ic)
11165 {
11166   int size, offset, lit;
11167   sym_link *letype = getSpec(operandType(left));
11168
11169     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11170     pic16_aopOp(left,ic,FALSE);
11171     pic16_aopOp(result,ic,TRUE);
11172     size = AOP_SIZE(result);
11173
11174     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11175   
11176     /* if bit then unpack */
11177     if (IS_BITFIELD(letype)) {
11178       genUnpackBits(result,left,"BAD",GPOINTER);
11179       goto release;
11180     }
11181
11182     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11183
11184       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11185       // load FSR0 from immediate
11186       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11187
11188       werror(W_POSSBUG2, __FILE__, __LINE__);
11189
11190       offset = 0;
11191       while(size--) {
11192         if(size) {
11193           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11194         } else {
11195           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11196         }
11197         offset++;
11198       }
11199
11200       goto release;
11201
11202     } else { /* we need to get it byte by byte */
11203
11204       /* set up WREG:PRODL:FSR0L with address from left */
11205       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11206       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11207       pic16_mov2w(AOP(left), 2);
11208       pic16_callGenericPointerRW(0, size);
11209       
11210       assignResultValue(result, 1);
11211       
11212       goto release;
11213     }
11214
11215 release:
11216   pic16_freeAsmop(left,NULL,ic,TRUE);
11217   pic16_freeAsmop(result,NULL,ic,TRUE);
11218 }
11219
11220 /*-----------------------------------------------------------------*/
11221 /* genConstPointerGet - get value from const generic pointer space */
11222 /*-----------------------------------------------------------------*/
11223 static void genConstPointerGet (operand *left,
11224                                 operand *result, iCode *ic)
11225 {
11226   //sym_link *retype = getSpec(operandType(result));
11227   // symbol *albl = newiTempLabel(NULL);        // patch 15
11228   // symbol *blbl = newiTempLabel(NULL);        //
11229   // PIC_OPCODE poc;                            // patch 15
11230   int size;
11231   int offset = 0;
11232
11233   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11234   pic16_aopOp(left,ic,FALSE);
11235   pic16_aopOp(result,ic,TRUE);
11236   size = AOP_SIZE(result);
11237
11238   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11239
11240   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11241
11242   // set up table pointer
11243   if( (AOP_TYPE(left) == AOP_PCODE) 
11244       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11245           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11246     {
11247       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11248       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11249       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11250       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11251       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11252       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11253   } else {
11254     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11255     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11256     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11257   }
11258
11259   while(size--) {
11260     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11261     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11262     offset++;
11263   }
11264     
11265   pic16_freeAsmop(left,NULL,ic,TRUE);
11266   pic16_freeAsmop(result,NULL,ic,TRUE);
11267 }
11268
11269
11270 /*-----------------------------------------------------------------*/
11271 /* genPointerGet - generate code for pointer get                   */
11272 /*-----------------------------------------------------------------*/
11273 static void genPointerGet (iCode *ic)
11274 {
11275   operand *left, *result ;
11276   sym_link *type, *etype;
11277   int p_type;
11278
11279     FENTRY;
11280     
11281     left = IC_LEFT(ic);
11282     result = IC_RESULT(ic) ;
11283
11284     /* depending on the type of pointer we need to
11285     move it to the correct pointer register */
11286     type = operandType(left);
11287     etype = getSpec(type);
11288
11289 #if 0
11290     if (IS_PTR_CONST(type))
11291 #else
11292     if (IS_CODEPTR(type))
11293 #endif
11294       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11295
11296     /* if left is of type of pointer then it is simple */
11297     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11298       p_type = DCL_TYPE(type);
11299     else {
11300       /* we have to go by the storage class */
11301       p_type = PTR_TYPE(SPEC_OCLS(etype));
11302
11303       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11304
11305       if (SPEC_OCLS(etype)->codesp ) {
11306         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11307         //p_type = CPOINTER ;   
11308       } else
11309       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11310         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11311         /*p_type = FPOINTER ;*/ 
11312       } else
11313       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11314         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11315         /* p_type = PPOINTER; */
11316       } else
11317       if (SPEC_OCLS(etype) == idata ) {
11318         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11319         /* p_type = IPOINTER; */
11320       } else {
11321         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11322         /* p_type = POINTER ; */
11323       }
11324     }
11325
11326     /* now that we have the pointer type we assign
11327     the pointer values */
11328     switch (p_type) {
11329       case POINTER:     
11330       case FPOINTER:
11331       case IPOINTER:
11332         genNearPointerGet (left,result,ic);
11333         break;
11334
11335       case PPOINTER:
11336         genPagedPointerGet(left,result,ic);
11337         break;
11338
11339 #if 0
11340       /* PICs do not support FAR pointers... */
11341       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11342       case FPOINTER:
11343         genFarPointerGet (left,result,ic);
11344         break;
11345 #endif
11346
11347       case CPOINTER:
11348         genConstPointerGet (left,result,ic);
11349         //pic16_emitcodePointerGet (left,result,ic);
11350         break;
11351
11352       case GPOINTER:
11353 #if 0
11354       if (IS_PTR_CONST(type))
11355         genConstPointerGet (left,result,ic);
11356       else
11357 #endif
11358         genGenPointerGet (left,result,ic);
11359       break;
11360
11361     default:
11362       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11363               "genPointerGet: illegal pointer type");
11364     
11365     }
11366 }
11367
11368 /*-----------------------------------------------------------------*/
11369 /* genPackBits - generates code for packed bit storage             */
11370 /*-----------------------------------------------------------------*/
11371 static void genPackBits (sym_link    *etype , operand *result,
11372                          operand *right ,
11373                          char *rname, int p_type)
11374 {
11375   int shCnt = 0 ;
11376   int offset = 0  ;
11377   int rLen = 0 ;
11378   int blen, bstr ;   
11379   int shifted_and_masked = 0;
11380   unsigned long lit = (unsigned long)-1;
11381   sym_link *retype;
11382
11383   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11384   blen = SPEC_BLEN(etype);
11385   bstr = SPEC_BSTR(etype);
11386
11387   retype = getSpec(operandType(right));
11388
11389   if(AOP_TYPE(right) == AOP_LIT) {
11390     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11391     
11392     if((blen == 1) && (bstr < 8)) {
11393       /* it is a single bit, so use the appropriate bit instructions */
11394
11395       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11396
11397       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11398         /* workaround to reduce the extra lfsr instruction */
11399         if(lit) {
11400           pic16_emitpcode(POC_BSF,
11401               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11402         } else {
11403           pic16_emitpcode(POC_BCF,
11404               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11405         }
11406       } else {
11407         if (PIC_IS_DATA_PTR(operandType(result))) {
11408           pic16_loadFSR0(result, 0);
11409           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11410               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11411         } else {
11412           /* get old value */
11413           pic16_derefPtr (result, p_type, 0, NULL);
11414           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11415               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11416           /* write back new value */
11417           pic16_derefPtr (result, p_type, 1, NULL);
11418         }
11419       }
11420
11421       return;
11422     }
11423     /* IORLW below is more efficient */
11424     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11425     lit = (lit & ((1UL << blen) - 1)) << bstr;
11426     shifted_and_masked = 1;
11427     offset++;
11428   } else
11429     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11430         && IS_BITFIELD(retype) 
11431         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11432         && (blen == 1)) {
11433       int rblen, rbstr;
11434
11435       rblen = SPEC_BLEN( retype );
11436       rbstr = SPEC_BSTR( retype );
11437
11438       if(IS_BITFIELD(etype)) {
11439         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11440         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11441       } else {
11442         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11443       }
11444
11445       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11446
11447       if(IS_BITFIELD(etype)) {
11448         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11449       } else {
11450         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11451       }
11452
11453       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11454
11455       return;
11456     } else {
11457       /* move right to W */
11458       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11459     }
11460
11461   /* if the bit length is less than or   */
11462   /* it exactly fits a byte then         */
11463   if((shCnt=SPEC_BSTR(etype))
11464       || SPEC_BLEN(etype) <= 8 )  {
11465     int fsr0_setup = 0;
11466
11467     if (blen != 8 || bstr != 0) {
11468       // we need to combine the value with the old value
11469       if(!shifted_and_masked)
11470       {
11471         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11472
11473         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11474             SPEC_BSTR(etype), SPEC_BLEN(etype));
11475
11476         /* shift left acc, do NOT mask the result again */
11477         AccLsh(shCnt, 0);
11478
11479         /* using PRODH as a temporary register here */
11480         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11481       }
11482
11483       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11484         || IS_DIRECT(result)) {
11485         /* access symbol directly */
11486         pic16_mov2w (AOP(result), 0);
11487       } else {
11488         /* get old value */
11489         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11490       }
11491 #if 1
11492       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11493             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11494                             (unsigned char)(0xff >> (8-bstr))) ));
11495       if (!shifted_and_masked) {
11496         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11497       } else {
11498         /* We have the shifted and masked (literal) right value in `lit' */
11499         if (lit != 0)
11500           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11501       }
11502     } // if (blen != 8 || bstr != 0)
11503
11504     /* write new value back */
11505     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11506         || IS_DIRECT(result)) {
11507       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11508     } else {
11509       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11510     }
11511 #endif
11512
11513     return;
11514   }
11515
11516
11517 #if 0
11518   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11519   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11520   exit(-1);
11521 #endif
11522
11523
11524   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11525   rLen = SPEC_BLEN(etype)-8;
11526
11527   /* now generate for lengths greater than one byte */
11528   while (1) {
11529     rLen -= 8 ;
11530     if (rLen <= 0 ) {
11531       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11532       break ;
11533     }
11534
11535     switch (p_type) {
11536       case POINTER:
11537         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11538         break;
11539
11540         /*
11541            case FPOINTER:
11542            MOVA(l);
11543            pic16_emitcode("movx","@dptr,a");
11544            break;
11545
11546            case GPOINTER:
11547            MOVA(l);
11548            DEBUGpic16_emitcode(";lcall","__gptrput");
11549            break;  
11550          */
11551       default:
11552         assert(0);
11553     }   
11554
11555
11556     pic16_mov2w(AOP(right), offset++);
11557   }
11558
11559   /* last last was not complete */
11560   if (rLen)   {
11561     /* save the byte & read byte */
11562     switch (p_type) {
11563       case POINTER:
11564         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11565         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11566         break;
11567
11568         /*
11569            case FPOINTER:
11570            pic16_emitcode ("mov","b,a");
11571            pic16_emitcode("movx","a,@dptr");
11572            break;
11573
11574            case GPOINTER:
11575            pic16_emitcode ("push","b");
11576            pic16_emitcode ("push","acc");
11577            pic16_emitcode ("lcall","__gptrget");
11578            pic16_emitcode ("pop","b");
11579            break;
11580          */
11581       default:
11582         assert(0);
11583     }
11584     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11585     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11586     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11587     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11588     //        pic16_emitcode ("orl","a,b");
11589   }
11590
11591   //    if (p_type == GPOINTER)
11592   //        pic16_emitcode("pop","b");
11593
11594   switch (p_type) {
11595
11596     case POINTER:
11597       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11598       //        pic16_emitcode("mov","@%s,a",rname);
11599       break;
11600       /*
11601          case FPOINTER:
11602          pic16_emitcode("movx","@dptr,a");
11603          break;
11604
11605          case GPOINTER:
11606          DEBUGpic16_emitcode(";lcall","__gptrput");
11607          break;                 
11608        */
11609     default:
11610       assert(0);
11611   }
11612
11613   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11614 }
11615
11616 /*-----------------------------------------------------------------*/
11617 /* genDataPointerSet - remat pointer to data space                 */
11618 /*-----------------------------------------------------------------*/
11619 static void genDataPointerSet(operand *right,
11620                               operand *result,
11621                               iCode *ic)
11622 {
11623   int size, offset = 0, resoffset=0 ;
11624
11625     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11626     pic16_aopOp(right,ic,FALSE);
11627
11628     size = AOP_SIZE(right);
11629
11630 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11631
11632 #if 0
11633     if ( AOP_TYPE(result) == AOP_PCODE) {
11634       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11635               AOP(result)->aopu.pcop->name,
11636                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11637               PCOR(AOP(result)->aopu.pcop)->instance:
11638               PCOI(AOP(result)->aopu.pcop)->offset);
11639     }
11640 #endif
11641
11642     if(AOP(result)->aopu.pcop->type == PO_DIR)
11643       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11644
11645     while (size--) {
11646       if (AOP_TYPE(right) == AOP_LIT) {
11647         unsigned int lit;
11648
11649           if(!IS_FLOAT(operandType( right )))
11650             lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11651           else {
11652             union {
11653               unsigned long lit_int;
11654               float lit_float;
11655             } info;
11656         
11657               /* take care if literal is a float */
11658               info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11659               lit = info.lit_int;
11660           }
11661                     lit = lit >> (8*offset);
11662                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11663                 } else {
11664                   pic16_mov2w(AOP(right), offset);
11665                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11666                 }
11667                 offset++;
11668                 resoffset++;
11669         }
11670
11671     pic16_freeAsmop(right,NULL,ic,TRUE);
11672 }
11673
11674
11675
11676 /*-----------------------------------------------------------------*/
11677 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11678 /*-----------------------------------------------------------------*/
11679 static void genNearPointerSet (operand *right,
11680                                operand *result, 
11681                                iCode *ic)
11682 {
11683   asmop *aop = NULL;
11684   sym_link *retype;
11685   sym_link *ptype = operandType(result);
11686   sym_link *resetype;
11687     
11688     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11689     retype= getSpec(operandType(right));
11690     resetype = getSpec(operandType(result));
11691   
11692     pic16_aopOp(result,ic,FALSE);
11693     
11694     /* if the result is rematerializable &
11695      * in data space & not a bit variable */
11696         
11697     /* and result is not a bit variable */
11698     if (AOP_TYPE(result) == AOP_PCODE
11699 //      && AOP_TYPE(result) == AOP_IMMD
11700       && DCL_TYPE(ptype) == POINTER
11701       && !IS_BITFIELD(retype)
11702       && !IS_BITFIELD(resetype)) {
11703
11704         genDataPointerSet (right,result,ic);
11705         pic16_freeAsmop(result,NULL,ic,TRUE);
11706       return;
11707     }
11708
11709     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11710     pic16_aopOp(right,ic,FALSE);
11711     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11712
11713     /* if bitfield then unpack the bits */
11714     if (IS_BITFIELD(resetype)) {
11715       genPackBits (resetype, result, right, NULL, POINTER);
11716     } else {
11717       /* we have can just get the values */
11718       int size = AOP_SIZE(right);
11719       int offset = 0 ;    
11720
11721         pic16_loadFSR0(result, 0);
11722             
11723         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11724         while (size--) {
11725           if (AOP_TYPE(right) == AOP_LIT) {
11726             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11727             if (size) {
11728               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11729             } else {
11730               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11731             }
11732           } else { // no literal
11733             if(size) {
11734               pic16_emitpcode(POC_MOVFF,
11735                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11736                   pic16_popCopyReg(&pic16_pc_postinc0)));
11737             } else {
11738               pic16_emitpcode(POC_MOVFF,
11739                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11740                   pic16_popCopyReg(&pic16_pc_indf0)));
11741             }
11742           }
11743           
11744           offset++;
11745         }
11746     }
11747
11748     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11749     /* now some housekeeping stuff */
11750     if (aop) {
11751       /* we had to allocate for this iCode */
11752       pic16_freeAsmop(NULL,aop,ic,TRUE);
11753     } else { 
11754       /* we did not allocate which means left
11755        * already in a pointer register, then
11756        * if size > 0 && this could be used again
11757        * we have to point it back to where it 
11758        * belongs */
11759       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11760       if (AOP_SIZE(right) > 1
11761         && !OP_SYMBOL(result)->remat
11762         && ( OP_SYMBOL(result)->liveTo > ic->seq
11763         || ic->depth )) {
11764
11765           int size = AOP_SIZE(right) - 1;
11766
11767             while (size--)
11768               pic16_emitcode("decf","fsr0,f");
11769               //pic16_emitcode("dec","%s",rname);
11770       }
11771     }
11772
11773     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11774     /* done */
11775 //release:
11776     pic16_freeAsmop(right,NULL,ic,TRUE);
11777     pic16_freeAsmop(result,NULL,ic,TRUE);
11778 }
11779
11780 /*-----------------------------------------------------------------*/
11781 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11782 /*-----------------------------------------------------------------*/
11783 static void genPagedPointerSet (operand *right,
11784                                operand *result, 
11785                                iCode *ic)
11786 {
11787     asmop *aop = NULL;
11788     regs *preg = NULL ;
11789     char *rname , *l;
11790     sym_link *retype;
11791        
11792     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11793
11794     retype= getSpec(operandType(right));
11795     
11796     pic16_aopOp(result,ic,FALSE);
11797     
11798     /* if the value is already in a pointer register
11799        then don't need anything more */
11800     if (!AOP_INPREG(AOP(result))) {
11801         /* otherwise get a free pointer register */
11802         aop = newAsmop(0);
11803         preg = getFreePtr(ic,&aop,FALSE);
11804         pic16_emitcode("mov","%s,%s",
11805                 preg->name,
11806                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11807         rname = preg->name ;
11808     } else
11809         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11810     
11811     pic16_freeAsmop(result,NULL,ic,TRUE);
11812     pic16_aopOp (right,ic,FALSE);
11813
11814     /* if bitfield then unpack the bits */
11815     if (IS_BITFIELD(retype)) 
11816         genPackBits (retype,result,right,rname,PPOINTER);
11817     else {
11818         /* we have can just get the values */
11819         int size = AOP_SIZE(right);
11820         int offset = 0 ;        
11821         
11822         while (size--) {
11823             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11824             
11825             MOVA(l);
11826             pic16_emitcode("movx","@%s,a",rname);
11827
11828             if (size)
11829                 pic16_emitcode("inc","%s",rname);
11830
11831             offset++;
11832         }
11833     }
11834     
11835     /* now some housekeeping stuff */
11836     if (aop) {
11837         /* we had to allocate for this iCode */
11838         pic16_freeAsmop(NULL,aop,ic,TRUE);
11839     } else { 
11840         /* we did not allocate which means left
11841            already in a pointer register, then
11842            if size > 0 && this could be used again
11843            we have to point it back to where it 
11844            belongs */
11845         if (AOP_SIZE(right) > 1 &&
11846             !OP_SYMBOL(result)->remat &&
11847             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11848               ic->depth )) {
11849             int size = AOP_SIZE(right) - 1;
11850             while (size--)
11851                 pic16_emitcode("dec","%s",rname);
11852         }
11853     }
11854
11855     /* done */
11856     pic16_freeAsmop(right,NULL,ic,TRUE);
11857     
11858         
11859 }
11860
11861 #if 0
11862 /* This code is not adjusted to PIC16 and fails utterly...
11863  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11864
11865 /*-----------------------------------------------------------------*/
11866 /* genFarPointerSet - set value from far space                     */
11867 /*-----------------------------------------------------------------*/
11868 static void genFarPointerSet (operand *right,
11869                               operand *result, iCode *ic)
11870 {
11871     int size, offset ;
11872     sym_link *retype = getSpec(operandType(right));
11873
11874     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11875     pic16_aopOp(result,ic,FALSE);
11876
11877     /* if the operand is already in dptr 
11878     then we do nothing else we move the value to dptr */
11879     if (AOP_TYPE(result) != AOP_STR) {
11880         /* if this is remateriazable */
11881         if (AOP_TYPE(result) == AOP_IMMD)
11882             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11883         else { /* we need to get it byte by byte */
11884             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11885             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11886             if (options.model == MODEL_FLAT24)
11887             {
11888                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11889             }
11890         }
11891     }
11892     /* so dptr know contains the address */
11893     pic16_freeAsmop(result,NULL,ic,TRUE);
11894     pic16_aopOp(right,ic,FALSE);
11895
11896     /* if bit then unpack */
11897     if (IS_BITFIELD(retype)) 
11898         genPackBits(retype,result,right,"dptr",FPOINTER);
11899     else {
11900         size = AOP_SIZE(right);
11901         offset = 0 ;
11902
11903         while (size--) {
11904             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11905             MOVA(l);
11906             pic16_emitcode("movx","@dptr,a");
11907             if (size)
11908                 pic16_emitcode("inc","dptr");
11909         }
11910     }
11911
11912     pic16_freeAsmop(right,NULL,ic,TRUE);
11913 }
11914 #endif
11915
11916 /*-----------------------------------------------------------------*/
11917 /* genGenPointerSet - set value from generic pointer space         */
11918 /*-----------------------------------------------------------------*/
11919 #if 0
11920 static void genGenPointerSet (operand *right,
11921                               operand *result, iCode *ic)
11922 {
11923         int i, size, offset, lit;
11924         sym_link *retype = getSpec(operandType(right));
11925
11926         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11927
11928         pic16_aopOp(result,ic,FALSE);
11929         pic16_aopOp(right,ic,FALSE);
11930         size = AOP_SIZE(right);
11931         offset = 0;
11932
11933         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11934
11935         /* if the operand is already in dptr 
11936                 then we do nothing else we move the value to dptr */
11937         if (AOP_TYPE(result) != AOP_STR) {
11938                 /* if this is remateriazable */
11939                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11940                 // WARNING: anythig until "else" is untested!
11941                 if (AOP_TYPE(result) == AOP_IMMD) {
11942                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11943                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11944                         // load FSR0 from immediate
11945                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11946                         offset = 0;
11947                         while(size--) {
11948                                 if(size) {
11949                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11950                                 } else {
11951                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11952                                 }
11953                                 offset++;
11954                         }
11955                         goto release;
11956                 }
11957                 else { /* we need to get it byte by byte */
11958                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11959                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11960
11961                         // set up FSR0 with address of result
11962                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11963                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11964
11965                         /* hack hack! see if this the FSR. If so don't load W */
11966                         if(AOP_TYPE(right) != AOP_ACC) {
11967
11968                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11969
11970                                 if(AOP_TYPE(right) == AOP_LIT)
11971                                 {
11972                                         // copy literal
11973                                         // note: pic16_popGet handles sign extension
11974                                         for(i=0;i<size;i++) {
11975                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11976                                                 if(i < size-1)
11977                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11978                                                 else
11979                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11980                                         }
11981                                 } else {
11982                                         // copy regs
11983
11984                                         for(i=0;i<size;i++) {
11985                                                 if(i < size-1)
11986                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11987                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11988                                                 else
11989                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11990                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11991                                         }
11992                                 }
11993                                 goto release;
11994                         } 
11995                         // right = ACC
11996                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11997                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11998                         goto release;
11999         } // if (AOP_TYPE(result) != AOP_IMMD)
12000
12001         } // if (AOP_TYPE(result) != AOP_STR)
12002         /* so dptr know contains the address */
12003
12004
12005         /* if bit then unpack */
12006         if (IS_BITFIELD(retype)) 
12007                 genPackBits(retype,result,right,"dptr",GPOINTER);
12008         else {
12009                 size = AOP_SIZE(right);
12010                 offset = 0 ;
12011
12012                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12013
12014                 // set up FSR0 with address of result
12015                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12016                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12017         
12018                 while (size--) {
12019                         if (AOP_TYPE(right) == AOP_LIT) {
12020                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12021                                 if (size) {
12022                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12023                                 } else {
12024                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12025                                 }
12026                         } else { // no literal
12027                                 if(size) {
12028                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12029                                 } else {
12030                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12031                                 }
12032                         }
12033                         offset++;
12034                 }
12035         }
12036
12037         release:
12038         pic16_freeAsmop(right,NULL,ic,TRUE);
12039         pic16_freeAsmop(result,NULL,ic,TRUE);
12040 }
12041 #endif
12042
12043 static void genGenPointerSet (operand *right,
12044                               operand *result, iCode *ic)
12045 {
12046   int size;
12047   sym_link *retype = getSpec(operandType(result));
12048
12049     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12050
12051     pic16_aopOp(result,ic,FALSE);
12052     pic16_aopOp(right,ic,FALSE);
12053     size = AOP_SIZE(right);
12054
12055     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12056
12057
12058     /* if bit then unpack */
12059     if (IS_BITFIELD(retype)) {
12060 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12061       genPackBits(retype,result,right,"dptr",GPOINTER);
12062       goto release;
12063     }
12064
12065     size = AOP_SIZE(right);
12066
12067     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12068
12069
12070     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12071
12072     /* value of right+0 is placed on stack, which will be retrieved
12073      * by the support function thus restoring the stack. The important
12074      * thing is that there is no need to manually restore stack pointer
12075      * here */
12076     pushaop(AOP(right), 0);
12077 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12078     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12079     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12080     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12081     
12082     /* load address to write to in WREG:FSR0H:FSR0L */
12083     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12084                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12085     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12086                                 pic16_popCopyReg(&pic16_pc_prodl)));
12087     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12088     
12089     pic16_callGenericPointerRW(1, size);
12090
12091 release:
12092     pic16_freeAsmop(right,NULL,ic,TRUE);
12093     pic16_freeAsmop(result,NULL,ic,TRUE);
12094 }
12095
12096 /*-----------------------------------------------------------------*/
12097 /* genPointerSet - stores the value into a pointer location        */
12098 /*-----------------------------------------------------------------*/
12099 static void genPointerSet (iCode *ic)
12100 {    
12101   operand *right, *result ;
12102   sym_link *type, *etype;
12103   int p_type;
12104
12105     FENTRY;
12106
12107     right = IC_RIGHT(ic);
12108     result = IC_RESULT(ic) ;
12109
12110     /* depending on the type of pointer we need to
12111     move it to the correct pointer register */
12112     type = operandType(result);
12113     etype = getSpec(type);
12114     
12115     /* if left is of type of pointer then it is simple */
12116     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12117         p_type = DCL_TYPE(type);
12118     }
12119     else {
12120         /* we have to go by the storage class */
12121         p_type = PTR_TYPE(SPEC_OCLS(etype));
12122
12123 /*      if (SPEC_OCLS(etype)->codesp ) { */
12124 /*          p_type = CPOINTER ;  */
12125 /*      } */
12126 /*      else */
12127 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12128 /*              p_type = FPOINTER ; */
12129 /*          else */
12130 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12131 /*                  p_type = PPOINTER ; */
12132 /*              else */
12133 /*                  if (SPEC_OCLS(etype) == idata ) */
12134 /*                      p_type = IPOINTER ; */
12135 /*                  else */
12136 /*                      p_type = POINTER ; */
12137     }
12138
12139     /* now that we have the pointer type we assign
12140     the pointer values */
12141     switch (p_type) {
12142       case POINTER:
12143       case FPOINTER:
12144       case IPOINTER:
12145         genNearPointerSet (right,result,ic);
12146         break;
12147
12148       case PPOINTER:
12149         genPagedPointerSet (right,result,ic);
12150         break;
12151
12152 #if 0
12153       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12154       case FPOINTER:
12155         genFarPointerSet (right,result,ic);
12156         break;
12157 #endif
12158         
12159       case GPOINTER:
12160         genGenPointerSet (right,result,ic);
12161         break;
12162
12163       default:
12164         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12165           "genPointerSet: illegal pointer type");
12166     }
12167 }
12168
12169 /*-----------------------------------------------------------------*/
12170 /* genIfx - generate code for Ifx statement                        */
12171 /*-----------------------------------------------------------------*/
12172 static void genIfx (iCode *ic, iCode *popIc)
12173 {
12174   operand *cond = IC_COND(ic);
12175   int isbit =0;
12176
12177     FENTRY;
12178
12179     pic16_aopOp(cond,ic,FALSE);
12180
12181     /* get the value into acc */
12182     if (AOP_TYPE(cond) != AOP_CRY)
12183       pic16_toBoolean(cond);
12184     else
12185       isbit = 1;
12186     /* the result is now in the accumulator */
12187     pic16_freeAsmop(cond,NULL,ic,TRUE);
12188
12189     /* if there was something to be popped then do it */
12190     if (popIc)
12191       genIpop(popIc);
12192
12193     /* if the condition is  a bit variable */
12194     if (isbit && IS_ITEMP(cond) && 
12195         SPIL_LOC(cond)) {
12196       genIfxJump(ic,"c");
12197       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12198     } else {
12199       if (isbit && !IS_ITEMP(cond))
12200         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12201         else
12202         genIfxJump(ic,"a");
12203     }
12204     ic->generated = 1;
12205 }
12206
12207 /*-----------------------------------------------------------------*/
12208 /* genAddrOf - generates code for address of                       */
12209 /*-----------------------------------------------------------------*/
12210 static void genAddrOf (iCode *ic)
12211 {
12212   operand *result, *left;
12213   int size;
12214   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12215   pCodeOp *pcop0, *pcop1, *pcop2;
12216
12217     FENTRY;
12218
12219     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12220
12221     sym = OP_SYMBOL( IC_LEFT(ic) );
12222     
12223     if(sym->onStack) {
12224       /* get address of symbol on stack */
12225       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12226 #if 0
12227       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12228                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12229 #endif
12230
12231       // operands on stack are accessible via "FSR2 + index" with index
12232       // starting at 2 for arguments and growing from 0 downwards for
12233       // local variables (index == 0 is not assigned so we add one here)
12234       {
12235         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12236
12237           if (soffs <= 0) {
12238             assert (soffs < 0);
12239             soffs++;
12240           } // if
12241
12242           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12243           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12244           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12245           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12246           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12247           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12248           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12249       }
12250
12251       goto release;
12252     }
12253         
12254 //      if(pic16_debug_verbose) {
12255 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12256 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12257 //      }
12258         
12259     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12260     size = AOP_SIZE(IC_RESULT(ic));
12261
12262     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12263     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12264     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12265         
12266     if (size == 3) {
12267       pic16_emitpcode(POC_MOVLW, pcop0);
12268       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12269       pic16_emitpcode(POC_MOVLW, pcop1);
12270       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12271       pic16_emitpcode(POC_MOVLW, pcop2);
12272       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12273     } else
12274     if (size == 2) {
12275       pic16_emitpcode(POC_MOVLW, pcop0);
12276       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12277       pic16_emitpcode(POC_MOVLW, pcop1);
12278     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12279     } else {
12280       pic16_emitpcode(POC_MOVLW, pcop0);
12281       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12282     }
12283
12284     pic16_freeAsmop(left, NULL, ic, FALSE);
12285 release:
12286     pic16_freeAsmop(result,NULL,ic,TRUE);
12287 }
12288
12289
12290 #if 0
12291 /*-----------------------------------------------------------------*/
12292 /* genFarFarAssign - assignment when both are in far space         */
12293 /*-----------------------------------------------------------------*/
12294 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12295 {
12296     int size = AOP_SIZE(right);
12297     int offset = 0;
12298     char *l ;
12299     /* first push the right side on to the stack */
12300     while (size--) {
12301         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12302         MOVA(l);
12303         pic16_emitcode ("push","acc");
12304     }
12305     
12306     pic16_freeAsmop(right,NULL,ic,FALSE);
12307     /* now assign DPTR to result */
12308     pic16_aopOp(result,ic,FALSE);
12309     size = AOP_SIZE(result);
12310     while (size--) {
12311         pic16_emitcode ("pop","acc");
12312         pic16_aopPut(AOP(result),"a",--offset);
12313     }
12314     pic16_freeAsmop(result,NULL,ic,FALSE);
12315         
12316 }
12317 #endif
12318
12319 /*-----------------------------------------------------------------*/
12320 /* genAssign - generate code for assignment                        */
12321 /*-----------------------------------------------------------------*/
12322 static void genAssign (iCode *ic)
12323 {
12324   operand *result, *right;
12325   sym_link *restype, *rtype;
12326   int size, offset,know_W;
12327   unsigned long lit = 0L;
12328
12329     result = IC_RESULT(ic);
12330     right  = IC_RIGHT(ic) ;
12331
12332     FENTRY;
12333   
12334     /* if they are the same */
12335     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12336       return ;
12337
12338     /* reversed order operands are aopOp'ed so that result operand
12339      * is effective in case right is a stack symbol. This maneauver
12340      * allows to use the _G.resDirect flag later */
12341      pic16_aopOp(result,ic,TRUE);
12342     pic16_aopOp(right,ic,FALSE);
12343
12344     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12345
12346     /* if they are the same registers */
12347     if (pic16_sameRegs(AOP(right),AOP(result)))
12348       goto release;
12349
12350     /* if the result is a bit */
12351     if (AOP_TYPE(result) == AOP_CRY) {
12352       /* if the right size is a literal then
12353          we know what the value is */
12354       if (AOP_TYPE(right) == AOP_LIT) {
12355           
12356         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12357             pic16_popGet(AOP(result),0));
12358
12359         if (((int) operandLitValue(right))) 
12360           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12361               AOP(result)->aopu.aop_dir,
12362               AOP(result)->aopu.aop_dir);
12363         else
12364           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12365               AOP(result)->aopu.aop_dir,
12366               AOP(result)->aopu.aop_dir);
12367         
12368         goto release;
12369       }
12370
12371       /* the right is also a bit variable */
12372       if (AOP_TYPE(right) == AOP_CRY) {
12373         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12374         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12375         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12376
12377         goto release ;
12378       }
12379
12380       /* we need to or */
12381       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12382       pic16_toBoolean(right);
12383       emitSKPZ;
12384       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12385       //pic16_aopPut(AOP(result),"a",0);
12386       goto release ;
12387     }
12388
12389     /* bit variables done */
12390     /* general case */
12391     size = AOP_SIZE(result);
12392     offset = 0 ;
12393
12394   /* bit variables done */
12395   /* general case */
12396   size = AOP_SIZE(result);
12397   restype = operandType(result);
12398   rtype = operandType(right);
12399   offset = 0 ;
12400
12401   if(AOP_TYPE(right) == AOP_LIT) {
12402     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12403     {
12404       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12405
12406       /* patch tag for literals that are cast to pointers */
12407       if (IS_CODEPTR(restype)) {
12408         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12409         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12410       } else {
12411         if (IS_GENPTR(restype))
12412         {
12413           if (IS_CODEPTR(rtype)) {
12414             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12415             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12416           } else if (PIC_IS_DATA_PTR(rtype)) {
12417             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12418             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12419           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12420             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12421           } else if (IS_PTR(rtype)) {
12422             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12423             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12424           }
12425         }
12426       }
12427     } else {
12428       union {
12429         unsigned long lit_int;
12430         float lit_float;
12431       } info;
12432
12433
12434       if(IS_FIXED16X16(operandType(right))) {
12435         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12436       } else {
12437         /* take care if literal is a float */
12438         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12439         lit = info.lit_int;
12440       }
12441     }
12442   }
12443
12444 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12445 //                      sizeof(unsigned long int), sizeof(float));
12446
12447
12448     if (AOP_TYPE(right) == AOP_REG) {
12449       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12450       while (size--) {
12451         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12452       } // while
12453       goto release;
12454     }
12455
12456     /* when do we have to read the program memory?
12457      * - if right itself is a symbol in code space
12458      *   (we don't care what it points to if it's a pointer)
12459      * - AND right is not a function (we would want its address)
12460      */
12461     if(AOP_TYPE(right) != AOP_LIT
12462       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12463       && !IS_FUNC(OP_SYM_TYPE(right))
12464       && !IS_ITEMP(right)) {
12465
12466       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12467       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12468       
12469       // set up table pointer
12470       if(is_LitOp(right)) {
12471 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12472         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12473         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12474         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12475         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12476         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12477         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12478       } else {
12479 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12480         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12481             pic16_popCopyReg(&pic16_pc_tblptrl)));
12482         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12483             pic16_popCopyReg(&pic16_pc_tblptrh)));
12484         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12485             pic16_popCopyReg(&pic16_pc_tblptru)));
12486       }
12487
12488       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12489       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12490       while(size--) {
12491         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12492         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12493             pic16_popGet(AOP(result),offset)));
12494         offset++;
12495       }
12496
12497       /* FIXME: for pointers we need to extend differently (according
12498        * to pointer type DATA/CODE/EEPROM/... :*/
12499       size = getSize(OP_SYM_TYPE(right));
12500       if(AOP_SIZE(result) > size) {
12501         size = AOP_SIZE(result) - size;
12502         while(size--) {
12503           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12504           offset++;
12505         }
12506       }
12507       goto release;
12508     }
12509
12510 #if 0
12511     /* VR - What is this?! */
12512     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12513       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12514       
12515       if(aopIdx(AOP(result),0) == 4) {
12516         /* this is a workaround to save value of right into wreg too,
12517          * value of wreg is going to be used later */
12518         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12519         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12520         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12521         goto release;
12522       } else
12523 //      assert(0);
12524       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12525     }
12526 #endif
12527
12528   know_W=-1;
12529   while (size--) {
12530     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12531     if(AOP_TYPE(right) == AOP_LIT) {
12532       if(lit&0xff) {
12533         if(know_W != (lit&0xff))
12534           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12535         know_W = lit&0xff;
12536         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12537       } else
12538         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12539
12540       lit >>= 8;
12541
12542     } else if (AOP_TYPE(right) == AOP_CRY) {
12543       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12544       if(offset == 0) {
12545         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12546         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12547         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12548       }
12549     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12550         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12551         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12552     } else {
12553       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12554
12555       if(!_G.resDirect) {                                               /* use this aopForSym feature */
12556           if(AOP_TYPE(result) == AOP_ACC) {
12557             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12558           } else
12559           if(AOP_TYPE(right) == AOP_ACC) {
12560             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12561           } else {
12562             pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12563           }
12564       }
12565     }
12566       
12567       offset++;
12568     }
12569   
12570 release:
12571   pic16_freeAsmop (right,NULL,ic,FALSE);
12572   pic16_freeAsmop (result,NULL,ic,TRUE);
12573
12574
12575 /*-----------------------------------------------------------------*/
12576 /* genJumpTab - generates code for jump table                       */
12577 /*-----------------------------------------------------------------*/
12578 static void genJumpTab (iCode *ic)
12579 {
12580   symbol *jtab;
12581   char *l;
12582   pCodeOp *jt_offs;
12583   pCodeOp *jt_offs_hi;
12584   pCodeOp *jt_label;
12585
12586     FENTRY;
12587
12588     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12589     /* get the condition into accumulator */
12590     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12591     MOVA(l);
12592     /* multiply by three */
12593     pic16_emitcode("add","a,acc");
12594     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12595
12596     jtab = newiTempLabel(NULL);
12597     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12598     pic16_emitcode("jmp","@a+dptr");
12599     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12600
12601 #if 0
12602     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12603     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12604     emitSKPNC;
12605     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12606     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12607     pic16_emitpLabel(jtab->key);
12608
12609 #else
12610
12611     jt_offs = pic16_popGetTempReg(0);
12612     jt_offs_hi = pic16_popGetTempReg(1);
12613     jt_label = pic16_popGetLabel (jtab->key);
12614     //fprintf (stderr, "Creating jump table...\n");
12615
12616     // calculate offset into jump table (idx * sizeof (GOTO))
12617     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12618     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12619     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12620     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12621     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12622     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12623     pic16_emitpcode(POC_MOVWF , jt_offs);
12624
12625     // prepare PCLATx (set to first entry in jump table)
12626     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12627     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12628     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12629     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12630     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12631
12632     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12633     pic16_emitpcode(POC_ADDWF , jt_offs);
12634     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12635     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12636     emitSKPNC;
12637     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12638
12639     // release temporaries and prepare jump into table (new PCL --> WREG)
12640     pic16_emitpcode(POC_MOVFW , jt_offs);
12641     pic16_popReleaseTempReg (jt_offs_hi, 1);
12642     pic16_popReleaseTempReg (jt_offs, 0);
12643
12644     // jump into the table
12645     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12646
12647     pic16_emitpLabelFORCE(jtab->key);
12648 #endif
12649
12650     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12651 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12652
12653     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12654     /* now generate the jump labels */
12655     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12656          jtab = setNextItem(IC_JTLABELS(ic))) {
12657 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12658         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12659         
12660     }
12661     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12662
12663 }
12664
12665 /*-----------------------------------------------------------------*/
12666 /* genMixedOperation - gen code for operators between mixed types  */
12667 /*-----------------------------------------------------------------*/
12668 /*
12669   TSD - Written for the PIC port - but this unfortunately is buggy.
12670   This routine is good in that it is able to efficiently promote 
12671   types to different (larger) sizes. Unfortunately, the temporary
12672   variables that are optimized out by this routine are sometimes
12673   used in other places. So until I know how to really parse the 
12674   iCode tree, I'm going to not be using this routine :(.
12675 */
12676 static int genMixedOperation (iCode *ic)
12677 {
12678 #if 0
12679   operand *result = IC_RESULT(ic);
12680   sym_link *ctype = operandType(IC_LEFT(ic));
12681   operand *right = IC_RIGHT(ic);
12682   int ret = 0;
12683   int big,small;
12684   int offset;
12685
12686   iCode *nextic;
12687   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12688
12689   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12690
12691   nextic = ic->next;
12692   if(!nextic)
12693     return 0;
12694
12695   nextright = IC_RIGHT(nextic);
12696   nextleft  = IC_LEFT(nextic);
12697   nextresult = IC_RESULT(nextic);
12698
12699   pic16_aopOp(right,ic,FALSE);
12700   pic16_aopOp(result,ic,FALSE);
12701   pic16_aopOp(nextright,  nextic, FALSE);
12702   pic16_aopOp(nextleft,   nextic, FALSE);
12703   pic16_aopOp(nextresult, nextic, FALSE);
12704
12705   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12706
12707     operand *t = right;
12708     right = nextright;
12709     nextright = t; 
12710
12711     pic16_emitcode(";remove right +","");
12712
12713   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12714 /*
12715     operand *t = right;
12716     right = nextleft;
12717     nextleft = t; 
12718 */
12719     pic16_emitcode(";remove left +","");
12720   } else
12721     return 0;
12722
12723   big = AOP_SIZE(nextleft);
12724   small = AOP_SIZE(nextright);
12725
12726   switch(nextic->op) {
12727
12728   case '+':
12729     pic16_emitcode(";optimize a +","");
12730     /* if unsigned or not an integral type */
12731     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12732       pic16_emitcode(";add a bit to something","");
12733     } else {
12734
12735       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12736
12737       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12738         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12739         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12740       } else
12741         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12742
12743       offset = 0;
12744       while(--big) {
12745
12746         offset++;
12747
12748         if(--small) {
12749           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12750             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12751             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12752           }
12753
12754           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12755           emitSKPNC;
12756           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12757                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12758                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12759           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12760           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12761
12762         } else {
12763           pic16_emitcode("rlf","known_zero,w");
12764
12765           /*
12766             if right is signed
12767               btfsc  right,7
12768                addlw ff
12769           */
12770           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12771             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12772             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12773           } else {
12774             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12775           }
12776         }
12777       }
12778       ret = 1;
12779     }
12780   }
12781   ret = 1;
12782
12783 release:
12784   pic16_freeAsmop(right,NULL,ic,TRUE);
12785   pic16_freeAsmop(result,NULL,ic,TRUE);
12786   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12787   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12788   if(ret)
12789     nextic->generated = 1;
12790
12791   return ret;
12792 #else
12793   return 0;
12794 #endif
12795 }
12796 /*-----------------------------------------------------------------*/
12797 /* genCast - gen code for casting                                  */
12798 /*-----------------------------------------------------------------*/
12799 static void genCast (iCode *ic)
12800 {
12801   operand *result = IC_RESULT(ic);
12802   sym_link *ctype = operandType(IC_LEFT(ic));
12803   sym_link *rtype = operandType(IC_RIGHT(ic));
12804   sym_link *restype = operandType(IC_RESULT(ic));
12805   operand *right = IC_RIGHT(ic);
12806   int size, offset ;
12807
12808
12809     FENTRY;
12810
12811         /* if they are equivalent then do nothing */
12812 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12813 //              return ;
12814
12815         pic16_aopOp(result,ic,FALSE);
12816         pic16_aopOp(right,ic,FALSE) ;
12817
12818         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12819
12820
12821         /* if the result is a bit */
12822         if (AOP_TYPE(result) == AOP_CRY) {
12823         
12824                 /* if the right size is a literal then
12825                  * we know what the value is */
12826                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12827
12828                 if (AOP_TYPE(right) == AOP_LIT) {
12829                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12830                                 pic16_popGet(AOP(result),0));
12831
12832                         if (((int) operandLitValue(right))) 
12833                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12834                                         AOP(result)->aopu.aop_dir,
12835                                         AOP(result)->aopu.aop_dir);
12836                         else
12837                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12838                                         AOP(result)->aopu.aop_dir,
12839                                         AOP(result)->aopu.aop_dir);
12840                         goto release;
12841                 }
12842
12843                 /* the right is also a bit variable */
12844                 if (AOP_TYPE(right) == AOP_CRY) {
12845                         emitCLRC;
12846                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12847
12848                         pic16_emitcode("clrc","");
12849                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12850                                 AOP(right)->aopu.aop_dir,
12851                                 AOP(right)->aopu.aop_dir);
12852                         pic16_aopPut(AOP(result),"c",0);
12853                         goto release ;
12854                 }
12855
12856                 /* we need to or */
12857                 if (AOP_TYPE(right) == AOP_REG) {
12858                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12859                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12860                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12861                 }
12862                 pic16_toBoolean(right);
12863                 pic16_aopPut(AOP(result),"a",0);
12864                 goto release ;
12865         }
12866
12867         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12868           int offset = 1;
12869
12870                 size = AOP_SIZE(result);
12871
12872                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12873
12874                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12875                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12876                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12877
12878                 while (size--)
12879                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12880
12881                 goto release;
12882         }
12883
12884         if(IS_BITFIELD(getSpec(restype))
12885           && IS_BITFIELD(getSpec(rtype))) {
12886           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12887         }
12888         
12889         /* port from pic14 to cope with generic pointers */
12890         if (PIC_IS_TAGGED(restype))
12891         {
12892           operand *result = IC_RESULT(ic);
12893           //operand *left = IC_LEFT(ic);
12894           operand *right = IC_RIGHT(ic);
12895           int tag = 0xff;
12896
12897           /* copy common part */
12898           int max, size = AOP_SIZE(result);
12899           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12900           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12901
12902           max = size;
12903           while (size--)
12904           {
12905             pic16_mov2w (AOP(right), size);
12906             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12907           } // while
12908
12909           /* upcast into generic pointer type? */
12910           if (IS_GENPTR(restype)
12911               && !PIC_IS_TAGGED(rtype)
12912               && (AOP_SIZE(result) > max))
12913           {
12914             /* determine appropriate tag for right */
12915             if (PIC_IS_DATA_PTR(rtype))
12916               tag = GPTR_TAG_DATA;
12917             else if (IS_CODEPTR(rtype))
12918               tag = GPTR_TAG_CODE;
12919             else if (PIC_IS_DATA_PTR(ctype)) {
12920               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12921               tag = GPTR_TAG_DATA;
12922             } else if (IS_CODEPTR(ctype)) {
12923               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12924               tag = GPTR_TAG_CODE;
12925             } else if (IS_PTR(rtype)) {
12926               PERFORM_ONCE(weirdcast,
12927               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12928               );
12929               tag = GPTR_TAG_DATA;
12930             } else {
12931               PERFORM_ONCE(weirdcast,
12932               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12933               );
12934               tag = GPTR_TAG_DATA;
12935             }
12936
12937             assert (AOP_SIZE(result) == 3);
12938             /* zero-extend address... */
12939             for (size = max; size < AOP_SIZE(result)-1; size++)
12940               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12941             /* ...and add tag */
12942             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12943           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12944             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12945             for (size = max; size < AOP_SIZE(result)-1; size++)
12946               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12947             /* add __code tag */
12948             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12949           } else if (AOP_SIZE(result) > max) {
12950             /* extend non-pointers */
12951             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12952             pic16_addSign(result, max, 0);
12953           } // if
12954           goto release;
12955         }
12956
12957         /* if they are the same size : or less */
12958         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12959
12960                 /* if they are in the same place */
12961                 if (pic16_sameRegs(AOP(right),AOP(result)))
12962                         goto release;
12963
12964                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12965 #if 0
12966                 if (IS_PTR_CONST(rtype))
12967 #else
12968                 if (IS_CODEPTR(rtype))
12969 #endif
12970                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12971
12972 #if 0
12973                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12974 #else
12975                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12976 #endif
12977                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12978
12979 #if 0
12980                 if(AOP_TYPE(right) == AOP_IMMD) {
12981                   pCodeOp *pcop0, *pcop1, *pcop2;
12982                   symbol *sym = OP_SYMBOL( right );
12983
12984                         size = AOP_SIZE(result);
12985                         /* low */
12986                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12987                         /* high */
12988                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12989                         /* upper */
12990                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12991         
12992                         if (size == 3) {
12993                                 pic16_emitpcode(POC_MOVLW, pcop0);
12994                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12995                                 pic16_emitpcode(POC_MOVLW, pcop1);
12996                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12997                                 pic16_emitpcode(POC_MOVLW, pcop2);
12998                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12999                         } else
13000                         if (size == 2) {
13001                                 pic16_emitpcode(POC_MOVLW, pcop0);
13002                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13003                                 pic16_emitpcode(POC_MOVLW, pcop1);
13004                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13005                         } else {
13006                                 pic16_emitpcode(POC_MOVLW, pcop0);
13007                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13008                         }
13009                 } else
13010 #endif
13011                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13012                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13013                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13014                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13015                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13016                         if(AOP_SIZE(result) <2)
13017                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13018                 } else {
13019                         /* if they in different places then copy */
13020                         size = AOP_SIZE(result);
13021                         offset = 0 ;
13022                         while (size--) {
13023                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13024                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13025                                 offset++;
13026                         }
13027                 }
13028                 goto release;
13029         }
13030
13031         /* if the result is of type pointer */
13032         if (IS_PTR(ctype)) {
13033           int p_type;
13034           sym_link *type = operandType(right);
13035           sym_link *etype = getSpec(type);
13036
13037                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13038
13039                 /* pointer to generic pointer */
13040                 if (IS_GENPTR(ctype)) {
13041                   char *l = zero;
13042             
13043                         if (IS_PTR(type)) 
13044                                 p_type = DCL_TYPE(type);
13045                         else {
13046                 /* we have to go by the storage class */
13047                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13048
13049 /*              if (SPEC_OCLS(etype)->codesp )  */
13050 /*                  p_type = CPOINTER ;  */
13051 /*              else */
13052 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13053 /*                      p_type = FPOINTER ; */
13054 /*                  else */
13055 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13056 /*                          p_type = PPOINTER; */
13057 /*                      else */
13058 /*                          if (SPEC_OCLS(etype) == idata ) */
13059 /*                              p_type = IPOINTER ; */
13060 /*                          else */
13061 /*                              p_type = POINTER ; */
13062             }
13063                 
13064             /* the first two bytes are known */
13065       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13066             size = GPTRSIZE - 1; 
13067             offset = 0 ;
13068             while (size--) {
13069               if(offset < AOP_SIZE(right)) {
13070                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13071                 pic16_mov2f(AOP(result), AOP(right), offset);
13072 /*
13073                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13074                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13075                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13076                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13077                 } else { 
13078                   
13079                   pic16_aopPut(AOP(result),
13080                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13081                          offset);
13082                 }
13083 */
13084               } else 
13085                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13086               offset++;
13087             }
13088             /* the last byte depending on type */
13089             switch (p_type) {
13090             case IPOINTER:
13091             case POINTER:
13092             case FPOINTER:
13093                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13094                 break;
13095
13096             case CPOINTER:
13097                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13098                 break;
13099
13100             case PPOINTER:
13101               pic16_emitcode(";BUG!? ","%d",__LINE__);
13102                 l = "#0x03";
13103                 break;
13104
13105             case GPOINTER:
13106                 if (GPTRSIZE > AOP_SIZE(right)) {
13107                   // assume __data pointer... THIS MIGHT BE WRONG!
13108                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13109                 } else {
13110                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13111                 }
13112               break;
13113               
13114             default:
13115                 /* this should never happen */
13116                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13117                        "got unknown pointer type");
13118                 exit(1);
13119             }
13120             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13121             goto release ;
13122         }
13123         
13124         
13125         assert( 0 );
13126         /* just copy the pointers */
13127         size = AOP_SIZE(result);
13128         offset = 0 ;
13129         while (size--) {
13130             pic16_aopPut(AOP(result),
13131                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13132                    offset);
13133             offset++;
13134         }
13135         goto release ;
13136     }
13137     
13138
13139
13140     /* so we now know that the size of destination is greater
13141     than the size of the source.
13142     Now, if the next iCode is an operator then we might be
13143     able to optimize the operation without performing a cast.
13144     */
13145     if(genMixedOperation(ic))
13146       goto release;
13147
13148     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13149     
13150     /* we move to result for the size of source */
13151     size = AOP_SIZE(right);
13152     offset = 0 ;
13153
13154     while (size--) {
13155       if(!_G.resDirect)
13156         pic16_mov2f(AOP(result), AOP(right), offset);
13157       offset++;
13158     }
13159
13160     /* now depending on the sign of the destination */
13161     size = AOP_SIZE(result) - AOP_SIZE(right);
13162     /* if unsigned or not an integral type */
13163     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13164       while (size--)
13165         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13166     } else {
13167       /* we need to extend the sign :( */
13168
13169       if(size == 1) {
13170         /* Save one instruction of casting char to int */
13171         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13172         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13173         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13174       } else {
13175         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13176
13177         if(offset)
13178           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13179         else
13180           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13181         
13182         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13183
13184         while (size--)
13185           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13186       }
13187     }
13188
13189 release:
13190     pic16_freeAsmop(right,NULL,ic,TRUE);
13191     pic16_freeAsmop(result,NULL,ic,TRUE);
13192
13193 }
13194
13195 /*-----------------------------------------------------------------*/
13196 /* genDjnz - generate decrement & jump if not zero instrucion      */
13197 /*-----------------------------------------------------------------*/
13198 static int genDjnz (iCode *ic, iCode *ifx)
13199 {
13200     symbol *lbl, *lbl1;
13201     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13202
13203     if (!ifx)
13204         return 0;
13205     
13206     /* if the if condition has a false label
13207        then we cannot save */
13208     if (IC_FALSE(ifx))
13209         return 0;
13210
13211     /* if the minus is not of the form 
13212        a = a - 1 */
13213     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13214         !IS_OP_LITERAL(IC_RIGHT(ic)))
13215         return 0;
13216
13217     if (operandLitValue(IC_RIGHT(ic)) != 1)
13218         return 0;
13219
13220     /* if the size of this greater than one then no
13221        saving */
13222     if (getSize(operandType(IC_RESULT(ic))) > 1)
13223         return 0;
13224
13225     /* otherwise we can save BIG */
13226     lbl = newiTempLabel(NULL);
13227     lbl1= newiTempLabel(NULL);
13228
13229     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13230     
13231     if (IS_AOP_PREG(IC_RESULT(ic))) {
13232         pic16_emitcode("dec","%s",
13233                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13234         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13235         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13236     } else {    
13237
13238
13239       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13240       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13241
13242       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13243       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13244
13245     }
13246     
13247     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13248     ifx->generated = 1;
13249     return 1;
13250 }
13251
13252 /*-----------------------------------------------------------------*/
13253 /* genReceive - generate code for a receive iCode                  */
13254 /*-----------------------------------------------------------------*/
13255 static void genReceive (iCode *ic)
13256 {    
13257
13258   FENTRY;
13259
13260 #if 0
13261   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13262         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13263 #endif
13264 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13265
13266   if (isOperandInFarSpace(IC_RESULT(ic))
13267       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13268           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13269
13270     int size = getSize(operandType(IC_RESULT(ic)));
13271     int offset =  pic16_fReturnSizePic - size;
13272
13273       assert( 0 );
13274       while (size--) {
13275         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13276                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13277                       offset++;
13278         }
13279
13280       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13281
13282       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13283       size = AOP_SIZE(IC_RESULT(ic));
13284       offset = 0;
13285       while (size--) {
13286         pic16_emitcode ("pop","acc");
13287         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13288       }
13289   } else {
13290     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13291     _G.accInUse++;
13292     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13293     _G.accInUse--;
13294
13295     /* set pseudo stack pointer to where it should be - dw*/
13296     GpsuedoStkPtr = ic->parmBytes;
13297
13298     /* setting GpsuedoStkPtr has side effects here: */
13299     assignResultValue(IC_RESULT(ic), 0);
13300   }
13301
13302   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13303 }
13304
13305 /*-----------------------------------------------------------------*/
13306 /* genDummyRead - generate code for dummy read of volatiles        */
13307 /*-----------------------------------------------------------------*/
13308 static void
13309 genDummyRead (iCode * ic)
13310 {
13311   operand *op;
13312   int i;
13313
13314   op = IC_RIGHT(ic);
13315   if (op && IS_SYMOP(op)) {
13316     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13317       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13318       return;
13319     }
13320     pic16_aopOp (op, ic, FALSE);
13321     for (i=0; i < AOP_SIZE(op); i++) {
13322       // may need to protect this from the peepholer -- this is not nice but works...
13323       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13324       pic16_mov2w (AOP(op),i);
13325       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13326     } // for i
13327     pic16_freeAsmop (op, NULL, ic, TRUE);
13328   } else if (op) {
13329     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13330   } // if
13331 }
13332
13333 /*-----------------------------------------------------------------*/
13334 /* genpic16Code - generate code for pic16 based controllers        */
13335 /*-----------------------------------------------------------------*/
13336 /*
13337  * At this point, ralloc.c has gone through the iCode and attempted
13338  * to optimize in a way suitable for a PIC. Now we've got to generate
13339  * PIC instructions that correspond to the iCode.
13340  *
13341  * Once the instructions are generated, we'll pass through both the
13342  * peep hole optimizer and the pCode optimizer.
13343  *-----------------------------------------------------------------*/
13344
13345 void genpic16Code (iCode *lic)
13346 {
13347   iCode *ic;
13348   int cln = 0;
13349
13350     lineHead = lineCurr = NULL;
13351
13352     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13353     pic16_addpBlock(pb);
13354
13355 #if 0
13356     /* if debug information required */
13357     if (options.debug && currFunc) {
13358       if (currFunc) {
13359         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13360       }
13361     }
13362 #endif
13363
13364     for (ic = lic ; ic ; ic = ic->next ) {
13365
13366       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13367       if ( cln != ic->lineno ) {
13368         if ( options.debug ) {
13369           debugFile->writeCLine (ic);
13370         }
13371         
13372         if(!options.noCcodeInAsm) {
13373           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13374               printCLine(ic->filename, ic->lineno)));
13375         }
13376
13377         cln = ic->lineno ;
13378       }
13379         
13380       if(options.iCodeInAsm) {
13381         char *l;
13382
13383           /* insert here code to print iCode as comment */
13384           l = Safe_strdup(printILine(ic));
13385           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13386       }
13387
13388       /* if the result is marked as
13389        * spilt and rematerializable or code for
13390        * this has already been generated then
13391        * do nothing */
13392       if (resultRemat(ic) || ic->generated ) 
13393         continue ;
13394         
13395       /* depending on the operation */
13396       switch (ic->op) {
13397         case '!' :
13398           pic16_genNot(ic);
13399           break;
13400             
13401         case '~' :
13402           pic16_genCpl(ic);
13403           break;
13404             
13405         case UNARYMINUS:
13406           genUminus (ic);
13407           break;
13408             
13409         case IPUSH:
13410           genIpush (ic);
13411           break;
13412             
13413         case IPOP:
13414           /* IPOP happens only when trying to restore a 
13415            * spilt live range, if there is an ifx statement
13416            * following this pop then the if statement might
13417            * be using some of the registers being popped which
13418            * would destroy the contents of the register so
13419            * we need to check for this condition and handle it */
13420            if (ic->next
13421              && ic->next->op == IFX
13422              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13423                genIfx (ic->next,ic);
13424           else
13425             genIpop (ic);
13426           break; 
13427             
13428         case CALL:
13429           genCall (ic);
13430           break;
13431             
13432         case PCALL:
13433           genPcall (ic);
13434           break;
13435             
13436         case FUNCTION:
13437           genFunction (ic);
13438           break;
13439             
13440         case ENDFUNCTION:
13441           genEndFunction (ic);
13442           break;
13443             
13444         case RETURN:
13445           genRet (ic);
13446           break;
13447             
13448         case LABEL:
13449           genLabel (ic);
13450           break;
13451             
13452         case GOTO:
13453           genGoto (ic);
13454           break;
13455             
13456         case '+' :
13457           pic16_genPlus (ic) ;
13458           break;
13459             
13460         case '-' :
13461           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13462             pic16_genMinus (ic);
13463           break;
13464
13465         case '*' :
13466           genMult (ic);
13467           break;
13468             
13469         case '/' :
13470           genDiv (ic) ;
13471           break;
13472             
13473         case '%' :
13474           genMod (ic);
13475           break;
13476             
13477         case '>' :
13478           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13479           break;
13480             
13481         case '<' :
13482           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13483           break;
13484             
13485         case LE_OP:
13486         case GE_OP:
13487         case NE_OP:
13488           /* note these two are xlated by algebraic equivalence
13489            * during parsing SDCC.y */
13490           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13491             "got '>=' or '<=' shouldn't have come here");
13492           break;
13493
13494         case EQ_OP:
13495           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13496           break;            
13497             
13498         case AND_OP:
13499           genAndOp (ic);
13500           break;
13501             
13502         case OR_OP:
13503           genOrOp (ic);
13504           break;
13505             
13506         case '^' :
13507           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13508           break;
13509             
13510         case '|' :
13511           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13512           break;
13513             
13514         case BITWISEAND:
13515           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13516           break;
13517             
13518         case INLINEASM:
13519           genInline (ic);
13520           break;
13521             
13522         case RRC:
13523           genRRC (ic);
13524           break;
13525             
13526         case RLC:
13527           genRLC (ic);
13528           break;
13529             
13530         case GETHBIT:
13531           genGetHbit (ic);
13532           break;
13533             
13534         case LEFT_OP:
13535           genLeftShift (ic);
13536           break;
13537             
13538         case RIGHT_OP:
13539           genRightShift (ic);
13540           break;
13541             
13542         case GET_VALUE_AT_ADDRESS:
13543           genPointerGet(ic);
13544           break;
13545             
13546         case '=' :
13547           if (POINTER_SET(ic))
13548             genPointerSet(ic);
13549           else
13550             genAssign(ic);
13551           break;
13552             
13553         case IFX:
13554           genIfx (ic,NULL);
13555           break;
13556             
13557         case ADDRESS_OF:
13558           genAddrOf (ic);
13559           break;
13560             
13561         case JUMPTABLE:
13562           genJumpTab (ic);
13563           break;
13564             
13565         case CAST:
13566           genCast (ic);
13567           break;
13568             
13569         case RECEIVE:
13570           genReceive(ic);
13571           break;
13572             
13573         case SEND:
13574           addSet(&_G.sendSet,ic);
13575           break;
13576
13577         case DUMMY_READ_VOLATILE:
13578           genDummyRead (ic);
13579           break;
13580
13581         default :
13582           ic = ic;
13583       }
13584     }
13585
13586
13587     /* now we are ready to call the
13588        peep hole optimizer */
13589     if (!options.nopeep)
13590       peepHole (&lineHead);
13591
13592     /* now do the actual printing */
13593     printLine (lineHead, codeOutFile);
13594
13595 #ifdef PCODE_DEBUG
13596     DFPRINTF((stderr,"printing pBlock\n\n"));
13597     pic16_printpBlock(stdout,pb);
13598 #endif
13599
13600     return;
13601 }
13602