735f113ccfc8e3ce4515644761cde442b807b04d
[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         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1293         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1294           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1295                                                   getSize(sym->type), 
1296                                                   sym->usl.spillLoc->offset, op);
1297         } else {
1298           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1299           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1300           assert (getSize(sym->type) <= 1);
1301           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1302         }
1303         aop->size = getSize(sym->type);
1304
1305         return;
1306     }
1307
1308     {
1309       sym_link *type = operandType(op);
1310 #if 0
1311       if(IS_PTR_CONST(type)) 
1312 #else
1313       if(IS_CODEPTR(type)) 
1314 #endif
1315         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1316     }
1317
1318     /* must be in a register */
1319     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1320     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1321     aop->size = sym->nRegs;
1322     for ( i = 0 ; i < sym->nRegs ;i++)
1323         aop->aopu.aop_reg[i] = sym->regs[i];
1324 }
1325
1326 /*-----------------------------------------------------------------*/
1327 /* pic16_freeAsmop - free up the asmop given to an operand               */
1328 /*----------------------------------------------------------------*/
1329 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1330 {   
1331     asmop *aop ;
1332
1333     if (!op)
1334         aop = aaop;
1335     else 
1336         aop = op->aop;
1337
1338     if (!aop)
1339         return ;
1340
1341     if (aop->freed)
1342         goto dealloc; 
1343
1344     aop->freed = 1;
1345
1346     /* depending on the asmop type only three cases need work AOP_RO
1347        , AOP_R1 && AOP_STK */
1348 #if 1
1349     switch (aop->type) {
1350         case AOP_FSR0 :
1351             if (_G.fsr0Pushed ) {
1352                 if (pop) {
1353                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1354                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1355 //                    pic16_emitcode ("pop","ar0");
1356                     _G.fsr0Pushed--;
1357                 }
1358             }
1359             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1360             break;
1361
1362         case AOP_FSR2 :
1363             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1364             break;
1365
1366         case AOP_R0 :
1367             if (_G.r0Pushed ) {
1368                 if (pop) {
1369                     pic16_emitcode ("pop","ar0");     
1370                     _G.r0Pushed--;
1371                 }
1372             }
1373             bitVectUnSetBit(ic->rUsed,R0_IDX);
1374             break;
1375
1376         case AOP_R1 :
1377             if (_G.r1Pushed ) {
1378                 if (pop) {
1379                     pic16_emitcode ("pop","ar1");
1380                     _G.r1Pushed--;
1381                 }
1382             }
1383             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1384             break;
1385
1386         case AOP_STA:
1387           {
1388             int i;
1389
1390               /* we must store the result on stack */
1391               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1392                 // operands on stack are accessible via "FSR2 + index" with index
1393                 // starting at 2 for arguments and growing from 0 downwards for
1394                 // local variables (index == 0 is not assigned so we add one here)
1395                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1396                 if (soffs <= 0) {
1397                   assert (soffs < 0);
1398                   soffs++;
1399                 } // if
1400                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1401                 for(i=0;i<aop->size;i++) {
1402                   /* initialise for stack access via frame pointer */
1403                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1404                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1405                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1406                 }
1407         
1408                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1409               }
1410
1411               if(!_G.resDirect) {
1412                 for(i=0;i<aop->size;i++) {
1413                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1414
1415                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1416                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1417 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1418                   }
1419                 }
1420                 
1421                 {
1422                   regs *sr;
1423                   
1424                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1425                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1426                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1427                       deleteSetItem( &_G.sregsAllocSet, sr );
1428                     }
1429                 }
1430               }
1431               _G.resDirect = 0;
1432           }
1433           break;
1434 #if 0
1435         case AOP_STK :
1436         {
1437             int sz = aop->size;    
1438             int stk = aop->aopu.aop_stk + aop->size;
1439             bitVectUnSetBit(ic->rUsed,R0_IDX);
1440             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1441
1442             getFreePtr(ic,&aop,FALSE);
1443             
1444             if (options.stack10bit)
1445             {
1446                 /* I'm not sure what to do here yet... */
1447                 /* #STUB */
1448                 fprintf(stderr, 
1449                         "*** Warning: probably generating bad code for "
1450                         "10 bit stack mode.\n");
1451             }
1452             
1453             if (stk) {
1454                 pic16_emitcode ("mov","a,_bp");
1455                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1456                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1457             } else {
1458                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1459             }
1460
1461             while (sz--) {
1462                 pic16_emitcode("pop","acc");
1463                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1464                 if (!sz) break;
1465                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1466             }
1467             op->aop = aop;
1468             pic16_freeAsmop(op,NULL,ic,TRUE);
1469             if (_G.r0Pushed) {
1470                 pic16_emitcode("pop","ar0");
1471                 _G.r0Pushed--;
1472             }
1473
1474             if (_G.r1Pushed) {
1475                 pic16_emitcode("pop","ar1");
1476                 _G.r1Pushed--;
1477             }       
1478         }
1479 #endif
1480
1481     }
1482 #endif
1483
1484 dealloc:
1485     /* all other cases just dealloc */
1486     if (op ) {
1487         op->aop = NULL;
1488         if (IS_SYMOP(op)) {
1489             OP_SYMBOL(op)->aop = NULL;    
1490             /* if the symbol has a spill */
1491             if (SPIL_LOC(op))
1492                 SPIL_LOC(op)->aop = NULL;
1493         }
1494     }
1495 }
1496
1497 /*-----------------------------------------------------------------*/
1498 /* pic16_aopGet - for fetching value of the aop                          */
1499 /*-----------------------------------------------------------------*/
1500 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1501 {
1502     char *s = buffer ;
1503     char *rs;
1504
1505     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1506
1507     /* offset is greater than size then zero */
1508     if (offset > (aop->size - 1) &&
1509         aop->type != AOP_LIT)
1510         return zero;
1511
1512     /* depending on type */
1513     switch (aop->type) {
1514
1515     case AOP_FSR0:
1516     case AOP_FSR2:
1517       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1518       rs = Safe_calloc(1, strlen(s)+1);
1519       strcpy(rs, s);
1520       return (rs);
1521       
1522 #if 0
1523       /* if we need to increment it */
1524       while (offset > aop->coff)
1525         {
1526           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1527           aop->coff++;
1528         }
1529
1530       while (offset < aop->coff)
1531         {
1532           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1533           aop->coff--;
1534         }
1535       aop->coff = offset;
1536       if (aop->paged)
1537         {
1538           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1539           return (dname ? "acc" : "a");
1540         }
1541       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1542       rs = Safe_calloc (1, strlen (s) + 1);
1543       strcpy (rs, s);
1544       return rs;
1545 #endif
1546
1547         
1548     case AOP_IMMD:
1549         if (bit16) 
1550             sprintf (s,"%s",aop->aopu.aop_immd);
1551         else
1552             if (offset) 
1553                 sprintf(s,"(%s >> %d)",
1554                         aop->aopu.aop_immd,
1555                         offset*8);
1556             else
1557                 sprintf(s,"%s",
1558                         aop->aopu.aop_immd);
1559         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1560         rs = Safe_calloc(1,strlen(s)+1);
1561         strcpy(rs,s);   
1562         return rs;
1563         
1564     case AOP_DIR:
1565       if (offset) {
1566         sprintf(s,"(%s + %d)",
1567                 aop->aopu.aop_dir,
1568                 offset);
1569         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1570       } else
1571             sprintf(s,"%s",aop->aopu.aop_dir);
1572         rs = Safe_calloc(1,strlen(s)+1);
1573         strcpy(rs,s);   
1574         return rs;
1575         
1576     case AOP_REG:
1577       return aop->aopu.aop_reg[offset]->name;
1578         
1579     case AOP_CRY:
1580       return aop->aopu.aop_dir;
1581         
1582     case AOP_ACC:
1583         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1584 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1585 //        assert( 0 );
1586 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1587         rs = Safe_strdup("WREG");
1588         return (rs);
1589
1590     case AOP_LIT:
1591         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1592         rs = Safe_calloc(1,strlen(s)+1);
1593         strcpy(rs,s);   
1594         return rs;
1595         
1596     case AOP_STR:
1597         aop->coff = offset ;
1598
1599 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1600 //          dname)
1601 //          return "acc";
1602         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1603           aop->type = AOP_ACC;
1604           return Safe_strdup("_WREG");
1605         }
1606         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1607         
1608         return aop->aopu.aop_str[offset];
1609         
1610     case AOP_PCODE:
1611       {
1612         pCodeOp *pcop = aop->aopu.pcop;
1613         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1614         if(pcop->name) {
1615           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1616           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1617           if (offset) {
1618             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1619           } else {
1620             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1621           }
1622         } else
1623           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1624
1625       }
1626       rs = Safe_calloc(1,strlen(s)+1);
1627       strcpy(rs,s);   
1628       return rs;
1629
1630 #if 0
1631     case AOP_PAGED:
1632       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1633       if (offset) {
1634         sprintf(s,"(%s + %d)",
1635                 aop->aopu.aop_dir,
1636                 offset);
1637       } else
1638             sprintf(s,"%s",aop->aopu.aop_dir);
1639       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1640       rs = Safe_calloc(1,strlen(s)+1);
1641       strcpy(rs,s);   
1642       return rs;
1643 #endif
1644
1645     case AOP_STA:
1646         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1647         return (rs);
1648         
1649     case AOP_STK:
1650 //        pCodeOp *pcop = aop->aop
1651         break;
1652
1653     }
1654
1655     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1656     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1657            "aopget got unsupported aop->type");
1658     exit(0);
1659 }
1660
1661
1662
1663 /* lock has the following meaning: When allocating temporary registers
1664  * for stack variables storage, the value of the temporary register is
1665  * saved on stack. Its value is restored at the end. This procedure is
1666  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1667  * a possibility that before a call to pic16_aopOp, a temporary register
1668  * is allocated for a while and it is freed after some time, this will
1669  * mess the stack and values will not be restored properly. So use lock=1
1670  * to allocate temporary registers used internally by the programmer, and
1671  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1672  * to inform the compiler developer about a possible bug. This is an internal
1673  * feature for developing the compiler -- VR */
1674  
1675 int _TempReg_lock = 0;
1676 /*-----------------------------------------------------------------*/
1677 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1678 /*-----------------------------------------------------------------*/
1679 pCodeOp *pic16_popGetTempReg(int lock)
1680 {
1681   pCodeOp *pcop=NULL;
1682   symbol *cfunc;
1683
1684 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1685     if(_TempReg_lock) {
1686 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1687     }
1688     
1689     _TempReg_lock += lock;
1690     
1691     cfunc = currFunc;
1692     currFunc = NULL;
1693
1694 #if 0
1695         {
1696           regs *rr;
1697           int i;
1698
1699                 /* this code might seem better but it does the *same* job with
1700                  * the old code, it all depends on ralloc.c to get a free/unused
1701                  * register */
1702          
1703                 i=0;
1704                 while(i < pic16_nRegs) {
1705                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1706                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1707                         if((!rr || (rr && rr->isFree))
1708                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1709                                 pcop = pic16_newpCodeOpReg( i );
1710                                 PCOR(pcop)->r->wasUsed = 1;
1711                                 PCOR(pcop)->r->isFree = 0;
1712                                 break;
1713                         }
1714                         i++;
1715                 }
1716
1717                 if(pcop) {
1718                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1719                 }
1720         }
1721 #else
1722     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1723     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1724       PCOR(pcop)->r->wasUsed=1;
1725       PCOR(pcop)->r->isFree=0;
1726
1727       /* push value on stack */
1728       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1729     }
1730 #endif
1731
1732     currFunc = cfunc;
1733
1734   return pcop;
1735 }
1736
1737 /*-----------------------------------------------------------------*/
1738 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1739 /*                           is not part of f, but don't save if   */
1740 /*                           inside v                              */
1741 /*-----------------------------------------------------------------*/
1742 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1743 {
1744   pCodeOp *pcop=NULL;
1745   symbol *cfunc;
1746   int i;
1747
1748 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1749
1750     if(_TempReg_lock) {
1751 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1752     }
1753
1754     _TempReg_lock += lock;
1755
1756     cfunc = currFunc;
1757     currFunc = NULL;
1758
1759     i = bitVectFirstBit(f);
1760     while(i < 128) {
1761
1762       /* bypass registers that are used by function */
1763       if(!bitVectBitValue(f, i)) {
1764       
1765         /* bypass registers that are already allocated for stack access */
1766         if(!bitVectBitValue(v, i))  {
1767         
1768 //          debugf("getting register rIdx = %d\n", i);
1769           /* ok, get the operand */
1770           pcop = pic16_newpCodeOpReg( i );
1771     
1772           /* should never by NULL */
1773           assert( pcop != NULL );
1774
1775           
1776           /* sanity check */
1777           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1778             int found=0;
1779             
1780               PCOR(pcop)->r->wasUsed=1;
1781               PCOR(pcop)->r->isFree=0;
1782
1783
1784               {
1785                 regs *sr;
1786               
1787                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1788
1789                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1790                       /* already used in previous steps, break */
1791                       found=1;          
1792                       break;
1793                     }
1794                   }
1795               }
1796
1797               /* caller takes care of the following */
1798 //              bitVectSetBit(v, i);
1799
1800               if(!found) {
1801                 /* push value on stack */
1802                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1803                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1804               }
1805           
1806             break;
1807           }
1808         }
1809       }
1810       i++;
1811     }
1812
1813     currFunc = cfunc;
1814
1815   return pcop;
1816 }
1817
1818
1819 /*-----------------------------------------------------------------*/
1820 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1821 /*-----------------------------------------------------------------*/
1822 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1823 {
1824   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1825
1826   _TempReg_lock -= lock;
1827
1828   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1829     PCOR(pcop)->r->isFree = 1;
1830
1831     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1832   }
1833 }
1834 /*-----------------------------------------------------------------*/
1835 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1836 /*-----------------------------------------------------------------*/
1837 pCodeOp *pic16_popGetLabel(int key)
1838 {
1839
1840   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1841
1842   if(key>max_key)
1843     max_key = key;
1844
1845   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1846 }
1847
1848 /*-----------------------------------------------------------------*/
1849 /* pic16_popCopyReg - copy a pcode operator                              */
1850 /*-----------------------------------------------------------------*/
1851 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1852 {
1853   pCodeOpReg *pcor;
1854
1855   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1856   memcpy (pcor, pc, sizeof (pCodeOpReg));
1857   pcor->r->wasUsed = 1;
1858   
1859   //pcor->pcop.type = pc->pcop.type;
1860   if(pc->pcop.name) {
1861     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1862       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1863   } else
1864     pcor->pcop.name = NULL;
1865
1866   //pcor->r = pc->r;
1867   //pcor->rIdx = pc->rIdx;
1868   //pcor->r->wasUsed=1;
1869   //pcor->instance = pc->instance;
1870
1871 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1872
1873   return PCOP(pcor);
1874 }
1875
1876 /*-----------------------------------------------------------------*/
1877 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1878 /*-----------------------------------------------------------------*/
1879 pCodeOp *pic16_popGetLit(int lit)
1880 {
1881   return pic16_newpCodeOpLit(lit);
1882 }
1883
1884 /* Allow for 12 bit literals (LFSR x, <here!>). */
1885 pCodeOp *pic16_popGetLit12(int lit)
1886 {
1887   return pic16_newpCodeOpLit12(lit);
1888 }
1889
1890 /*-----------------------------------------------------------------*/
1891 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1892 /*-----------------------------------------------------------------*/
1893 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1894 {
1895   return pic16_newpCodeOpLit2(lit, arg2);
1896 }
1897
1898
1899 /*-----------------------------------------------------------------*/
1900 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1901 /*-----------------------------------------------------------------*/
1902 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1903 {
1904   return pic16_newpCodeOpImmd(name, offset,index, 0);
1905 }
1906
1907
1908 /*-----------------------------------------------------------------*/
1909 /* pic16_popGet - asm operator to pcode operator conversion              */
1910 /*-----------------------------------------------------------------*/
1911 pCodeOp *pic16_popGetWithString(char *str)
1912 {
1913   pCodeOp *pcop;
1914
1915
1916   if(!str) {
1917     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1918     exit (1);
1919   }
1920
1921   pcop = pic16_newpCodeOp(str,PO_STR);
1922
1923   return pcop;
1924 }
1925
1926 /*-----------------------------------------------------------------*/
1927 /* pic16_popRegFromString -                                        */
1928 /*-----------------------------------------------------------------*/
1929 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1930 {
1931
1932   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1933   pcop->type = PO_DIR;
1934
1935   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1936   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1937
1938   if(!str)
1939     str = "BAD_STRING";
1940
1941   pcop->name = Safe_calloc(1,strlen(str)+1);
1942   strcpy(pcop->name,str);
1943
1944   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1945
1946   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1947 //  PCOR(pcop)->r->wasUsed = 1;
1948
1949   /* make sure that register doesn't exist,
1950    * and operand isn't NULL
1951    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1952   if((PCOR(pcop)->r == NULL) 
1953     && (op)
1954     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1955 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1956 //              __FUNCTION__, __LINE__, str, size, offset);
1957
1958     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1959     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1960
1961   }
1962   PCOR(pcop)->instance = offset;
1963
1964   return pcop;
1965 }
1966
1967 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1968 {
1969   pCodeOp *pcop;
1970
1971 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1972 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1973         
1974         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1975         PCOR(pcop)->rIdx = rIdx;
1976         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1977         if(!PCOR(pcop)->r)
1978                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1979                 
1980         PCOR(pcop)->r->isFree = 0;
1981         PCOR(pcop)->r->wasUsed = 1;
1982
1983         pcop->type = PCOR(pcop)->r->pc_type;
1984
1985   return pcop;
1986 }
1987
1988 /*---------------------------------------------------------------------------------*/
1989 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1990 /*                 VR 030601                                                       */
1991 /*---------------------------------------------------------------------------------*/
1992 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1993 {
1994   pCodeOpReg2 *pcop2;
1995   pCodeOp *temp;
1996   
1997         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1998
1999         /* comment the following check, so errors to throw up */
2000 //      if(!pcop2)return NULL;
2001
2002         temp = pic16_popGet(aop_dst, offset);
2003         pcop2->pcop2 = temp;
2004         
2005   return PCOP(pcop2);
2006 }
2007
2008
2009
2010 /*--------------------------------------------------------------------------------.-*/
2011 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2012 /*                  VR 030601 , adapted by Hans Dorn                                */
2013 /*--------------------------------------------------------------------------------.-*/
2014 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2015 {
2016   pCodeOpReg2 *pcop2;
2017  
2018         pcop2 = (pCodeOpReg2 *)src;
2019         pcop2->pcop2 = dst;
2020         
2021         return PCOP(pcop2);
2022 }
2023
2024
2025
2026 /*---------------------------------------------------------------------------------*/
2027 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2028 /*                     movff instruction                                           */
2029 /*---------------------------------------------------------------------------------*/
2030 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2031 {
2032   pCodeOpReg2 *pcop2;
2033
2034         if(!noalloc) {
2035                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
2036                 pcop2->pcop2 = pic16_popCopyReg(dst);
2037         } else {
2038                 /* the pCodeOp may be already allocated */
2039                 pcop2 = (pCodeOpReg2 *)(src);
2040                 pcop2->pcop2 = (pCodeOp *)(dst);
2041         }
2042
2043   return PCOP(pcop2);
2044 }
2045
2046
2047 /*-----------------------------------------------------------------*/
2048 /* pic16_popGet - asm operator to pcode operator conversion              */
2049 /*-----------------------------------------------------------------*/
2050 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2051 {
2052 //  char *s = buffer ;
2053 //  char *rs;
2054   pCodeOp *pcop;
2055
2056         FENTRY2;
2057                 /* offset is greater than
2058                  * size then zero */
2059
2060 //    if (offset > (aop->size - 1) &&
2061 //        aop->type != AOP_LIT)
2062 //      return NULL;  //zero;
2063
2064     /* depending on type */
2065     switch (aop->type) {
2066                 case AOP_R0:
2067                 case AOP_R1:
2068                 case AOP_DPTR:
2069                 case AOP_DPTR2:
2070                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2071                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2072                         assert( 0 );
2073                         return NULL;
2074
2075                 case AOP_FSR0:
2076                 case AOP_FSR2:
2077                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2078                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2079                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2080                         PCOR(pcop)->r->wasUsed = 1;
2081                         PCOR(pcop)->r->isFree = 0;
2082       
2083                         PCOR(pcop)->instance = offset;
2084                         pcop->type = PCOR(pcop)->r->pc_type;
2085                         return (pcop);
2086
2087                 case AOP_IMMD:
2088                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2089                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2090
2091                 case AOP_STA:
2092                         /* pCodeOp is already allocated from aopForSym */
2093                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2094                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2095                         return (pcop);
2096       
2097                 case AOP_ACC:
2098                         {
2099                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2100
2101                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2102
2103                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2104         
2105                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2106                                 PCOR(pcop)->rIdx = rIdx;
2107                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2108                                 PCOR(pcop)->r->wasUsed=1;
2109                                 PCOR(pcop)->r->isFree=0;
2110
2111                                 PCOR(pcop)->instance = offset;
2112                                 pcop->type = PCOR(pcop)->r->pc_type;
2113 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2114                                 return pcop;
2115
2116
2117 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2118 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2119
2120 //      assert( 0 );
2121                         }
2122         
2123     case AOP_DIR:
2124       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2125       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2126         
2127 #if 0
2128     case AOP_PAGED:
2129       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2130       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2131 #endif
2132
2133     case AOP_REG:
2134       {
2135         int rIdx;
2136         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2137         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2138
2139         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2140         
2141         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2142 //      pcop->type = PO_GPR_REGISTER;
2143         PCOR(pcop)->rIdx = rIdx;
2144         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2145         PCOR(pcop)->r->wasUsed=1;
2146         PCOR(pcop)->r->isFree=0;
2147
2148         PCOR(pcop)->instance = offset;
2149         pcop->type = PCOR(pcop)->r->pc_type;
2150         
2151         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2152 //      rs = aop->aopu.aop_reg[offset]->name;
2153 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2154         return pcop;
2155       }
2156
2157     case AOP_CRY:
2158         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2159
2160       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2161       PCOR(pcop)->instance = offset;
2162       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2163       //if(PCOR(pcop)->r == NULL)
2164       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2165       return pcop;
2166         
2167     case AOP_LIT:
2168         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2169       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2170
2171     case AOP_STR:
2172       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2173       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2174
2175       /*
2176       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2177       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2178       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2179       pcop->type = PCOR(pcop)->r->pc_type;
2180       pcop->name = PCOR(pcop)->r->name;
2181
2182       return pcop;
2183       */
2184
2185     case AOP_PCODE:
2186       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2187                           __LINE__, 
2188                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2189       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2190       switch( aop->aopu.pcop->type ) {
2191         case PO_DIR: PCOR(pcop)->instance += offset; break;
2192         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2193         case PO_WREG:
2194             assert (offset==0);
2195             break;
2196         default:
2197           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2198           assert( 0 );  /* should never reach here */;
2199       }
2200       return pcop;
2201     }
2202
2203     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2204            "pic16_popGet got unsupported aop->type");
2205     exit(0);
2206 }
2207 /*-----------------------------------------------------------------*/
2208 /* pic16_aopPut - puts a string for a aop                                */
2209 /*-----------------------------------------------------------------*/
2210 void pic16_aopPut (asmop *aop, char *s, int offset)
2211 {
2212     char *d = buffer ;
2213     symbol *lbl ;
2214
2215     return;
2216
2217     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2218
2219     if (aop->size && offset > ( aop->size - 1)) {
2220         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2221                "pic16_aopPut got offset > aop->size");
2222         exit(0);
2223     }
2224
2225     /* will assign value to value */
2226     /* depending on where it is ofcourse */
2227     switch (aop->type) {
2228     case AOP_DIR:
2229       if (offset) {
2230         sprintf(d,"(%s + %d)",
2231                 aop->aopu.aop_dir,offset);
2232         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2233
2234       } else
2235             sprintf(d,"%s",aop->aopu.aop_dir);
2236         
2237         if (strcmp(d,s)) {
2238           DEBUGpic16_emitcode(";","%d",__LINE__);
2239           if(strcmp(s,"W"))
2240             pic16_emitcode("movf","%s,w",s);
2241           pic16_emitcode("movwf","%s",d);
2242
2243           if(strcmp(s,"W")) {
2244             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2245             if(offset >= aop->size) {
2246               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2247               break;
2248             } else
2249               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2250           }
2251
2252           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2253
2254
2255         }
2256         break;
2257         
2258     case AOP_REG:
2259       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2260         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2261           /*
2262             if (*s == '@'           ||
2263                 strcmp(s,"r0") == 0 ||
2264                 strcmp(s,"r1") == 0 ||
2265                 strcmp(s,"r2") == 0 ||
2266                 strcmp(s,"r3") == 0 ||
2267                 strcmp(s,"r4") == 0 ||
2268                 strcmp(s,"r5") == 0 ||
2269                 strcmp(s,"r6") == 0 || 
2270                 strcmp(s,"r7") == 0 )
2271                 pic16_emitcode("mov","%s,%s  ; %d",
2272                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2273             else
2274           */
2275
2276           if(strcmp(s,"W")==0 )
2277             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2278
2279           pic16_emitcode("movwf","%s",
2280                    aop->aopu.aop_reg[offset]->name);
2281
2282           if(strcmp(s,zero)==0) {
2283             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2284
2285           } else if(strcmp(s,"W")==0) {
2286             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2287             pcop->type = PO_GPR_REGISTER;
2288
2289             PCOR(pcop)->rIdx = -1;
2290             PCOR(pcop)->r = NULL;
2291
2292             DEBUGpic16_emitcode(";","%d",__LINE__);
2293             pcop->name = Safe_strdup(s);
2294             pic16_emitpcode(POC_MOVFW,pcop);
2295             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2296           } else if(strcmp(s,one)==0) {
2297             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2298             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2299           } else {
2300             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2301           }
2302         }
2303         break;
2304         
2305     case AOP_DPTR:
2306     case AOP_DPTR2:
2307     
2308     if (aop->type == AOP_DPTR2)
2309     {
2310         genSetDPTR(1);
2311     }
2312     
2313         if (aop->code) {
2314             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2315                    "pic16_aopPut writting to code space");
2316             exit(0);
2317         }
2318         
2319         while (offset > aop->coff) {
2320             aop->coff++;
2321             pic16_emitcode ("inc","dptr");
2322         }
2323         
2324         while (offset < aop->coff) {
2325             aop->coff-- ;
2326             pic16_emitcode("lcall","__decdptr");
2327         }
2328         
2329         aop->coff = offset;
2330         
2331         /* if not in accumulater */
2332         MOVA(s);        
2333         
2334         pic16_emitcode ("movx","@dptr,a");
2335         
2336     if (aop->type == AOP_DPTR2)
2337     {
2338         genSetDPTR(0);
2339     }
2340         break;
2341         
2342     case AOP_R0:
2343     case AOP_R1:
2344         while (offset > aop->coff) {
2345             aop->coff++;
2346             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2347         }
2348         while (offset < aop->coff) {
2349             aop->coff-- ;
2350             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2351         }
2352         aop->coff = offset;
2353         
2354         if (aop->paged) {
2355             MOVA(s);           
2356             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2357             
2358         } else
2359             if (*s == '@') {
2360                 MOVA(s);
2361                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2362             } else
2363                 if (strcmp(s,"r0") == 0 ||
2364                     strcmp(s,"r1") == 0 ||
2365                     strcmp(s,"r2") == 0 ||
2366                     strcmp(s,"r3") == 0 ||
2367                     strcmp(s,"r4") == 0 ||
2368                     strcmp(s,"r5") == 0 ||
2369                     strcmp(s,"r6") == 0 || 
2370                     strcmp(s,"r7") == 0 ) {
2371                     char buffer[10];
2372                     sprintf(buffer,"a%s",s);
2373                     pic16_emitcode("mov","@%s,%s",
2374                              aop->aopu.aop_ptr->name,buffer);
2375                 } else
2376                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2377         
2378         break;
2379         
2380     case AOP_STK:
2381         if (strcmp(s,"a") == 0)
2382             pic16_emitcode("push","acc");
2383         else
2384             pic16_emitcode("push","%s",s);
2385         
2386         break;
2387         
2388     case AOP_CRY:
2389         /* if bit variable */
2390         if (!aop->aopu.aop_dir) {
2391             pic16_emitcode("clr","a");
2392             pic16_emitcode("rlc","a");
2393         } else {
2394             if (s == zero) 
2395                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2396             else
2397                 if (s == one)
2398                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2399                 else
2400                     if (!strcmp(s,"c"))
2401                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2402                     else {
2403                         lbl = newiTempLabel(NULL);
2404                         
2405                         if (strcmp(s,"a")) {
2406                             MOVA(s);
2407                         }
2408                         pic16_emitcode("clr","c");
2409                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2410                         pic16_emitcode("cpl","c");
2411                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2412                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2413                     }
2414         }
2415         break;
2416         
2417     case AOP_STR:
2418         aop->coff = offset;
2419         if (strcmp(aop->aopu.aop_str[offset],s))
2420             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2421         break;
2422         
2423     case AOP_ACC:
2424         aop->coff = offset;
2425         if (!offset && (strcmp(s,"acc") == 0))
2426             break;
2427         
2428         if (strcmp(aop->aopu.aop_str[offset],s))
2429             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2430         break;
2431
2432     default :
2433         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2434 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2435 //             "pic16_aopPut got unsupported aop->type");
2436 //      exit(0);    
2437     }    
2438
2439 }
2440
2441 /*-----------------------------------------------------------------*/
2442 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2443 /*-----------------------------------------------------------------*/
2444 void pic16_mov2w (asmop *aop, int offset)
2445 {
2446   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2447
2448   if(is_LitAOp(aop))
2449     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2450   else
2451     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2452 }
2453
2454 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2455 {
2456   if(is_LitAOp(src)) {
2457     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2458     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2459   } else {
2460     if(pic16_sameRegsOfs(src, dst, offset))return;
2461     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2462                       pic16_popGet(dst, offset)));
2463   }
2464 }
2465
2466 static void pic16_movLit2f(pCodeOp *pc, int lit)
2467 {
2468   if (0 == (lit & 0x00ff))
2469   {
2470     pic16_emitpcode (POC_CLRF, pc);
2471   } else if (0xff == (lit & 0x00ff))
2472   {
2473     pic16_emitpcode (POC_SETF, pc);
2474   } else {
2475     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2476     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2477   }
2478 }
2479
2480 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2481 {
2482   if(is_LitAOp(src)) {
2483     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2484     pic16_emitpcode(POC_MOVWF, dst);
2485   } else {
2486     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2487   }
2488 }
2489
2490 void pic16_testStackOverflow(void)
2491 {
2492 #define GSTACK_TEST_NAME        "_gstack_test"
2493
2494   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2495   
2496   {
2497     symbol *sym;
2498
2499       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2500       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2501 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2502       checkAddSym(&externs, sym);
2503   }
2504
2505 }
2506
2507 /* push pcop into stack */
2508 void pic16_pushpCodeOp(pCodeOp *pcop)
2509 {
2510 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2511   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2512   if(pic16_options.gstack)
2513     pic16_testStackOverflow();
2514     
2515 }
2516
2517 /* pop pcop from stack */
2518 void pic16_poppCodeOp(pCodeOp *pcop)
2519 {
2520   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2521   if(pic16_options.gstack)
2522     pic16_testStackOverflow();
2523 }
2524
2525
2526 /*-----------------------------------------------------------------*/
2527 /* pushw - pushes wreg to stack                                    */
2528 /*-----------------------------------------------------------------*/
2529 void pushw(void)
2530 {
2531   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2532   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2533   if(pic16_options.gstack)
2534     pic16_testStackOverflow();
2535 }
2536
2537                 
2538 /*-----------------------------------------------------------------*/
2539 /* pushaop - pushes aop to stack                                   */
2540 /*-----------------------------------------------------------------*/
2541 void pushaop(asmop *aop, int offset)
2542 {
2543   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2544
2545   if(_G.resDirect)return;
2546   
2547   if(is_LitAOp(aop)) {
2548     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2549     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2550   } else {
2551     pic16_emitpcode(POC_MOVFF,
2552       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2553   }
2554
2555   if(pic16_options.gstack)
2556     pic16_testStackOverflow();
2557 }
2558
2559 /*-----------------------------------------------------------------*/
2560 /* popaop - pops aop from stack                                    */
2561 /*-----------------------------------------------------------------*/
2562 void popaop(asmop *aop, int offset)
2563 {
2564   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2565   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2566   if(pic16_options.gstack)
2567     pic16_testStackOverflow();
2568 }
2569
2570 void popaopidx(asmop *aop, int offset, int index)
2571 {
2572   int ofs=1;
2573
2574     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2575
2576     if(STACK_MODEL_LARGE)ofs++;
2577
2578     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2579     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2580     if(pic16_options.gstack)
2581       pic16_testStackOverflow();
2582 }
2583
2584 #if !(USE_GENERIC_SIGNED_SHIFT)
2585 /*-----------------------------------------------------------------*/
2586 /* reAdjustPreg - points a register back to where it should        */
2587 /*-----------------------------------------------------------------*/
2588 static void reAdjustPreg (asmop *aop)
2589 {
2590     int size ;
2591
2592     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2593     aop->coff = 0;
2594     if ((size = aop->size) <= 1)
2595         return ;
2596     size-- ;
2597     switch (aop->type) {
2598         case AOP_R0 :
2599         case AOP_R1 :
2600             while (size--)
2601                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2602             break;          
2603         case AOP_DPTR :
2604         case AOP_DPTR2:
2605             if (aop->type == AOP_DPTR2)
2606             {
2607                 genSetDPTR(1);
2608             } 
2609             while (size--)
2610             {
2611                 pic16_emitcode("lcall","__decdptr");
2612             }
2613                 
2614             if (aop->type == AOP_DPTR2)
2615             {
2616                 genSetDPTR(0);
2617             }                
2618             break;  
2619
2620     }   
2621
2622 }
2623 #endif
2624
2625 #if 0
2626 /*-----------------------------------------------------------------*/
2627 /* opIsGptr: returns non-zero if the passed operand is             */   
2628 /* a generic pointer type.                                         */
2629 /*-----------------------------------------------------------------*/ 
2630 static int opIsGptr(operand *op)
2631 {
2632     sym_link *type = operandType(op);
2633     
2634     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2635     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2636     {
2637         return 1;
2638     }
2639     return 0;        
2640 }
2641 #endif
2642
2643 /*-----------------------------------------------------------------*/
2644 /* pic16_getDataSize - get the operand data size                         */
2645 /*-----------------------------------------------------------------*/
2646 int pic16_getDataSize(operand *op)
2647 {
2648     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2649
2650
2651     return AOP_SIZE(op);
2652
2653     // tsd- in the pic port, the genptr size is 1, so this code here
2654     // fails. ( in the 8051 port, the size was 4).
2655 #if 0
2656     int size;
2657     size = AOP_SIZE(op);
2658     if (size == GPTRSIZE)
2659     {
2660         sym_link *type = operandType(op);
2661         if (IS_GENPTR(type))
2662         {
2663             /* generic pointer; arithmetic operations
2664              * should ignore the high byte (pointer type).
2665              */
2666             size--;
2667     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2668         }
2669     }
2670     return size;
2671 #endif
2672 }
2673
2674 /*-----------------------------------------------------------------*/
2675 /* pic16_outAcc - output Acc                                             */
2676 /*-----------------------------------------------------------------*/
2677 void pic16_outAcc(operand *result)
2678 {
2679   int size,offset;
2680   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2681   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2682
2683
2684   size = pic16_getDataSize(result);
2685   if(size){
2686     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2687     size--;
2688     offset = 1;
2689     /* unsigned or positive */
2690     while(size--)
2691       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2692   }
2693
2694 }
2695
2696 /*-----------------------------------------------------------------*/
2697 /* pic16_outBitC - output a bit C                                  */
2698 /*                 Move to result the value of Carry flag -- VR    */
2699 /*-----------------------------------------------------------------*/
2700 void pic16_outBitC(operand *result)
2701 {
2702   int i;
2703
2704     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2705
2706     /* if the result is bit */
2707     if (AOP_TYPE(result) == AOP_CRY) {
2708         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2709         pic16_aopPut(AOP(result),"c",0);
2710     } else {
2711
2712         i = AOP_SIZE(result);
2713         while(i--) {
2714                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2715         }
2716         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2717     }
2718 }
2719
2720 /*-----------------------------------------------------------------*/
2721 /* pic16_outBitOp - output a bit from Op                           */
2722 /*                 Move to result the value of set/clr op -- VR    */
2723 /*-----------------------------------------------------------------*/
2724 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2725 {
2726   int i;
2727
2728     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2729
2730     /* if the result is bit */
2731     if (AOP_TYPE(result) == AOP_CRY) {
2732         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2733         pic16_aopPut(AOP(result),"c",0);
2734     } else {
2735
2736         i = AOP_SIZE(result);
2737         while(i--) {
2738                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2739         }
2740         pic16_emitpcode(POC_RRCF, pcop);          
2741         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2742     }
2743 }
2744
2745 /*-----------------------------------------------------------------*/
2746 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2747 /*-----------------------------------------------------------------*/
2748 void pic16_toBoolean(operand *oper)
2749 {
2750     int size = AOP_SIZE(oper) - 1;
2751     int offset = 1;
2752
2753     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2754
2755     if ( AOP_TYPE(oper) != AOP_ACC) {
2756       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2757     }
2758     while (size--) {
2759       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2760     }
2761 }
2762
2763 /*-----------------------------------------------------------------*/
2764 /* genUminusFloat - unary minus for floating points                */
2765 /*-----------------------------------------------------------------*/
2766 static void genUminusFloat(operand *op,operand *result)
2767 {
2768   int size ,offset =0 ;
2769   
2770     FENTRY;
2771     /* for this we just need to flip the 
2772     first it then copy the rest in place */
2773     size = AOP_SIZE(op);
2774     assert( size == AOP_SIZE(result) );
2775
2776     while(size--) {
2777       pic16_mov2f(AOP(result), AOP(op), offset);
2778       offset++;
2779     }
2780     
2781     /* toggle the MSB's highest bit */
2782     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2783 }
2784
2785 /*-----------------------------------------------------------------*/
2786 /* genUminus - unary minus code generation                         */
2787 /*-----------------------------------------------------------------*/
2788 static void genUminus (iCode *ic)
2789 {
2790   int size, i;
2791   sym_link *optype, *rtype;
2792   symbol *label;
2793   int needLabel=0;
2794
2795     FENTRY;     
2796     
2797     /* assign asmops */
2798     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2799     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2800
2801     /* if both in bit space then special case */
2802     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2803       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2804         
2805         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2806         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2807         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2808         goto release; 
2809     } 
2810
2811     optype = operandType(IC_LEFT(ic));
2812     rtype = operandType(IC_RESULT(ic));
2813
2814
2815     /* if float then do float stuff */
2816     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2817       if(IS_FIXED(optype))
2818         debugf("implement fixed16x16 type\n", 0);
2819         
2820         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2821         goto release;
2822     }
2823
2824     /* otherwise subtract from zero by taking the 2's complement */
2825     size = AOP_SIZE(IC_LEFT(ic));
2826     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2827     label = newiTempLabel ( NULL );
2828     
2829     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2830       for (i=size-1; i > 0; i--) {
2831         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2832       } // for
2833       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2834       for (i=1; i < size; i++) {
2835         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2836         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2837       } // for
2838     } else {
2839       for (i=size-1; i >= 0; i--) {
2840         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2841         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2842       } // for
2843       if (size > 1) {
2844         for (i=0; i < size-2; i++) {
2845           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2846           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2847         } // for
2848         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2849       } // if
2850       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2851     }
2852     if (needLabel)
2853       pic16_emitpLabel (label->key);
2854
2855 release:
2856     /* release the aops */
2857     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2858     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2859 }
2860
2861 #if 0
2862 /*-----------------------------------------------------------------*/
2863 /* saveRegisters - will look for a call and save the registers     */
2864 /*-----------------------------------------------------------------*/
2865 static void saveRegisters(iCode *lic) 
2866 {
2867     int i;
2868     iCode *ic;
2869     bitVect *rsave;
2870     sym_link *dtype;
2871
2872     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2873     /* look for call */
2874     for (ic = lic ; ic ; ic = ic->next) 
2875         if (ic->op == CALL || ic->op == PCALL)
2876             break;
2877
2878     if (!ic) {
2879         fprintf(stderr,"found parameter push with no function call\n");
2880         return ;
2881     }
2882
2883     /* if the registers have been saved already then
2884     do nothing */
2885     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2886         return ;
2887
2888     /* find the registers in use at this time 
2889     and push them away to safety */
2890     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2891                           ic->rUsed);
2892
2893     ic->regsSaved = 1;
2894     if (options.useXstack) {
2895         if (bitVectBitValue(rsave,R0_IDX))
2896             pic16_emitcode("mov","b,r0");
2897         pic16_emitcode("mov","r0,%s",spname);
2898         for (i = 0 ; i < pic16_nRegs ; i++) {
2899             if (bitVectBitValue(rsave,i)) {
2900                 if (i == R0_IDX)
2901                     pic16_emitcode("mov","a,b");
2902                 else
2903                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2904                 pic16_emitcode("movx","@r0,a");
2905                 pic16_emitcode("inc","r0");
2906             }
2907         }
2908         pic16_emitcode("mov","%s,r0",spname);
2909         if (bitVectBitValue(rsave,R0_IDX))
2910             pic16_emitcode("mov","r0,b");           
2911     }// else
2912     //for (i = 0 ; i < pic16_nRegs ; i++) {
2913     //    if (bitVectBitValue(rsave,i))
2914     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2915     //}
2916
2917     dtype = operandType(IC_LEFT(ic));
2918     if (currFunc && dtype && 
2919         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2920         IFFUNC_ISISR(currFunc->type) &&
2921         !ic->bankSaved) 
2922
2923         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2924
2925 }
2926 /*-----------------------------------------------------------------*/
2927 /* unsaveRegisters - pop the pushed registers                      */
2928 /*-----------------------------------------------------------------*/
2929 static void unsaveRegisters (iCode *ic)
2930 {
2931     int i;
2932     bitVect *rsave;
2933
2934     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2935     /* find the registers in use at this time 
2936     and push them away to safety */
2937     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2938                           ic->rUsed);
2939     
2940     if (options.useXstack) {
2941         pic16_emitcode("mov","r0,%s",spname);   
2942         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2943             if (bitVectBitValue(rsave,i)) {
2944                 pic16_emitcode("dec","r0");
2945                 pic16_emitcode("movx","a,@r0");
2946                 if (i == R0_IDX)
2947                     pic16_emitcode("mov","b,a");
2948                 else
2949                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2950             }       
2951
2952         }
2953         pic16_emitcode("mov","%s,r0",spname);
2954         if (bitVectBitValue(rsave,R0_IDX))
2955             pic16_emitcode("mov","r0,b");
2956     } //else
2957     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2958     //    if (bitVectBitValue(rsave,i))
2959     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2960     //}
2961
2962 }  
2963 #endif
2964
2965 #if 0  // patch 14
2966 /*-----------------------------------------------------------------*/
2967 /* pushSide -                                                      */
2968 /*-----------------------------------------------------------------*/
2969 static void pushSide(operand * oper, int size)
2970 {
2971         int offset = 0;
2972     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2973         while (size--) {
2974                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2975                 if (AOP_TYPE(oper) != AOP_REG &&
2976                     AOP_TYPE(oper) != AOP_DIR &&
2977                     strcmp(l,"a") ) {
2978                         pic16_emitcode("mov","a,%s",l);
2979                         pic16_emitcode("push","acc");
2980                 } else
2981                         pic16_emitcode("push","%s",l);
2982         }
2983 }
2984 #endif // patch 14
2985
2986 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2987 {
2988   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2989     pic16_emitpcode(POC_MOVFW, src);
2990     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2991   } else {
2992     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2993         src, pic16_popGet(AOP(op), offset)));
2994   }
2995 }
2996
2997
2998 /*-----------------------------------------------------------------*/
2999 /* assignResultValue - assign results to oper, rescall==1 is       */
3000 /*                     called from genCall() or genPcall()         */
3001 /*-----------------------------------------------------------------*/
3002 static void assignResultValue(operand * oper, int rescall)
3003 {
3004   int size = AOP_SIZE(oper);
3005   int offset=0;
3006   
3007     FENTRY2;
3008 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3009     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3010
3011     if(rescall) {
3012       /* assign result from a call/pcall function() */
3013                 
3014       /* function results are stored in a special order,
3015        * see top of file with Function return policy, or manual */
3016
3017       if(size <= 4) {
3018         /* 8-bits, result in WREG */
3019         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3020                         
3021         if(size>1) {
3022           /* 16-bits, result in PRODL:WREG */
3023           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3024         }
3025                         
3026         if(size>2) {
3027           /* 24-bits, result in PRODH:PRODL:WREG */
3028           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3029         }
3030                         
3031         if(size>3) {
3032           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3033           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3034         }
3035       
3036       } else {
3037         /* >32-bits, result on stack, and FSR0 points to beginning.
3038          * Fix stack when done */
3039         /* FIXME FIXME */
3040 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3041         while (size--) {
3042 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3043 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3044                 
3045           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3046           GpsuedoStkPtr++;
3047         }
3048                         
3049         /* fix stack */
3050         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3051         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3052         if(STACK_MODEL_LARGE) {
3053           emitSKPNC;
3054           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3055         }
3056       }                 
3057     } else {
3058       int areg = 0;             /* matching argument register */
3059       
3060 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3061       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3062
3063
3064       /* its called from genReceive (probably) -- VR */
3065       /* I hope this code will not be called from somewhere else in the future! 
3066        * We manually set the pseudo stack pointer in genReceive. - dw
3067        */
3068       if(!GpsuedoStkPtr && _G.useWreg) {
3069 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3070
3071         /* The last byte in the assignment is in W */
3072         if(areg <= GpsuedoStkPtr) {
3073           size--;
3074           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3075           offset++;
3076 //          debugf("receive from WREG\n", 0);
3077         }
3078         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3079       }
3080 //      GpsuedoStkPtr++;
3081       _G.stack_lat = AOP_SIZE(oper)-1;
3082
3083       while (size) {
3084         size--;
3085         GpsuedoStkPtr++;
3086         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3087 //        debugf("receive from STACK\n", 0);
3088         offset++;
3089       }
3090     }
3091 }
3092
3093
3094 /*-----------------------------------------------------------------*/
3095 /* genIpush - generate code for pushing this gets a little complex */
3096 /*-----------------------------------------------------------------*/
3097 static void genIpush (iCode *ic)
3098 {
3099 //  int size, offset=0;
3100
3101   FENTRY;
3102   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3103
3104   if(ic->parmPush) {
3105     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3106
3107     /* send to stack as normal */
3108     addSet(&_G.sendSet,ic);
3109 //    addSetHead(&_G.sendSet,ic);
3110     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3111   }
3112
3113         
3114 #if 0
3115     int size, offset = 0 ;
3116     char *l;
3117
3118
3119     /* if this is not a parm push : ie. it is spill push 
3120     and spill push is always done on the local stack */
3121     if (!ic->parmPush) {
3122
3123         /* and the item is spilt then do nothing */
3124         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3125             return ;
3126
3127         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3128         size = AOP_SIZE(IC_LEFT(ic));
3129         /* push it on the stack */
3130         while(size--) {
3131             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3132             if (*l == '#') {
3133                 MOVA(l);
3134                 l = "acc";
3135             }
3136             pic16_emitcode("push","%s",l);
3137         }
3138         return ;        
3139     }
3140
3141     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3142 #endif
3143 }
3144
3145 /*-----------------------------------------------------------------*/
3146 /* genIpop - recover the registers: can happen only for spilling   */
3147 /*-----------------------------------------------------------------*/
3148 static void genIpop (iCode *ic)
3149 {
3150   FENTRY;
3151   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3152 #if 0
3153     int size,offset ;
3154
3155
3156     /* if the temp was not pushed then */
3157     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3158         return ;
3159
3160     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3161     size = AOP_SIZE(IC_LEFT(ic));
3162     offset = (size-1);
3163     while (size--) 
3164         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3165                                    FALSE,TRUE));
3166
3167     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3168 #endif
3169 }
3170
3171 #if 0
3172 /*-----------------------------------------------------------------*/
3173 /* unsaverbank - restores the resgister bank from stack            */
3174 /*-----------------------------------------------------------------*/
3175 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3176 {
3177   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3178 #if 0
3179     int i;
3180     asmop *aop ;
3181     regs *r = NULL;
3182
3183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3184     if (popPsw) {
3185         if (options.useXstack) {
3186             aop = newAsmop(0);
3187             r = getFreePtr(ic,&aop,FALSE);
3188             
3189             
3190             pic16_emitcode("mov","%s,_spx",r->name);
3191             pic16_emitcode("movx","a,@%s",r->name);
3192             pic16_emitcode("mov","psw,a");
3193             pic16_emitcode("dec","%s",r->name);
3194             
3195         }else
3196             pic16_emitcode ("pop","psw");
3197     }
3198
3199     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3200         if (options.useXstack) {       
3201             pic16_emitcode("movx","a,@%s",r->name);
3202             //pic16_emitcode("mov","(%s+%d),a",
3203             //       regspic16[i].base,8*bank+regspic16[i].offset);
3204             pic16_emitcode("dec","%s",r->name);
3205
3206         } else 
3207           pic16_emitcode("pop",""); //"(%s+%d)",
3208         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3209     }
3210
3211     if (options.useXstack) {
3212
3213         pic16_emitcode("mov","_spx,%s",r->name);
3214         pic16_freeAsmop(NULL,aop,ic,TRUE);
3215
3216     }
3217 #endif 
3218 }
3219
3220 /*-----------------------------------------------------------------*/
3221 /* saverbank - saves an entire register bank on the stack          */
3222 /*-----------------------------------------------------------------*/
3223 static void saverbank (int bank, iCode *ic, bool pushPsw)
3224 {
3225   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3226 #if 0
3227     int i;
3228     asmop *aop ;
3229     regs *r = NULL;
3230
3231     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3232     if (options.useXstack) {
3233
3234         aop = newAsmop(0);
3235         r = getFreePtr(ic,&aop,FALSE);  
3236         pic16_emitcode("mov","%s,_spx",r->name);
3237
3238     }
3239
3240     for (i = 0 ; i < pic16_nRegs ;i++) {
3241         if (options.useXstack) {
3242             pic16_emitcode("inc","%s",r->name);
3243             //pic16_emitcode("mov","a,(%s+%d)",
3244             //         regspic16[i].base,8*bank+regspic16[i].offset);
3245             pic16_emitcode("movx","@%s,a",r->name);           
3246         } else 
3247           pic16_emitcode("push","");// "(%s+%d)",
3248                      //regspic16[i].base,8*bank+regspic16[i].offset);
3249     }
3250     
3251     if (pushPsw) {
3252         if (options.useXstack) {
3253             pic16_emitcode("mov","a,psw");
3254             pic16_emitcode("movx","@%s,a",r->name);     
3255             pic16_emitcode("inc","%s",r->name);
3256             pic16_emitcode("mov","_spx,%s",r->name);       
3257             pic16_freeAsmop (NULL,aop,ic,TRUE);
3258             
3259         } else
3260             pic16_emitcode("push","psw");
3261         
3262         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3263     }
3264     ic->bankSaved = 1;
3265 #endif
3266 }
3267 #endif  /* 0 */
3268
3269
3270 static int wparamCmp(void *p1, void *p2)
3271 {
3272   return (!strcmp((char *)p1, (char *)p2));
3273 }
3274
3275 int inWparamList(char *s)
3276 {
3277   return isinSetWith(wparamList, s, wparamCmp);
3278
3279
3280
3281 /*-----------------------------------------------------------------*/
3282 /* genCall - generates a call statement                            */
3283 /*-----------------------------------------------------------------*/
3284 static void genCall (iCode *ic)
3285 {
3286   sym_link *ftype;   
3287   int stackParms=0;
3288   int use_wreg=0;
3289   int inwparam=0;
3290   char *fname;
3291   
3292     FENTRY;
3293
3294     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3295     /* if caller saves & we have not saved then */
3296 //    if (!ic->regsSaved)
3297 //      saveRegisters(ic);
3298
3299         /* initialise stackParms for IPUSH pushes */
3300 //      stackParms = psuedoStkPtr;
3301 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3302     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3303     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3304
3305 #if 0
3306     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3307 #endif
3308
3309     /* if send set is not empty the assign */
3310     if (_G.sendSet) {
3311       iCode *sic;
3312       int psuedoStkPtr=-1; 
3313       int firstTimeThruLoop = 1;
3314
3315
3316         /* reverse sendSet if function is not reentrant */
3317         if(!IFFUNC_ISREENT(ftype))
3318           _G.sendSet = reverseSet(_G.sendSet);
3319
3320         /* First figure how many parameters are getting passed */
3321         stackParms = 0;
3322         use_wreg = 0;
3323         
3324         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3325           int size;
3326 //          int offset = 0;
3327
3328             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3329             size = AOP_SIZE(IC_LEFT(sic));
3330
3331             stackParms += size;
3332
3333             /* pass the last byte through WREG */
3334             if(inwparam) {
3335
3336               while (size--) {
3337                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3338                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3339                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3340
3341                 if(!firstTimeThruLoop) {
3342                   /* If this is not the first time we've been through the loop
3343                    * then we need to save the parameter in a temporary
3344                    * register. The last byte of the last parameter is
3345                    * passed in W. */
3346
3347                   pushw();
3348 //                  --psuedoStkPtr;             // sanity check
3349                   use_wreg = 1;
3350                 }
3351                 
3352                 firstTimeThruLoop=0;
3353
3354                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3355
3356 //                offset++;
3357               }
3358             } else {
3359               /* all arguments are passed via stack */
3360               use_wreg = 0;
3361
3362               while (size--) {
3363                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3364                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3365                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3366
3367 //                pushaop(AOP(IC_LEFT(sic)), size);
3368                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3369                                 
3370                 if(!_G.resDirect)
3371                   pushw();
3372               }
3373             }
3374
3375             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3376           }
3377
3378           if(inwparam) {
3379             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3380               pushw();  /* save last parameter to stack if functions has varargs */
3381               use_wreg = 0;
3382             } else
3383               use_wreg = 1;
3384           } else use_wreg = 0;
3385
3386           _G.stackRegSet = _G.sendSet;
3387           _G.sendSet = NULL;
3388     }
3389
3390     /* make the call */
3391     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3392
3393     GpsuedoStkPtr=0;
3394     
3395     /* if we need to assign a result value */
3396     if ((IS_ITEMP(IC_RESULT(ic))
3397           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3398               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3399         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3400
3401       _G.accInUse++;
3402       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3403       _G.accInUse--;
3404
3405       assignResultValue(IC_RESULT(ic), 1);
3406
3407       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3408                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3409                 
3410       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3411     }
3412
3413     if(!stackParms && ic->parmBytes) {
3414       stackParms = ic->parmBytes;
3415     }
3416       
3417     stackParms -= use_wreg;
3418     
3419     if(stackParms>0) {
3420       if(stackParms == 1) {
3421         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3422       } else {
3423         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3424         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3425       }
3426       if(STACK_MODEL_LARGE) {
3427         emitSKPNC;
3428         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3429       }
3430     }
3431
3432 #if 0
3433     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3434 #endif
3435
3436     /* adjust the stack for parameters if required */
3437 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3438
3439 #if 0
3440       /* if register bank was saved then pop them */
3441       if (ic->bankSaved)
3442         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3443
3444       /* if we hade saved some registers then unsave them */
3445       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3446         unsaveRegisters (ic);
3447 #endif
3448 }
3449
3450
3451
3452 /*-----------------------------------------------------------------*/
3453 /* genPcall - generates a call by pointer statement                */
3454 /*            new version, created from genCall - HJD              */
3455 /*-----------------------------------------------------------------*/
3456 static void genPcall (iCode *ic)
3457 {
3458   sym_link *fntype;
3459   int stackParms=0;
3460   symbol *retlbl = newiTempLabel(NULL);
3461   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3462   
3463     FENTRY;
3464
3465     fntype = operandType( IC_LEFT(ic) )->next;
3466
3467     /* if send set is not empty the assign */
3468     if (_G.sendSet) {
3469       iCode *sic;
3470       int psuedoStkPtr=-1; 
3471
3472       /* reverse sendSet if function is not reentrant */
3473       if(!IFFUNC_ISREENT(fntype))
3474         _G.sendSet = reverseSet(_G.sendSet);
3475
3476       stackParms = 0;
3477       
3478       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3479         int size;
3480
3481           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3482           size = AOP_SIZE(IC_LEFT(sic));
3483           stackParms += size;
3484
3485           /* all parameters are passed via stack, since WREG is clobbered
3486            * by the calling sequence */
3487           while (size--) {
3488             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3489             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3490             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3491
3492             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3493             pushw();
3494           }
3495
3496           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3497       }
3498
3499       _G.stackRegSet = _G.sendSet;
3500       _G.sendSet = NULL;
3501     }
3502
3503     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3504
3505     // push return address
3506     // push $ on return stack, then replace with retlbl
3507
3508     /* Thanks to Thorsten Klose for pointing out that the following
3509      * snippet should be interrupt safe */
3510     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3511     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3512
3513     pic16_emitpcodeNULLop(POC_PUSH);
3514
3515     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3516     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3517     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3518     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3519     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3520     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3521
3522
3523     /* restore interrupt control register */
3524     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3525     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3526
3527     /* make the call by writing the pointer into pc */
3528     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3529     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3530
3531     // note: MOVFF to PCL not allowed
3532     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3533     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3534
3535
3536     /* return address is here: (X) */
3537     pic16_emitpLabelFORCE(retlbl->key);
3538
3539     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3540
3541     GpsuedoStkPtr=0;
3542     /* if we need assign a result value */
3543     if ((IS_ITEMP(IC_RESULT(ic))
3544           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3545               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3546         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3547
3548       _G.accInUse++;
3549       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3550       _G.accInUse--;
3551
3552       assignResultValue(IC_RESULT(ic), 1);
3553
3554       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3555               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3556                 
3557       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3558     }
3559
3560 //    stackParms -= use_wreg;
3561     
3562     if(stackParms>0) {
3563       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3564       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3565       if(STACK_MODEL_LARGE) {
3566         emitSKPNC;
3567         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3568       }
3569     }
3570 }
3571
3572 /*-----------------------------------------------------------------*/
3573 /* resultRemat - result  is rematerializable                       */
3574 /*-----------------------------------------------------------------*/
3575 static int resultRemat (iCode *ic)
3576 {
3577   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3578   if (SKIP_IC(ic) || ic->op == IFX)
3579     return 0;
3580
3581   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3582     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3583     if (sym->remat && !POINTER_SET(ic)) 
3584       return 1;
3585   }
3586
3587   return 0;
3588 }
3589
3590 #if defined(__BORLANDC__) || defined(_MSC_VER)
3591 #define STRCASECMP stricmp
3592 #else
3593 #define STRCASECMP strcasecmp
3594 #endif
3595
3596 #if 0
3597 /*-----------------------------------------------------------------*/
3598 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3599 /*-----------------------------------------------------------------*/
3600 static bool inExcludeList(char *s)
3601 {
3602   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3603     int i =0;
3604     
3605     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3606     if (options.excludeRegs[i] &&
3607     STRCASECMP(options.excludeRegs[i],"none") == 0)
3608         return FALSE ;
3609
3610     for ( i = 0 ; options.excludeRegs[i]; i++) {
3611         if (options.excludeRegs[i] &&
3612         STRCASECMP(s,options.excludeRegs[i]) == 0)
3613             return TRUE;
3614     }
3615     return FALSE ;
3616 }
3617 #endif
3618
3619 /*-----------------------------------------------------------------*/
3620 /* genFunction - generated code for function entry                 */
3621 /*-----------------------------------------------------------------*/
3622 static void genFunction (iCode *ic)
3623 {
3624   symbol *sym;
3625   sym_link *ftype;
3626   
3627     FENTRY;
3628     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3629
3630     pic16_labelOffset += (max_key+4);
3631     max_key=0;
3632     GpsuedoStkPtr=0;
3633     _G.nRegsSaved = 0;
3634         
3635     ftype = operandType(IC_LEFT(ic));
3636     sym = OP_SYMBOL(IC_LEFT(ic));
3637
3638     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3639       /* create an absolute section at the interrupt vector:
3640        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3641       symbol *asym;
3642       char asymname[128];
3643       pBlock *apb;
3644
3645 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3646
3647         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3648           sprintf(asymname, "ivec_%s", sym->name);
3649         else
3650           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3651   
3652         /* when an interrupt is declared as naked, do not emit the special
3653          * wrapper segment at vector address. The user should take care for
3654          * this instead. -- VR */
3655
3656         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3657           asym = newSymbol(asymname, 0);
3658           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3659           pic16_addpBlock( apb );
3660
3661           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3662           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3663           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3664           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3665           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3666                 
3667           /* mark the end of this tiny function */
3668           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3669         } else {
3670           sprintf(asymname, "%s", sym->rname);
3671         }
3672
3673         {
3674           absSym *abSym;
3675
3676             abSym = Safe_calloc(1, sizeof(absSym));
3677             strcpy(abSym->name, asymname);
3678
3679             switch( FUNC_INTNO(sym->type) ) {
3680               case 0: abSym->address = 0x000000; break;
3681               case 1: abSym->address = 0x000008; break;
3682               case 2: abSym->address = 0x000018; break;
3683               
3684               default:
3685 //                fprintf(stderr, "no interrupt number is given\n");
3686                 abSym->address = -1; break;
3687             }
3688
3689             /* relocate interrupt vectors if needed */
3690             if(abSym->address != -1)
3691               abSym->address += pic16_options.ivt_loc;
3692
3693             addSet(&absSymSet, abSym);
3694         }
3695     }
3696
3697     /* create the function header */
3698     pic16_emitcode(";","-----------------------------------------");
3699     pic16_emitcode(";"," function %s",sym->name);
3700     pic16_emitcode(";","-----------------------------------------");
3701
3702     pic16_emitcode("","%s:",sym->rname);
3703     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3704
3705     {
3706       absSym *ab;
3707
3708         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3709           if(!strcmp(ab->name, sym->rname)) {
3710             pic16_pBlockConvert2Absolute(pb);
3711             break;
3712           }
3713         }
3714     }
3715
3716     if(IFFUNC_ISNAKED(ftype)) {
3717       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3718       return;
3719     }
3720         
3721     /* if critical function then turn interrupts off */
3722     if (IFFUNC_ISCRITICAL(ftype)) {
3723       //pic16_emitcode("clr","ea");
3724     }
3725
3726     currFunc = sym;             /* update the currFunc symbol */
3727     _G.fregsUsed = sym->regsUsed;
3728     _G.sregsAlloc = newBitVect(128);
3729     
3730
3731     /* if this is an interrupt service routine then
3732      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3733     if (IFFUNC_ISISR(sym->type)) {
3734         _G.usefastretfie = 1;   /* use shadow registers by default */
3735         
3736         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3737         if(!FUNC_ISSHADOWREGS(sym->type)) {
3738           /* do not save WREG,STATUS,BSR for high priority interrupts
3739            * because they are stored in the hardware shadow registers already */
3740           _G.usefastretfie = 0;
3741           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3742           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3743           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3744         }
3745
3746         /* these should really be optimized somehow, because not all
3747          * interrupt handlers modify them */
3748         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3749         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3750         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3751         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3752         
3753 //        pic16_pBlockConvert2ISR(pb);
3754     }
3755
3756     /* emit code to setup stack frame if user enabled,
3757      * and function is not main() */
3758     
3759 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3760     if(strcmp(sym->name, "main")) {
3761       if(0 
3762         || !options.ommitFramePtr 
3763 //        || sym->regsUsed
3764         || IFFUNC_ARGS(sym->type)
3765         || FUNC_HASSTACKPARM(sym->etype)
3766         ) {
3767         /* setup the stack frame */
3768         if(STACK_MODEL_LARGE)
3769           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3770         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3771
3772         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3773         if(STACK_MODEL_LARGE)
3774           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3775       }
3776     }
3777
3778     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3779           && sym->stack) {
3780
3781       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3782
3783       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3784       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3785       emitSKPC;
3786       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3787     }
3788           
3789     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3790       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3791         _G.useWreg = 0;
3792       else
3793         _G.useWreg = 1;
3794     } else
3795       _G.useWreg = 0;
3796
3797     /* if callee-save to be used for this function
3798      * then save the registers being used in this function */
3799 //    if (IFFUNC_CALLEESAVES(sym->type))
3800     if(strcmp(sym->name, "main")) {
3801       int i;
3802
3803         /* if any registers used */
3804         if (sym->regsUsed) {
3805                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3806
3807           if(!xinst) {
3808             /* save the registers used */
3809             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3810             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3811               if (bitVectBitValue(sym->regsUsed,i)) {
3812 #if 0
3813                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3814 #endif
3815                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3816                 _G.nRegsSaved++;
3817
3818                 if(!pic16_regWithIdx(i)->wasUsed) {
3819                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3820                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3821                   pic16_regWithIdx(i)->wasUsed = 1;
3822                 }
3823               }
3824             }
3825           } else {
3826             
3827             /* xinst */
3828             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3829             for(i=0;i<sym->regsUsed->size;i++) {
3830               if(bitVectBitValue(sym->regsUsed, i)) {
3831                 _G.nRegsSaved++;
3832               }
3833             }
3834                         
3835 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3836           }
3837
3838           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3839
3840         }
3841     }
3842         
3843     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3844 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3845 }
3846
3847 /*-----------------------------------------------------------------*/
3848 /* genEndFunction - generates epilogue for functions               */
3849 /*-----------------------------------------------------------------*/
3850 static void genEndFunction (iCode *ic)
3851 {
3852   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3853
3854     FENTRY;
3855
3856     if(IFFUNC_ISNAKED(sym->type)) {
3857       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3858       return;
3859     }
3860
3861     _G.stack_lat = 0;
3862
3863     /* add code for ISCRITICAL */
3864     if(IFFUNC_ISCRITICAL(sym->type)) {
3865       /* if critical function, turn on interrupts */
3866       
3867       /* TODO: add code here -- VR */
3868     }
3869     
3870 //    sym->regsUsed = _G.fregsUsed;
3871     
3872     /* now we need to restore the registers */
3873     /* if any registers used */
3874
3875     /* first restore registers that might be used for stack access */
3876     if(_G.sregsAllocSet) {
3877     regs *sr;
3878     
3879       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3880       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3881         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3882       }
3883     }
3884
3885     if (strcmp(sym->name, "main") && sym->regsUsed) {
3886       int i;
3887
3888         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3889         /* restore registers used */
3890         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3891         for ( i = sym->regsUsed->size; i >= 0; i--) {
3892           if (bitVectBitValue(sym->regsUsed,i)) {
3893             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3894             _G.nRegsSaved--;
3895           }
3896         }
3897         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3898     }
3899
3900       
3901
3902     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3903           && sym->stack) {
3904       if (sym->stack == 1) {
3905         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3906         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3907       } else {
3908         // we have to add more than one...
3909         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3910         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3911         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3912         emitSKPNC;
3913         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3914         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3915         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3916       }
3917     }
3918
3919     if(strcmp(sym->name, "main")) {
3920       if(0
3921         || !options.ommitFramePtr
3922 //        || sym->regsUsed
3923         || IFFUNC_ARGS(sym->type)
3924         || FUNC_HASSTACKPARM(sym->etype)
3925         ) {
3926         /* restore stack frame */
3927         if(STACK_MODEL_LARGE)
3928           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3929         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3930       }
3931     }
3932
3933     _G.useWreg = 0;
3934
3935     if (IFFUNC_ISISR(sym->type)) {
3936       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3937       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3938       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3939       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3940
3941       if(!FUNC_ISSHADOWREGS(sym->type)) {
3942         /* do not restore interrupt vector for WREG,STATUS,BSR
3943          * for high priority interrupt, see genFunction */
3944         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3945         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3946         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3947       }
3948 //      _G.interruptvector = 0;         /* sanity check */
3949
3950
3951       /* if debug then send end of function */
3952 /*      if (options.debug && currFunc)  */
3953       if (currFunc) {
3954         debugFile->writeEndFunction (currFunc, ic, 1);
3955       }
3956         
3957       if(_G.usefastretfie)
3958         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3959       else
3960         pic16_emitpcodeNULLop(POC_RETFIE);
3961
3962       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3963       
3964       _G.usefastretfie = 0;
3965       return;
3966     }
3967
3968     if (IFFUNC_ISCRITICAL(sym->type)) {
3969       pic16_emitcode("setb","ea");
3970     }
3971
3972     /* if debug then send end of function */
3973     if (currFunc) {
3974       debugFile->writeEndFunction (currFunc, ic, 1);
3975     }
3976
3977     /* insert code to restore stack frame, if user enabled it
3978      * and function is not main() */
3979          
3980
3981     pic16_emitpcodeNULLop(POC_RETURN);
3982
3983     /* Mark the end of a function */
3984     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3985 }
3986
3987
3988 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3989 {
3990   unsigned long lit=1;
3991   operand *op;
3992
3993     op = IC_LEFT(ic);
3994   
3995     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3996     if(AOP_TYPE(op) == AOP_LIT) {
3997       if(!IS_FLOAT(operandType( op ))) {
3998         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3999       } else {
4000         union {
4001           unsigned long lit_int;
4002           float lit_float;
4003         } info;
4004         
4005         /* take care if literal is a float */
4006         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4007         lit = info.lit_int;
4008       }
4009     }
4010
4011     if(is_LitOp(op)) {
4012       pic16_movLit2f(dest, lit);
4013     } else {
4014       if(dest->type == PO_WREG && (offset == 0)) {
4015         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4016       return;
4017     }
4018     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4019   }
4020 }
4021
4022 /*-----------------------------------------------------------------*/
4023 /* genRet - generate code for return statement                     */
4024 /*-----------------------------------------------------------------*/
4025 static void genRet (iCode *ic)
4026 {
4027   int size;
4028   operand *left;
4029
4030     FENTRY;
4031         /* if we have no return value then
4032          * just generate the "ret" */
4033         
4034         if (!IC_LEFT(ic)) 
4035                 goto jumpret;       
4036     
4037         /* we have something to return then
4038          * move the return value into place */
4039         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4040         size = AOP_SIZE(IC_LEFT(ic));
4041
4042         if(size <= 4) {
4043           if(size>3)
4044             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4045           
4046           if(size>2)
4047             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4048
4049           if(size>1)
4050             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4051           
4052           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4053
4054         } else {
4055                 /* >32-bits, setup stack and FSR0 */
4056                 while (size--) {
4057 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4058 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4059
4060                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4061
4062 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4063                         GpsuedoStkPtr++;
4064                 }
4065                         
4066                 /* setup FSR0 */
4067                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4068                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4069
4070                 if(STACK_MODEL_LARGE) {
4071                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4072                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4073                 } else {
4074                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4075                 }
4076         }
4077                                 
4078 #if 0
4079         /* old code, left here for reference -- VR */    
4080         while (size--) {
4081           char *l ;
4082
4083                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4084                         /* #NOCHANGE */
4085                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4086                         pic16_emitpcomment("push %s",l);
4087                         pushed++;
4088                 } else {
4089                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4090                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4091                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4092                         
4093                         if (strcmp(fReturn[offset],l)) {
4094                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4095                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4096                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4097                                 } else {
4098                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4099                                 }
4100                                 
4101                                 if(size) {
4102                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4103                                 }
4104                                 offset++;
4105                         }
4106                 }
4107         }    
4108
4109         if (pushed) {
4110                 while(pushed) {
4111                         pushed--;
4112                         if (strcmp(fReturn[pushed],"a"))
4113                                 pic16_emitcode("pop",fReturn[pushed]);
4114                         else
4115                                 pic16_emitcode("pop","acc");
4116                 }
4117         }
4118 #endif
4119
4120
4121         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4122     
4123 jumpret:
4124         /* generate a jump to the return label
4125          * if the next is not the return statement */
4126         if (!(ic->next && ic->next->op == LABEL
4127                 && IC_LABEL(ic->next) == returnLabel)) {
4128         
4129                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4130                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4131         }
4132 }
4133
4134 /*-----------------------------------------------------------------*/
4135 /* genLabel - generates a label                                    */
4136 /*-----------------------------------------------------------------*/
4137 static void genLabel (iCode *ic)
4138 {
4139   FENTRY;
4140
4141   /* special case never generate */
4142   if (IC_LABEL(ic) == entryLabel)
4143     return ;
4144
4145   pic16_emitpLabel(IC_LABEL(ic)->key);
4146 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4147 }
4148
4149 /*-----------------------------------------------------------------*/
4150 /* genGoto - generates a goto                                      */
4151 /*-----------------------------------------------------------------*/
4152 //tsd
4153 static void genGoto (iCode *ic)
4154 {
4155   FENTRY;
4156   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4157 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4158 }
4159
4160
4161 /*-----------------------------------------------------------------*/
4162 /* genMultbits :- multiplication of bits                           */
4163 /*-----------------------------------------------------------------*/
4164 static void genMultbits (operand *left, 
4165                          operand *right, 
4166                          operand *result)
4167 {
4168   FENTRY;
4169
4170   if(!pic16_sameRegs(AOP(result),AOP(right)))
4171     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4172
4173   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4174   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4175   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4176
4177 }
4178
4179
4180 /*-----------------------------------------------------------------*/
4181 /* genMultOneByte : 8 bit multiplication & division                */
4182 /*-----------------------------------------------------------------*/
4183 static void genMultOneByte (operand *left,
4184                             operand *right,
4185                             operand *result)
4186 {
4187
4188   FENTRY;
4189   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4190   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4191
4192   /* (if two literals, the value is computed before) */
4193   /* if one literal, literal on the right */
4194   if (AOP_TYPE(left) == AOP_LIT){
4195     operand *t = right;
4196     right = left;
4197     left = t;
4198   }
4199
4200         /* size is already checked in genMult == 1 */
4201 //      size = AOP_SIZE(result);
4202
4203         if (AOP_TYPE(right) == AOP_LIT){
4204                 pic16_emitpcomment("multiply lit val:%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         } else {
4209                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4210                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4211                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4212                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4213         }
4214         
4215         pic16_genMult8X8_8 (left, right,result);
4216 }
4217
4218 /*-----------------------------------------------------------------*/
4219 /* genMultOneWord : 16 bit multiplication                          */
4220 /*-----------------------------------------------------------------*/
4221 static void genMultOneWord (operand *left,
4222                             operand *right,
4223                             operand *result)
4224 {
4225   FENTRY;
4226   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4227   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4228
4229   /* (if two literals, the value is computed before)
4230    * if one literal, literal on the right */
4231   if (AOP_TYPE(left) == AOP_LIT){
4232     operand *t = right;
4233     right = left;
4234     left = t;
4235   }
4236
4237   /* size is checked already == 2 */
4238 //  size = AOP_SIZE(result);
4239
4240   if (AOP_TYPE(right) == AOP_LIT) {
4241     pic16_emitpcomment("multiply lit val:%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   } else {
4246     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4247       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4248       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4249       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4250   }
4251         
4252   pic16_genMult16X16_16(left, right,result);
4253 }
4254
4255 /*-----------------------------------------------------------------*/
4256 /* genMultOneLong : 32 bit multiplication                          */
4257 /*-----------------------------------------------------------------*/
4258 static void genMultOneLong (operand *left,
4259                             operand *right,
4260                             operand *result)
4261 {
4262   FENTRY;
4263   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4264   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4265
4266   /* (if two literals, the value is computed before)
4267    * if one literal, literal on the right */
4268   if (AOP_TYPE(left) == AOP_LIT){
4269     operand *t = right;
4270     right = left;
4271     left = t;
4272   }
4273
4274   /* size is checked already == 4 */
4275 //  size = AOP_SIZE(result);
4276
4277   if (AOP_TYPE(right) == AOP_LIT) {
4278     pic16_emitpcomment("multiply lit val:%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   } else {
4283     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4284         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4285         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4286         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4287   }
4288         
4289   pic16_genMult32X32_32(left, right,result);
4290 }
4291
4292
4293
4294 /*-----------------------------------------------------------------*/
4295 /* genMult - generates code for multiplication                     */
4296 /*-----------------------------------------------------------------*/
4297 static void genMult (iCode *ic)
4298 {
4299   operand *left = IC_LEFT(ic);
4300   operand *right = IC_RIGHT(ic);
4301   operand *result= IC_RESULT(ic);   
4302
4303     FENTRY;
4304         /* assign the amsops */
4305         pic16_aopOp (left,ic,FALSE);
4306         pic16_aopOp (right,ic,FALSE);
4307         pic16_aopOp (result,ic,TRUE);
4308
4309         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4310
4311         /* special cases first *
4312         * both are bits */
4313         if (AOP_TYPE(left) == AOP_CRY
4314                 && AOP_TYPE(right)== AOP_CRY) {
4315                 genMultbits(left,right,result);
4316           goto release ;
4317         }
4318
4319         /* if both are of size == 1 */
4320         if(AOP_SIZE(left) == 1
4321                 && AOP_SIZE(right) == 1) {
4322                 genMultOneByte(left,right,result);
4323           goto release ;
4324         }
4325
4326         /* if both are of size == 2 */
4327         if(AOP_SIZE(left) == 2
4328                 && AOP_SIZE(right) == 2) {
4329                 genMultOneWord(left, right, result);
4330           goto release;
4331         }
4332         
4333         /* if both are of size == 4 */
4334         if(AOP_SIZE(left) == 4
4335                 && AOP_SIZE(right) == 4) {
4336                 genMultOneLong(left, right, result);
4337           goto release;
4338         }
4339         
4340         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4341
4342
4343         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4344         /* should have been converted to function call */
4345         assert(0) ;
4346
4347 release :
4348         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4349         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4350         pic16_freeAsmop(result,NULL,ic,TRUE); 
4351 }
4352
4353 /*-----------------------------------------------------------------*/
4354 /* genDivbits :- division of bits                                  */
4355 /*-----------------------------------------------------------------*/
4356 static void genDivbits (operand *left, 
4357                         operand *right, 
4358                         operand *result)
4359 {
4360   char *l;
4361
4362     FENTRY;
4363     /* the result must be bit */    
4364     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4365     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4366
4367     MOVA(l);    
4368
4369     pic16_emitcode("div","ab");
4370     pic16_emitcode("rrc","a");
4371     pic16_aopPut(AOP(result),"c",0);
4372 }
4373
4374 /*-----------------------------------------------------------------*/
4375 /* genDivOneByte : 8 bit division                                  */
4376 /*-----------------------------------------------------------------*/
4377 static void genDivOneByte (operand *left,
4378                            operand *right,
4379                            operand *result)
4380 {
4381   sym_link *opetype = operandType(result);
4382   char *l ;
4383   symbol *lbl ;
4384   int size,offset;
4385
4386         /* result = divident / divisor
4387          * - divident may be a register or a literal,
4388          * - divisor may be a register or a literal,
4389          * so there are 3 cases (literal / literal is optimized
4390          * by the front-end) to handle.
4391          * In addition we must handle signed and unsigned, which
4392          * result in 6 final different cases -- VR */
4393
4394     FENTRY;
4395     
4396     size = AOP_SIZE(result) - 1;
4397     offset = 1;
4398     /* signed or unsigned */
4399     if (SPEC_USIGN(opetype)) {
4400       pCodeOp *pct1,    /* count */
4401                 *pct2,  /* reste */
4402                 *pct3;  /* temp */
4403       symbol *label1, *label2, *label3;;
4404
4405
4406         /* unsigned is easy */
4407
4408         pct1 = pic16_popGetTempReg(1);
4409         pct2 = pic16_popGetTempReg(1);
4410         pct3 = pic16_popGetTempReg(1);
4411         
4412         label1 = newiTempLabel(NULL);
4413         label2 = newiTempLabel(NULL);
4414         label3 = newiTempLabel(NULL);
4415
4416         /* the following algorithm is extracted from divuint.c */
4417
4418         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4419         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4420         
4421         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4422
4423         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4424         
4425         pic16_emitpLabel(label1->key);
4426         
4427         emitCLRC;
4428         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4429
4430
4431         emitCLRC;
4432         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4433         
4434
4435         emitSKPNC;
4436         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4437         
4438         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4439         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4440         
4441         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4442         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4443         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4444         
4445         pic16_emitpLabel( label3->key );
4446         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4447         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4448         
4449         
4450
4451         pic16_emitpLabel(label2->key);
4452         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4453         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4454         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4455         
4456         /* result is in wreg */
4457         if(AOP_TYPE(result) != AOP_ACC)
4458                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4459
4460         pic16_popReleaseTempReg( pct3, 1);
4461         pic16_popReleaseTempReg( pct2, 1);
4462         pic16_popReleaseTempReg( pct1, 1);
4463
4464         return ;
4465     }
4466
4467     /* signed is a little bit more difficult */
4468
4469     /* save the signs of the operands */
4470     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4471     MOVA(l);    
4472     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4473     pic16_emitcode("push","acc"); /* save it on the stack */
4474
4475     /* now sign adjust for both left & right */
4476     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4477     MOVA(l);       
4478     lbl = newiTempLabel(NULL);
4479     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4480     pic16_emitcode("cpl","a");   
4481     pic16_emitcode("inc","a");
4482     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4483     pic16_emitcode("mov","b,a");
4484
4485     /* sign adjust left side */
4486     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4487     MOVA(l);
4488
4489     lbl = newiTempLabel(NULL);
4490     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4491     pic16_emitcode("cpl","a");
4492     pic16_emitcode("inc","a");
4493     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4494
4495     /* now the division */
4496     pic16_emitcode("div","ab");
4497     /* we are interested in the lower order
4498     only */
4499     pic16_emitcode("mov","b,a");
4500     lbl = newiTempLabel(NULL);
4501     pic16_emitcode("pop","acc");   
4502     /* if there was an over flow we don't 
4503     adjust the sign of the result */
4504     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4505     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4506     CLRC;
4507     pic16_emitcode("clr","a");
4508     pic16_emitcode("subb","a,b");
4509     pic16_emitcode("mov","b,a");
4510     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4511
4512     /* now we are done */
4513     pic16_aopPut(AOP(result),"b",0);
4514     if(size > 0){
4515         pic16_emitcode("mov","c,b.7");
4516         pic16_emitcode("subb","a,acc");   
4517     }
4518     while (size--)
4519         pic16_aopPut(AOP(result),"a",offset++);
4520
4521 }
4522
4523 /*-----------------------------------------------------------------*/
4524 /* genDiv - generates code for division                            */
4525 /*-----------------------------------------------------------------*/
4526 static void genDiv (iCode *ic)
4527 {
4528     operand *left = IC_LEFT(ic);
4529     operand *right = IC_RIGHT(ic);
4530     operand *result= IC_RESULT(ic);   
4531
4532
4533         /* Division is a very lengthy algorithm, so it is better
4534          * to call support routines than inlining algorithm.
4535          * Division functions written here just in case someone
4536          * wants to inline and not use the support libraries -- VR */
4537
4538     FENTRY;
4539     
4540     /* assign the amsops */
4541     pic16_aopOp (left,ic,FALSE);
4542     pic16_aopOp (right,ic,FALSE);
4543     pic16_aopOp (result,ic,TRUE);
4544
4545     /* special cases first */
4546     /* both are bits */
4547     if (AOP_TYPE(left) == AOP_CRY &&
4548         AOP_TYPE(right)== AOP_CRY) {
4549         genDivbits(left,right,result);
4550         goto release ;
4551     }
4552
4553     /* if both are of size == 1 */
4554     if (AOP_SIZE(left) == 1 &&
4555         AOP_SIZE(right) == 1 ) {
4556         genDivOneByte(left,right,result);
4557         goto release ;
4558     }
4559
4560     /* should have been converted to function call */
4561     assert(0);
4562 release :
4563     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4564     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4565     pic16_freeAsmop(result,NULL,ic,TRUE); 
4566 }
4567
4568 /*-----------------------------------------------------------------*/
4569 /* genModbits :- modulus of bits                                   */
4570 /*-----------------------------------------------------------------*/
4571 static void genModbits (operand *left, 
4572                         operand *right, 
4573                         operand *result)
4574 {
4575   char *l;
4576
4577     FENTRY;  
4578     
4579     werror(W_POSSBUG2, __FILE__, __LINE__);
4580     /* the result must be bit */    
4581     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4582     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4583
4584     MOVA(l);       
4585
4586     pic16_emitcode("div","ab");
4587     pic16_emitcode("mov","a,b");
4588     pic16_emitcode("rrc","a");
4589     pic16_aopPut(AOP(result),"c",0);
4590 }
4591
4592 /*-----------------------------------------------------------------*/
4593 /* genModOneByte : 8 bit modulus                                   */
4594 /*-----------------------------------------------------------------*/
4595 static void genModOneByte (operand *left,
4596                            operand *right,
4597                            operand *result)
4598 {
4599   sym_link *opetype = operandType(result);
4600   char *l ;
4601   symbol *lbl ;
4602
4603     FENTRY;
4604     werror(W_POSSBUG2, __FILE__, __LINE__);
4605
4606     /* signed or unsigned */
4607     if (SPEC_USIGN(opetype)) {
4608         /* unsigned is easy */
4609         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4610         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4611         MOVA(l);    
4612         pic16_emitcode("div","ab");
4613         pic16_aopPut(AOP(result),"b",0);
4614         return ;
4615     }
4616
4617     /* signed is a little bit more difficult */
4618
4619     /* save the signs of the operands */
4620     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4621     MOVA(l);
4622
4623     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4624     pic16_emitcode("push","acc"); /* save it on the stack */
4625
4626     /* now sign adjust for both left & right */
4627     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4628     MOVA(l);
4629
4630     lbl = newiTempLabel(NULL);
4631     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4632     pic16_emitcode("cpl","a");   
4633     pic16_emitcode("inc","a");
4634     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4635     pic16_emitcode("mov","b,a"); 
4636
4637     /* sign adjust left side */
4638     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4639     MOVA(l);
4640
4641     lbl = newiTempLabel(NULL);
4642     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4643     pic16_emitcode("cpl","a");   
4644     pic16_emitcode("inc","a");
4645     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4646
4647     /* now the multiplication */
4648     pic16_emitcode("div","ab");
4649     /* we are interested in the lower order
4650     only */
4651     lbl = newiTempLabel(NULL);
4652     pic16_emitcode("pop","acc");   
4653     /* if there was an over flow we don't 
4654     adjust the sign of the result */
4655     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4656     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4657     CLRC ;
4658     pic16_emitcode("clr","a");
4659     pic16_emitcode("subb","a,b");
4660     pic16_emitcode("mov","b,a");
4661     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4662
4663     /* now we are done */
4664     pic16_aopPut(AOP(result),"b",0);
4665
4666 }
4667
4668 /*-----------------------------------------------------------------*/
4669 /* genMod - generates code for division                            */
4670 /*-----------------------------------------------------------------*/
4671 static void genMod (iCode *ic)
4672 {
4673   operand *left = IC_LEFT(ic);
4674   operand *right = IC_RIGHT(ic);
4675   operand *result= IC_RESULT(ic);  
4676
4677     FENTRY;
4678     
4679     /* assign the amsops */
4680     pic16_aopOp (left,ic,FALSE);
4681     pic16_aopOp (right,ic,FALSE);
4682     pic16_aopOp (result,ic,TRUE);
4683
4684     /* special cases first */
4685     /* both are bits */
4686     if (AOP_TYPE(left) == AOP_CRY &&
4687         AOP_TYPE(right)== AOP_CRY) {
4688         genModbits(left,right,result);
4689         goto release ;
4690     }
4691
4692     /* if both are of size == 1 */
4693     if (AOP_SIZE(left) == 1 &&
4694         AOP_SIZE(right) == 1 ) {
4695         genModOneByte(left,right,result);
4696         goto release ;
4697     }
4698
4699     /* should have been converted to function call */
4700     assert(0);
4701
4702 release :
4703     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4704     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4705     pic16_freeAsmop(result,NULL,ic,TRUE); 
4706 }
4707
4708 /*-----------------------------------------------------------------*/
4709 /* genIfxJump :- will create a jump depending on the ifx           */
4710 /*-----------------------------------------------------------------*/
4711 /*
4712   note: May need to add parameter to indicate when a variable is in bit space.
4713 */
4714 static void genIfxJump (iCode *ic, char *jval)
4715 {
4716   FENTRY;
4717   
4718     /* if true label then we jump if condition
4719     supplied is true */
4720     if ( IC_TRUE(ic) ) {
4721
4722         if(strcmp(jval,"a") == 0)
4723           emitSKPZ;
4724         else if (strcmp(jval,"c") == 0)
4725           emitSKPNC;
4726         else {
4727           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4728           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4729         }
4730
4731         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4732         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4733
4734     }
4735     else {
4736         /* false label is present */
4737         if(strcmp(jval,"a") == 0)
4738           emitSKPNZ;
4739         else if (strcmp(jval,"c") == 0)
4740           emitSKPC;
4741         else {
4742           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4743           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4744         }
4745
4746         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4747         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4748
4749     }
4750
4751
4752     /* mark the icode as generated */
4753     ic->generated = 1;
4754 }
4755
4756 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4757 {
4758   FENTRY;
4759   
4760     /* if true label then we jump if condition
4761     supplied is true */
4762     if ( IC_TRUE(ic) ) {
4763       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4764       pic16_emitpcode(POC_BTFSC, jop);
4765
4766       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4767       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4768
4769     } else {
4770       /* false label is present */
4771       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4772       pic16_emitpcode(POC_BTFSS, jop);
4773           
4774       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4775       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4776     }
4777
4778
4779     /* mark the icode as generated */
4780     ic->generated = 1;
4781 }
4782
4783 #if 0
4784 // not needed ATM
4785
4786 /*-----------------------------------------------------------------*/
4787 /* genSkip                                                         */
4788 /*-----------------------------------------------------------------*/
4789 static void genSkip(iCode *ifx,int status_bit)
4790 {
4791   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4792   if(!ifx)
4793     return;
4794
4795   if ( IC_TRUE(ifx) ) {
4796     switch(status_bit) {
4797     case 'z':
4798       emitSKPNZ;
4799       break;
4800
4801     case 'c':
4802       emitSKPNC;
4803       break;
4804
4805     case 'd':
4806       emitSKPDC;
4807       break;
4808
4809     }
4810
4811     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4812     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4813
4814   } else {
4815
4816     switch(status_bit) {
4817
4818     case 'z':
4819       emitSKPZ;
4820       break;
4821
4822     case 'c':
4823       emitSKPC;
4824       break;
4825
4826     case 'd':
4827       emitSKPDC;
4828       break;
4829     }
4830     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4831     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4832
4833   }
4834
4835 }
4836 #endif
4837
4838 /*-----------------------------------------------------------------*/
4839 /* genSkipc                                                        */
4840 /*-----------------------------------------------------------------*/
4841 static void genSkipc(resolvedIfx *rifx)
4842 {
4843   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4844   
4845   if(!rifx)
4846     return;
4847
4848   if(rifx->condition)
4849     emitSKPNC;
4850   else
4851     emitSKPC;
4852
4853   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4854   rifx->generated = 1;
4855 }
4856
4857 #if !(USE_SIMPLE_GENCMP)
4858 /*-----------------------------------------------------------------*/
4859 /* genSkipz2                                                       */
4860 /*-----------------------------------------------------------------*/
4861 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4862 {
4863   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4864   
4865   if(!rifx)
4866     return;
4867
4868   if( (rifx->condition ^ invert_condition) & 1)
4869     emitSKPZ;
4870   else
4871     emitSKPNZ;
4872
4873   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4874   rifx->generated = 1;
4875 }
4876 #endif
4877
4878 #if 0
4879 /*-----------------------------------------------------------------*/
4880 /* genSkipz                                                        */
4881 /*-----------------------------------------------------------------*/
4882 static void genSkipz(iCode *ifx, int condition)
4883 {
4884   if(!ifx)
4885     return;
4886
4887   if(condition)
4888     emitSKPNZ;
4889   else
4890     emitSKPZ;
4891
4892   if ( IC_TRUE(ifx) )
4893     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4894   else
4895     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4896
4897   if ( IC_TRUE(ifx) )
4898     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4899   else
4900     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4901
4902 }
4903 #endif
4904
4905 #if !(USE_SIMPLE_GENCMP)
4906 /*-----------------------------------------------------------------*/
4907 /* genSkipCond                                                     */
4908 /*-----------------------------------------------------------------*/
4909 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4910 {
4911   if(!rifx)
4912     return;
4913
4914   if(rifx->condition)
4915     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4916   else
4917     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4918
4919
4920   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4921   rifx->generated = 1;
4922 }
4923 #endif
4924
4925 #if 0
4926 /*-----------------------------------------------------------------*/
4927 /* genChkZeroes :- greater or less than comparison                 */
4928 /*     For each byte in a literal that is zero, inclusive or the   */
4929 /*     the corresponding byte in the operand with W                */
4930 /*     returns true if any of the bytes are zero                   */
4931 /*-----------------------------------------------------------------*/
4932 static int genChkZeroes(operand *op, int lit,  int size)
4933 {
4934
4935   int i;
4936   int flag =1;
4937
4938   while(size--) {
4939     i = (lit >> (size*8)) & 0xff;
4940
4941     if(i==0) {
4942       if(flag) 
4943         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4944       else
4945         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4946       flag = 0;
4947     }
4948   }
4949
4950   return (flag==0);
4951 }
4952 #endif
4953
4954
4955 /*-----------------------------------------------------------------*/
4956 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4957 /*                  aop (if it's NOT a literal) or from lit (if    */
4958 /*                  aop is a literal)                              */
4959 /*-----------------------------------------------------------------*/
4960 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4961   if (aop->type == AOP_LIT) {
4962     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4963   } else {
4964     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4965   }
4966 }
4967
4968 /*-----------------------------------------------------------------*/
4969 /* genCmp :- greater or less than comparison                       */
4970 /*-----------------------------------------------------------------*/
4971
4972 #if USE_SIMPLE_GENCMP           /* { */
4973
4974 /* genCmp performs a left < right comparison, stores
4975  * the outcome in result (if != NULL) and generates
4976  * control flow code for the ifx (if != NULL).
4977  *
4978  * This version leaves in sequences like
4979  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4980  * which should be optmized by the peephole
4981  * optimizer - RN 2005-01-01 */
4982 static void genCmp (operand *left,operand *right,
4983                     operand *result, iCode *ifx, int sign)
4984 {
4985   resolvedIfx rIfx;
4986   int size;
4987   int offs;
4988   symbol *templbl;
4989   operand *dummy;
4990   unsigned long lit;
4991   unsigned long mask;
4992   int performedLt;
4993
4994   FENTRY;
4995   
4996   assert (left && right);
4997   assert (AOP_SIZE(left) == AOP_SIZE(right));
4998
4999   size = AOP_SIZE(right) - 1;
5000   mask = (0x100UL << (size*8)) - 1;
5001   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5002   performedLt = 1;
5003   templbl = NULL;
5004   lit = 0;
5005   
5006   resolveIfx (&rIfx, ifx);
5007
5008   /* handle for special cases */
5009   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5010       return;
5011
5012   /**********************************************************************
5013    * handle bits - bit compares are promoted to int compares seemingly! *
5014    **********************************************************************/
5015 #if 0
5016   // THIS IS COMPLETELY UNTESTED!
5017   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5018     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5019     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5020     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5021
5022     emitSETC;
5023     // 1 < {0,1} is false --> clear C by skipping the next instruction
5024     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5025     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5026     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5027     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5028     emitCLRC; // only skipped for left=0 && right=1
5029
5030     goto correct_result_in_carry;
5031   } // if
5032 #endif
5033
5034   /*************************************************
5035    * make sure that left is register (or the like) *
5036    *************************************************/
5037   if (!isAOP_REGlike(left)) {
5038     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5039     assert (isAOP_LIT(left));
5040     assert (isAOP_REGlike(right));
5041     // swap left and right
5042     // left < right <==> right > left <==> (right >= left + 1)
5043     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5044
5045     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5046       // MAXVALUE < right? always false
5047       if (performedLt) emitCLRC; else emitSETC;
5048       goto correct_result_in_carry;
5049     } // if
5050
5051     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5052     // that's why we handled it above.
5053     lit++;
5054
5055     dummy = left;
5056     left = right;
5057     right = dummy;
5058
5059     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5060   } else if (isAOP_LIT(right)) {
5061     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5062   } // if
5063
5064   assert (isAOP_REGlike(left)); // left must be register or the like
5065   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5066
5067   /*************************************************
5068    * special cases go here                         *
5069    *************************************************/
5070
5071   if (isAOP_LIT(right)) {
5072     if (!sign) {
5073       // unsigned comparison to a literal
5074       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5075       if (lit == 0) {
5076         // unsigned left < 0? always false
5077         if (performedLt) emitCLRC; else emitSETC;
5078         goto correct_result_in_carry;
5079       }
5080     } else {
5081       // signed comparison to a literal
5082       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5083       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5084         // signed left < 0x80000000? always false
5085         if (performedLt) emitCLRC; else emitSETC;
5086         goto correct_result_in_carry;
5087       } else if (lit == 0) {
5088         // compare left < 0; set CARRY if SIGNBIT(left) is set
5089         if (performedLt) emitSETC; else emitCLRC;
5090         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5091         if (performedLt) emitCLRC; else emitSETC;
5092         goto correct_result_in_carry;
5093       }
5094     } // if (!sign)
5095   } // right is literal
5096
5097   /*************************************************
5098    * perform a general case comparison             *
5099    * make sure we get CARRY==1 <==> left >= right  *
5100    *************************************************/
5101   // compare most significant bytes
5102   //DEBUGpc ("comparing bytes at offset %d", size);
5103   if (!sign) {
5104     // unsigned comparison
5105     mov2w_regOrLit (AOP(right), lit, size);
5106     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5107   } else {
5108     // signed comparison
5109     // (add 2^n to both operands then perform an unsigned comparison)
5110     if (isAOP_LIT(right)) {
5111       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5112       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5113
5114       if (litbyte == 0x80) {
5115         // left >= 0x80 -- always true, but more bytes to come
5116         pic16_mov2w (AOP(left), size);
5117         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5118         emitSETC;
5119       } else {
5120         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5121         pic16_mov2w (AOP(left), size);
5122         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5123         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5124       } // if
5125     } else {
5126       /* using PRODL as a temporary register here */
5127       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5128       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5129       pic16_mov2w (AOP(left), size);
5130       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5131       pic16_emitpcode (POC_MOVWF, pctemp);
5132       pic16_mov2w (AOP(right), size);
5133       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5134       pic16_emitpcode (POC_SUBFW, pctemp);
5135       //pic16_popReleaseTempReg(pctemp, 1);
5136     }
5137   } // if (!sign)
5138
5139   // compare remaining bytes (treat as unsigned case from above)
5140   templbl = newiTempLabel ( NULL );
5141   offs = size;
5142   while (offs--) {
5143     //DEBUGpc ("comparing bytes at offset %d", offs);
5144     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5145     mov2w_regOrLit (AOP(right), lit, offs);
5146     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5147   } // while (offs)
5148   pic16_emitpLabel (templbl->key);
5149   goto result_in_carry;
5150
5151 result_in_carry:
5152   
5153   /****************************************************
5154    * now CARRY contains the result of the comparison: *
5155    * SUBWF sets CARRY iff                             *
5156    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5157    * (F=left, W=right)                                *
5158    ****************************************************/
5159
5160   if (performedLt) {
5161     if (result && AOP_TYPE(result) != AOP_CRY) {
5162       // value will be stored
5163       emitTOGC;
5164     } else {
5165       // value wil only be used in the following genSkipc()
5166       rIfx.condition ^= 1;
5167     }
5168   } // if
5169
5170 correct_result_in_carry:
5171
5172   // assign result to variable (if neccessary)
5173   if (result && AOP_TYPE(result) != AOP_CRY) {
5174     //DEBUGpc ("assign result");
5175     size = AOP_SIZE(result);
5176     while (size--) {
5177       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5178     } // while
5179     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5180   } // if (result)
5181
5182   // perform conditional jump
5183   if (ifx) {
5184     //DEBUGpc ("generate control flow");
5185     genSkipc (&rIfx);
5186     ifx->generated = 1;
5187   } // if
5188 }
5189
5190 #elif 1         /* } */
5191                 /* { */
5192       /* original code */
5193 static void genCmp (operand *left,operand *right,
5194                     operand *result, iCode *ifx, int sign)
5195 {
5196   int size; //, offset = 0 ;
5197   unsigned long lit = 0L,i = 0;
5198   resolvedIfx rFalseIfx;
5199   //  resolvedIfx rTrueIfx;
5200   symbol *truelbl;
5201   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5202 /*
5203   if(ifx) {
5204     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5205     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5206   }
5207 */
5208
5209   FENTRY;
5210   
5211   resolveIfx(&rFalseIfx,ifx);
5212   truelbl  = newiTempLabel(NULL);
5213   size = max(AOP_SIZE(left),AOP_SIZE(right));
5214
5215   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5216
5217 #define _swapp
5218
5219   /* if literal is on the right then swap with left */
5220   if ((AOP_TYPE(right) == AOP_LIT)) {
5221     operand *tmp = right ;
5222     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5223     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5224 #ifdef _swapp
5225
5226     lit = (lit - 1) & mask;
5227     right = left;
5228     left = tmp;
5229     rFalseIfx.condition ^= 1;
5230 #endif
5231
5232   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5233     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5234   }
5235
5236
5237   //if(IC_TRUE(ifx) == NULL)
5238   /* if left & right are bit variables */
5239   if (AOP_TYPE(left) == AOP_CRY &&
5240       AOP_TYPE(right) == AOP_CRY ) {
5241     assert (0 && "bit variables used in genCmp");
5242     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5243     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5244   } else {
5245     /* subtract right from left if at the
5246        end the carry flag is set then we know that
5247        left is greater than right */
5248
5249     symbol *lbl  = newiTempLabel(NULL);
5250
5251 #if 0
5252         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5253                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5254 #endif
5255
5256 #ifndef _swapp
5257     if(AOP_TYPE(right) == AOP_LIT) {
5258
5259       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5260
5261       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5262
5263       /* special cases */
5264
5265       if(lit == 0) {
5266
5267         if(sign != 0) 
5268           genSkipCond(&rFalseIfx,left,size-1,7);
5269         else 
5270           /* no need to compare to 0...*/
5271           /* NOTE: this is a de-generate compare that most certainly 
5272            *       creates some dead code. */
5273           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5274
5275         if(ifx) ifx->generated = 1;
5276         return;
5277
5278       }
5279       size--;
5280
5281       if(size == 0) {
5282         //i = (lit >> (size*8)) & 0xff;
5283         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5284         
5285         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5286
5287         i = ((0-lit) & 0xff);
5288         if(sign) {
5289           if( i == 0x81) { 
5290             /* lit is 0x7f, all signed chars are less than
5291              * this except for 0x7f itself */
5292             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5293             genSkipz2(&rFalseIfx,0);
5294           } else {
5295             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5296             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5297             genSkipc(&rFalseIfx);
5298           }
5299
5300         } else {
5301           if(lit == 1) {
5302             genSkipz2(&rFalseIfx,1);
5303           } else {
5304             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5305             genSkipc(&rFalseIfx);
5306           }
5307         }
5308
5309         if(ifx) ifx->generated = 1;
5310         return;
5311       }
5312
5313       /* chars are out of the way. now do ints and longs */
5314
5315
5316       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5317         
5318       /* special cases */
5319
5320       if(sign) {
5321
5322         if(lit == 0) {
5323           genSkipCond(&rFalseIfx,left,size,7);
5324           if(ifx) ifx->generated = 1;
5325           return;
5326         }
5327
5328         if(lit <0x100) {
5329           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5330
5331           //rFalseIfx.condition ^= 1;
5332           //genSkipCond(&rFalseIfx,left,size,7);
5333           //rFalseIfx.condition ^= 1;
5334
5335           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5336           if(rFalseIfx.condition)
5337             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5338           else
5339             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5340
5341           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5342           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5343           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5344
5345           while(size > 1)
5346             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5347
5348           if(rFalseIfx.condition) {
5349             emitSKPZ;
5350             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5351
5352           } else {
5353             emitSKPNZ;
5354           }
5355
5356           genSkipc(&rFalseIfx);
5357           pic16_emitpLabel(truelbl->key);
5358           if(ifx) ifx->generated = 1;
5359           return;
5360
5361         }
5362
5363         if(size == 1) {
5364
5365           if( (lit & 0xff) == 0) {
5366             /* lower byte is zero */
5367             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5368             i = ((lit >> 8) & 0xff) ^0x80;
5369             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5370             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5371             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5372             genSkipc(&rFalseIfx);
5373
5374
5375             if(ifx) ifx->generated = 1;
5376             return;
5377
5378           }
5379         } else {
5380           /* Special cases for signed longs */
5381           if( (lit & 0xffffff) == 0) {
5382             /* lower byte is zero */
5383             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5384             i = ((lit >> 8*3) & 0xff) ^0x80;
5385             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5386             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5387             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5388             genSkipc(&rFalseIfx);
5389
5390
5391             if(ifx) ifx->generated = 1;
5392             return;
5393
5394           }
5395
5396         }
5397
5398
5399         if(lit & (0x80 << (size*8))) {
5400           /* lit is negative */
5401           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5402
5403           //genSkipCond(&rFalseIfx,left,size,7);
5404
5405           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5406
5407           if(rFalseIfx.condition)
5408             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5409           else
5410             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5411
5412
5413         } else {
5414           /* lit is positive */
5415           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5416           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5417           if(rFalseIfx.condition)
5418             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5419           else
5420             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5421
5422         }
5423
5424         /*
5425           This works, but is only good for ints.
5426           It also requires a "known zero" register.
5427           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5428           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5429           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5430           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5431           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5432           genSkipc(&rFalseIfx);
5433
5434           pic16_emitpLabel(truelbl->key);
5435           if(ifx) ifx->generated = 1;
5436           return;
5437         **/
5438           
5439         /* There are no more special cases, so perform a general compare */
5440   
5441         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5442         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5443
5444         while(size--) {
5445
5446           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5447           emitSKPNZ;
5448           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5449         }
5450         //rFalseIfx.condition ^= 1;
5451         genSkipc(&rFalseIfx);
5452
5453         pic16_emitpLabel(truelbl->key);
5454
5455         if(ifx) ifx->generated = 1;
5456         return;
5457
5458
5459       }
5460
5461
5462       /* sign is out of the way. So now do an unsigned compare */
5463       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5464
5465
5466       /* General case - compare to an unsigned literal on the right.*/
5467
5468       i = (lit >> (size*8)) & 0xff;
5469       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5470       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5471       while(size--) {
5472         i = (lit >> (size*8)) & 0xff;
5473
5474         if(i) {
5475           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5476           emitSKPNZ;
5477           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5478         } else {
5479           /* this byte of the lit is zero, 
5480            *if it's not the last then OR in the variable */
5481           if(size)
5482             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5483         }
5484       }
5485
5486
5487       pic16_emitpLabel(lbl->key);
5488 //      pic16_emitpLabel(truelbl->key);
5489       //if(emitFinalCheck)
5490       genSkipc(&rFalseIfx);
5491       if(sign)
5492         pic16_emitpLabel(truelbl->key);
5493
5494       if(ifx) ifx->generated = 1;
5495       return;
5496
5497
5498     }
5499 #endif  // _swapp
5500
5501     if(AOP_TYPE(left) == AOP_LIT) {
5502       //symbol *lbl = newiTempLabel(NULL);
5503
5504       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5505
5506
5507       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5508
5509       /* Special cases */
5510       if((lit == 0) && (sign == 0)){
5511
5512         size--;
5513         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5514         while(size) 
5515           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5516
5517         genSkipz2(&rFalseIfx,0);
5518         if(ifx) ifx->generated = 1;
5519         return;
5520       }
5521
5522       if(size==1) {
5523         /* Special cases */
5524         lit &= 0xff;
5525         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5526           /* degenerate compare can never be true */
5527           if(rFalseIfx.condition == 0)
5528             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5529
5530           if(ifx) ifx->generated = 1;
5531           return;
5532         }
5533
5534         if(sign) {
5535           /* signed comparisons to a literal byte */
5536
5537           int lp1 = (lit+1) & 0xff;
5538
5539           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5540           switch (lp1) {
5541           case 0:
5542             rFalseIfx.condition ^= 1;
5543             genSkipCond(&rFalseIfx,right,0,7);
5544             break;
5545           case 0x7f:
5546             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5547             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5548             genSkipz2(&rFalseIfx,1);
5549             break;
5550           default:
5551             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5552             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5553             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5554             rFalseIfx.condition ^= 1;
5555             genSkipc(&rFalseIfx);
5556             break;
5557           }
5558         } else {
5559           /* unsigned comparisons to a literal byte */
5560
5561           switch(lit & 0xff ) {
5562           case 0:
5563             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5564             genSkipz2(&rFalseIfx,0);
5565             break;
5566           case 0x7f:
5567             rFalseIfx.condition ^= 1;
5568             genSkipCond(&rFalseIfx,right,0,7);
5569             break;
5570
5571           default:
5572             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5573             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5574             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5575             rFalseIfx.condition ^= 1;
5576             if (AOP_TYPE(result) == AOP_CRY)
5577               genSkipc(&rFalseIfx);
5578             else {
5579               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5580               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5581             }         
5582             break;
5583           }
5584         }
5585
5586         if(ifx) ifx->generated = 1;
5587         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5588                 goto check_carry;
5589         return;
5590
5591       } else {
5592
5593         /* Size is greater than 1 */
5594
5595         if(sign) {
5596           int lp1 = lit+1;
5597
5598           size--;
5599
5600           if(lp1 == 0) {
5601             /* this means lit = 0xffffffff, or -1 */
5602
5603
5604             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5605             rFalseIfx.condition ^= 1;
5606             genSkipCond(&rFalseIfx,right,size,7);
5607             if(ifx) ifx->generated = 1;
5608
5609             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5610               goto check_carry;
5611
5612             return;
5613           }
5614
5615           if(lit == 0) {
5616             int s = size;
5617
5618             if(rFalseIfx.condition) {
5619               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5620               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5621             }
5622
5623             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5624             while(size--)
5625               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5626
5627
5628             emitSKPZ;
5629             if(rFalseIfx.condition) {
5630               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5631               pic16_emitpLabel(truelbl->key);
5632             }else {
5633               rFalseIfx.condition ^= 1;
5634               genSkipCond(&rFalseIfx,right,s,7);
5635             }
5636
5637             if(ifx) ifx->generated = 1;
5638
5639             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5640               goto check_carry;
5641
5642             return;
5643           }
5644
5645           if((size == 1) &&  (0 == (lp1&0xff))) {
5646             /* lower byte of signed word is zero */
5647             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5648             i = ((lp1 >> 8) & 0xff) ^0x80;
5649             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5650             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5651             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5652
5653             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5654               emitTOGC;
5655               if(ifx) ifx->generated = 1;
5656               goto check_carry;
5657             } else {
5658               rFalseIfx.condition ^= 1;
5659               genSkipc(&rFalseIfx);
5660               if(ifx) ifx->generated = 1;
5661             }
5662
5663             return;
5664           }
5665
5666           if(lit & (0x80 << (size*8))) {
5667             /* Lit is less than zero */
5668             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5669             //rFalseIfx.condition ^= 1;
5670             //genSkipCond(&rFalseIfx,left,size,7);
5671             //rFalseIfx.condition ^= 1;
5672             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5673             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5674
5675             if(rFalseIfx.condition)
5676               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5677             else
5678               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5679
5680
5681           } else {
5682             /* Lit is greater than or equal to zero */
5683             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5684             //rFalseIfx.condition ^= 1;
5685             //genSkipCond(&rFalseIfx,right,size,7);
5686             //rFalseIfx.condition ^= 1;
5687
5688             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5689             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5690
5691             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5692             if(rFalseIfx.condition)
5693               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5694             else
5695               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5696
5697           }
5698
5699           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5700           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5701
5702           while(size--) {
5703
5704             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5705             emitSKPNZ;
5706             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5707           }
5708           rFalseIfx.condition ^= 1;
5709           //rFalseIfx.condition = 1;
5710           genSkipc(&rFalseIfx);
5711
5712           pic16_emitpLabel(truelbl->key);
5713
5714           if(ifx) ifx->generated = 1;
5715
5716
5717           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5718             goto check_carry;
5719
5720           return;
5721           // end of if (sign)
5722         } else {
5723
5724           /* compare word or long to an unsigned literal on the right.*/
5725
5726
5727           size--;
5728           if(lit < 0xff) {
5729             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5730             switch (lit) {
5731             case 0:
5732               break; /* handled above */
5733 /*
5734             case 0xff:
5735               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5736               while(size--)
5737                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5738               genSkipz2(&rFalseIfx,0);
5739               break;
5740 */
5741             default:
5742               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5743               while(--size)
5744                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5745
5746               emitSKPZ;
5747               if(rFalseIfx.condition)
5748                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5749               else
5750                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5751
5752
5753               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5754               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5755
5756               rFalseIfx.condition ^= 1;
5757               genSkipc(&rFalseIfx);
5758             }
5759
5760             pic16_emitpLabel(truelbl->key);
5761
5762             if(ifx) ifx->generated = 1;
5763
5764             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5765               goto check_carry;
5766
5767             return;
5768           }
5769
5770
5771           lit++;
5772           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5773           i = (lit >> (size*8)) & 0xff;
5774
5775           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5776           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5777
5778           while(size--) {
5779             i = (lit >> (size*8)) & 0xff;
5780
5781             if(i) {
5782               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5783               emitSKPNZ;
5784               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5785             } else {
5786               /* this byte of the lit is zero, 
5787                * if it's not the last then OR in the variable */
5788               if(size)
5789                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5790             }
5791           }
5792
5793
5794           pic16_emitpLabel(lbl->key);
5795
5796           rFalseIfx.condition ^= 1;
5797
5798           genSkipc(&rFalseIfx);
5799         }
5800
5801         if(sign)
5802           pic16_emitpLabel(truelbl->key);
5803         if(ifx) ifx->generated = 1;
5804
5805             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5806               goto check_carry;
5807
5808         return;
5809       }
5810     }
5811     /* Compare two variables */
5812
5813     DEBUGpic16_emitcode(";sign","%d",sign);
5814
5815     size--;
5816     if(sign) {
5817       /* Sigh. thus sucks... */
5818       if(size) {
5819         pCodeOp *pctemp;
5820         
5821         pctemp = pic16_popGetTempReg(1);
5822         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5823         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5824         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5825         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5826         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5827         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828         pic16_popReleaseTempReg(pctemp, 1);
5829       } else {
5830         /* Signed char comparison */
5831         /* Special thanks to Nikolai Golovchenko for this snippet */
5832         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5833         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5834         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5835         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5836         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5837         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5838
5839         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5840         genSkipc(&rFalseIfx);
5841           
5842         if(ifx) ifx->generated = 1;
5843
5844             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5845               goto check_carry;
5846
5847         return;
5848       }
5849
5850     } else {
5851
5852       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5853       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5854     }
5855
5856
5857     /* The rest of the bytes of a multi-byte compare */
5858     while (size) {
5859
5860       emitSKPZ;
5861       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5862       size--;
5863
5864       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5865       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5866
5867
5868     }
5869
5870     pic16_emitpLabel(lbl->key);
5871
5872     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5873     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5874         (AOP_TYPE(result) == AOP_REG)) {
5875       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5876       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5877     } else {
5878       genSkipc(&rFalseIfx);
5879     }         
5880     //genSkipc(&rFalseIfx);
5881     if(ifx) ifx->generated = 1;
5882
5883
5884             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5885               goto check_carry;
5886
5887     return;
5888
5889   }
5890
5891 check_carry:
5892   if ((AOP_TYPE(result) != AOP_CRY) 
5893         && AOP_SIZE(result)) {
5894     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5895
5896     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5897
5898     pic16_outBitC(result);
5899   } else {
5900     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5901     /* if the result is used in the next
5902        ifx conditional branch then generate
5903        code a little differently */
5904     if (ifx )
5905       genIfxJump (ifx,"c");
5906     else
5907       pic16_outBitC(result);
5908     /* leave the result in acc */
5909   }
5910
5911 }
5912
5913 #elif 0 /* VR version of genCmp() */    /* } else { */
5914
5915 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5916 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5917         operand *result, int offset, int invert_op)
5918 {
5919   /* add code here */
5920   
5921   /* check condition, > or < ?? */
5922   if(rIfx->condition != 0)invert_op ^= 1;
5923   
5924   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5925
5926   if(!ifx)invert_op ^= 1;
5927
5928   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5929       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5930   
5931   /* do selection */
5932   if(!invert_op)return POC_CPFSGT;
5933   else return POC_CPFSLT;
5934 }
5935
5936 static int compareAopfirstpass=1;
5937
5938 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5939             operand *oper, int offset, operand *result,
5940             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5941             symbol *tlbl)
5942 {
5943   int op;
5944   symbol *truelbl;
5945
5946   /* invert if there is a result to be loaded, in order to fit,
5947    * SETC/CLRC sequence */
5948   if(AOP_SIZE(result))invert_op ^= 1;
5949
5950 //  if(sign && !offset)invert_op ^= 1;
5951   
5952 //  if(sign)invert_op ^= 1;
5953   
5954   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5955
5956   if(AOP_SIZE(result) && compareAopfirstpass) {
5957     if(!ifx) {
5958       if(pcop2)
5959         pic16_emitpcode(POC_SETF, pcop2);
5960       else
5961         emitSETC;
5962     } else {
5963       if(pcop2)
5964         pic16_emitpcode(POC_CLRF, pcop2);
5965       else
5966         emitCLRC;
5967     }
5968   }
5969
5970   compareAopfirstpass = 0;
5971
5972       /* there is a bug when comparing operands with size > 1,
5973        * because higher bytes can be equal and test should be performed
5974        * to the next lower byte, current algorithm, considers operands
5975        * inequal in these cases! -- VR 20041107 */
5976
5977     
5978   if(pcop)
5979     pic16_emitpcode(op, pcop);
5980   else
5981     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5982
5983
5984   if((!sign || !offset) && AOP_SIZE(result)) {
5985     if(!ifx) {
5986       if(pcop2)
5987         pic16_emitpcode(POC_CLRF, pcop2);
5988         else
5989         emitCLRC;
5990     } else {
5991       if(pcop2)
5992         pic16_emitpcode(POC_SETF, pcop2);
5993       else
5994         emitSETC;
5995     }
5996     
5997     /* don't emit final branch (offset == 0) */
5998     if(offset) {
5999
6000       if(pcop2)
6001         pic16_emitpcode(POC_RRCF, pcop2);
6002
6003       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6004     }
6005   } else {
6006     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6007       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6008             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6009
6010       truelbl = newiTempLabel( NULL );
6011       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6012       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6013         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6014       else
6015         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6016       pic16_emitpLabel(truelbl->key);
6017     } else {
6018       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6019     }
6020   }
6021 }
6022
6023 static void genCmp (operand *left, operand *right,
6024                     operand *result, iCode *ifx, int sign)
6025 {
6026   int size, cmpop=1;
6027   long lit = 0L;
6028   resolvedIfx rFalseIfx;
6029   symbol *falselbl, *tlbl;
6030
6031     FENTRY;
6032     
6033     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6034
6035     resolveIfx(&rFalseIfx, ifx);
6036     size = max(AOP_SIZE(left), AOP_SIZE(right));
6037     
6038     /* if left & right are bit variables */
6039     if(AOP_TYPE(left) == AOP_CRY
6040       && AOP_TYPE(right) == AOP_CRY ) {
6041
6042         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6043         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6044         
6045         werror(W_POSSBUG2, __FILE__, __LINE__);
6046         exit(-1);
6047     }
6048     
6049     /* if literal is on the right then swap with left */
6050     if((AOP_TYPE(right) == AOP_LIT)) {
6051       operand *tmp = right ;
6052 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6053
6054         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6055
6056 //      lit = (lit - 1) & mask;
6057         right = left;
6058         left = tmp;
6059         rFalseIfx.condition ^= 1;               /* reverse compare */
6060     } else
6061     if ((AOP_TYPE(left) == AOP_LIT)) {
6062       /* float compares are handled by support functions */
6063       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6064     }
6065
6066     /* actual comparing algorithm */
6067 //    size = AOP_SIZE( right );
6068
6069     falselbl = newiTempLabel( NULL );
6070     if(AOP_TYPE(left) == AOP_LIT) {
6071       /* compare to literal */
6072       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6073       
6074       if(sign) {
6075         pCodeOp *pct, *pct2;
6076         symbol *tlbl1;
6077
6078         /* signed compare */
6079         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6080
6081         /* using PRODL:PRODH as a temporary register here */
6082         pct = pic16_popCopyReg(&pic16_pc_prodl);
6083         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6084         tlbl = newiTempLabel( NULL );
6085         
6086         /* first compare signs:
6087          *  a. if both are positive, compare just like unsigned
6088          *  b. if both are negative, invert cmpop, compare just like unsigned
6089          *  c. if different signs, determine the result directly */
6090
6091         size--;
6092
6093 #if 1
6094         /* { */
6095         tlbl1 = newiTempLabel( NULL );
6096 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6097
6098         if(lit > 0) {
6099
6100           /* literal is zero or positive:
6101            *  a. if carry is zero, too, continue compare,
6102            *  b. if carry is set, then continue depending on cmpop ^ condition:
6103            *    1. '<' return false (literal < variable),
6104            *    2. '>' return true (literal > variable) */
6105 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6106           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6107           
6108           
6109           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6110           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6111         } else 
6112         if(lit < 0) {
6113           
6114           /* literal is negative:
6115            *  a. if carry is set, too, continue compare,
6116            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6117            *    1. '<' return true (literal < variable),
6118            *    2. '>' return false (literal > variable) */
6119 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6120           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6121           
6122           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6123           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6124         }
6125 #if 1
6126         else {
6127           /* lit == 0 */
6128           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6129           
6130           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6131           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6132         }
6133 #endif
6134         
6135         
6136         pic16_emitpLabel( tlbl1->key );
6137 #endif  /* } */
6138
6139         compareAopfirstpass=1;
6140 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6141 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6142 //        pic16_emitpcode(POC_MOVWF, pct);
6143
6144 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6145         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6146 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6147         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6148
6149         /* generic case */        
6150           while( size-- ) {
6151 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6152 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6153 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6154 //            pic16_emitpcode(POC_MOVWF, pct);
6155
6156 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6157             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6158             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6159 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6160 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6161           }
6162         
6163         if(ifx)ifx->generated = 1;
6164
6165         if(AOP_SIZE(result)) {
6166           pic16_emitpLabel(tlbl->key);
6167           pic16_emitpLabel(falselbl->key);
6168           pic16_outBitOp( result, pct2 );
6169         } else {
6170           pic16_emitpLabel(tlbl->key);
6171         }
6172       } else {
6173
6174         /* unsigned compare */      
6175         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6176     
6177         compareAopfirstpass=1;
6178         while(size--) {
6179           
6180           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6181           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6182
6183         }
6184         if(ifx)ifx->generated = 1;
6185
6186         if(AOP_SIZE(result)) {
6187           pic16_emitpLabel(falselbl->key);
6188           pic16_outBitC( result );
6189         }
6190
6191       }
6192     } else {
6193       /* compare registers */
6194       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6195
6196
6197       if(sign) {
6198         pCodeOp *pct, *pct2;
6199         
6200         /* signed compare */
6201         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6202
6203         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6204         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6205         tlbl = newiTempLabel( NULL );
6206         
6207         compareAopfirstpass=1;
6208
6209         size--;
6210         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6211 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6212         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6213         pic16_emitpcode(POC_MOVWF, pct);
6214
6215         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6216 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6217         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6218
6219         /* WREG already holds left + 0x80 */
6220         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6221         
6222         while( size-- ) {
6223           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6224 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6225           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6226           pic16_emitpcode(POC_MOVWF, pct);
6227                 
6228           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6229 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6230           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6231
6232           /* WREG already holds left + 0x80 */
6233           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6234 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6235         }
6236         
6237         if(ifx)ifx->generated = 1;
6238
6239         if(AOP_SIZE(result)) {
6240           pic16_emitpLabel(tlbl->key);
6241           pic16_emitpLabel(falselbl->key);
6242           pic16_outBitOp( result, pct2 );
6243         } else {
6244           pic16_emitpLabel(tlbl->key);
6245         }
6246
6247       } else {
6248         /* unsigned compare */      
6249         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6250
6251         compareAopfirstpass=1;
6252         while(size--) {
6253           
6254           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6255           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6256
6257         }
6258
6259         if(ifx)ifx->generated = 1;
6260         if(AOP_SIZE(result)) {
6261
6262           pic16_emitpLabel(falselbl->key);
6263           pic16_outBitC( result );
6264         }
6265
6266       }
6267     }
6268 }
6269
6270 #endif  /* } */
6271
6272
6273
6274 /*-----------------------------------------------------------------*/
6275 /* genCmpGt :- greater than comparison                             */
6276 /*-----------------------------------------------------------------*/
6277 static void genCmpGt (iCode *ic, iCode *ifx)
6278 {
6279   operand *left, *right, *result;
6280   sym_link *letype , *retype;
6281   int sign ;
6282
6283     FENTRY;
6284     
6285     left = IC_LEFT(ic);
6286     right= IC_RIGHT(ic);
6287     result = IC_RESULT(ic);
6288
6289     letype = getSpec(operandType(left));
6290     retype =getSpec(operandType(right));
6291     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6292     /* assign the amsops */
6293     pic16_aopOp (left,ic,FALSE);
6294     pic16_aopOp (right,ic,FALSE);
6295     pic16_aopOp (result,ic,TRUE);
6296
6297     genCmp(right, left, result, ifx, sign);
6298
6299     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6300     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6301     pic16_freeAsmop(result,NULL,ic,TRUE); 
6302 }
6303
6304 /*-----------------------------------------------------------------*/
6305 /* genCmpLt - less than comparisons                                */
6306 /*-----------------------------------------------------------------*/
6307 static void genCmpLt (iCode *ic, iCode *ifx)
6308 {
6309   operand *left, *right, *result;
6310   sym_link *letype , *retype;
6311   int sign ;
6312
6313     FENTRY;
6314
6315     left = IC_LEFT(ic);
6316     right= IC_RIGHT(ic);
6317     result = IC_RESULT(ic);
6318
6319     letype = getSpec(operandType(left));
6320     retype =getSpec(operandType(right));
6321     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6322
6323     /* assign the amsops */
6324     pic16_aopOp (left,ic,FALSE);
6325     pic16_aopOp (right,ic,FALSE);
6326     pic16_aopOp (result,ic,TRUE);
6327
6328     genCmp(left, right, result, ifx, sign);
6329
6330     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6331     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6332     pic16_freeAsmop(result,NULL,ic,TRUE); 
6333 }
6334
6335 #if 0
6336 // not needed ATM
6337 // FIXME reenable literal optimisation when the pic16 port is stable
6338
6339 /*-----------------------------------------------------------------*/
6340 /* genc16bit2lit - compare a 16 bit value to a literal             */
6341 /*-----------------------------------------------------------------*/
6342 static void genc16bit2lit(operand *op, int lit, int offset)
6343 {
6344   int i;
6345
6346   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6347   if( (lit&0xff) == 0) 
6348     i=1;
6349   else
6350     i=0;
6351
6352   switch( BYTEofLONG(lit,i)) { 
6353   case 0:
6354     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6355     break;
6356   case 1:
6357     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6358     break;
6359   case 0xff:
6360     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6361     break;
6362   default:
6363     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6364     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6365   }
6366
6367   i ^= 1;
6368
6369   switch( BYTEofLONG(lit,i)) { 
6370   case 0:
6371     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6372     break;
6373   case 1:
6374     emitSKPNZ;
6375     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6376     break;
6377   case 0xff:
6378     emitSKPNZ;
6379     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6380     break;
6381   default:
6382     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6383     emitSKPNZ;
6384     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6385
6386   }
6387
6388 }
6389 #endif
6390
6391 #if 0
6392 // not needed ATM
6393 /*-----------------------------------------------------------------*/
6394 /* gencjneshort - compare and jump if not equal                    */
6395 /*-----------------------------------------------------------------*/
6396 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6397 {
6398   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6399   int offset = 0;
6400   int res_offset = 0;  /* the result may be a different size then left or right */
6401   int res_size = AOP_SIZE(result);
6402   resolvedIfx rIfx;
6403   symbol *lbl, *lbl_done;
6404
6405   unsigned long lit = 0L;
6406   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6407
6408   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6409   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6410   if(result)
6411     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6412   resolveIfx(&rIfx,ifx);
6413   lbl =  newiTempLabel(NULL);
6414   lbl_done =  newiTempLabel(NULL);
6415
6416
6417   /* if the left side is a literal or 
6418      if the right is in a pointer register and left 
6419      is not */
6420   if ((AOP_TYPE(left) == AOP_LIT) || 
6421       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6422     operand *t = right;
6423     right = left;
6424     left = t;
6425   }
6426   if(AOP_TYPE(right) == AOP_LIT)
6427     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6428
6429   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6430     preserve_result = 1;
6431
6432   if(result && !preserve_result)
6433     {
6434       int i;
6435       for(i = 0; i < AOP_SIZE(result); i++)
6436         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6437     }
6438
6439
6440   /* if the right side is a literal then anything goes */
6441   if (AOP_TYPE(right) == AOP_LIT &&
6442       AOP_TYPE(left) != AOP_DIR ) {
6443     switch(size) {
6444     case 2:
6445       genc16bit2lit(left, lit, 0);
6446       emitSKPZ;
6447       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6448       break;
6449     default:
6450       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6451       while (size--) {
6452         if(lit & 0xff) {
6453           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6454           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6455         } else {
6456           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6457         }
6458
6459         emitSKPZ;
6460         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6461         offset++;
6462         if(res_offset < res_size-1)
6463           res_offset++;
6464         lit >>= 8;
6465       }
6466       break;
6467     }
6468   }
6469
6470   /* if the right side is in a register or in direct space or
6471      if the left is a pointer register & right is not */    
6472   else if (AOP_TYPE(right) == AOP_REG ||
6473            AOP_TYPE(right) == AOP_DIR || 
6474            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6475            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6476     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6477     int lbl_key = lbl->key;
6478
6479     if(result) {
6480       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6481       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6482     }else {
6483       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6484       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6485               __FUNCTION__,__LINE__);
6486       return;
6487     }
6488    
6489 /*     switch(size) { */
6490 /*     case 2: */
6491 /*       genc16bit2lit(left, lit, 0); */
6492 /*       emitSKPNZ; */
6493 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6494 /*       break; */
6495 /*     default: */
6496     while (size--) {
6497       int emit_skip=1;
6498       if((AOP_TYPE(left) == AOP_DIR) && 
6499          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6500
6501         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6502         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6503
6504       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6505             
6506         switch (lit & 0xff) {
6507         case 0:
6508           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6509           break;
6510         case 1:
6511           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6512           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6513           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6514           emit_skip=0;
6515           break;
6516         case 0xff:
6517           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6518           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6519           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6520           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6521           emit_skip=0;
6522           break;
6523         default:
6524           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6525           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6526         }
6527         lit >>= 8;
6528
6529       } else {
6530         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6531       }
6532       if(emit_skip) {
6533         if(AOP_TYPE(result) == AOP_CRY) {
6534           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6535           if(rIfx.condition)
6536             emitSKPNZ;
6537           else
6538             emitSKPZ;
6539           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6540         } else {
6541           /* fix me. probably need to check result size too */
6542           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6543           if(rIfx.condition)
6544             emitSKPZ;
6545           else
6546             emitSKPNZ;
6547           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6548           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6549         }
6550         if(ifx)
6551           ifx->generated=1;
6552       }
6553       emit_skip++;
6554       offset++;
6555       if(res_offset < res_size-1)
6556         res_offset++;
6557     }
6558 /*       break; */
6559 /*     } */
6560   } else if(AOP_TYPE(right) == AOP_REG &&
6561             AOP_TYPE(left) != AOP_DIR){
6562
6563     while(size--) {
6564       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6565       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6566       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6567       if(rIfx.condition)
6568         emitSKPNZ;
6569       else
6570         emitSKPZ;
6571       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6572       offset++;
6573       if(res_offset < res_size-1)
6574         res_offset++;
6575     }
6576       
6577   }else{
6578     /* right is a pointer reg need both a & b */
6579     while(size--) {
6580       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6581       if(strcmp(l,"b"))
6582         pic16_emitcode("mov","b,%s",l);
6583       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6584       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6585       offset++;
6586     }
6587   }
6588
6589   if(result && preserve_result)
6590     {
6591       int i;
6592       for(i = 0; i < AOP_SIZE(result); i++)
6593         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6594     }
6595
6596   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6597
6598   if(result && preserve_result)
6599     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6600
6601   if(!rIfx.condition)
6602     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6603
6604   pic16_emitpLabel(lbl->key);
6605
6606   if(result && preserve_result)
6607     {
6608       int i;
6609       for(i = 0; i < AOP_SIZE(result); i++)
6610         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6611
6612       pic16_emitpLabel(lbl_done->key);
6613    }
6614
6615   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6616
6617   if(ifx)
6618     ifx->generated = 1;
6619 }
6620 #endif
6621
6622 #if 0
6623 /*-----------------------------------------------------------------*/
6624 /* gencjne - compare and jump if not equal                         */
6625 /*-----------------------------------------------------------------*/
6626 static void gencjne(operand *left, operand *right, iCode *ifx)
6627 {
6628     symbol *tlbl  = newiTempLabel(NULL);
6629
6630     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6631     gencjneshort(left, right, lbl);
6632
6633     pic16_emitcode("mov","a,%s",one);
6634     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6635     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6636     pic16_emitcode("clr","a");
6637     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6638
6639     pic16_emitpLabel(lbl->key);
6640     pic16_emitpLabel(tlbl->key);
6641
6642 }
6643 #endif
6644
6645
6646 /*-----------------------------------------------------------------*/
6647 /* is_LitOp - check if operand has to be treated as literal        */
6648 /*-----------------------------------------------------------------*/
6649 static bool is_LitOp(operand *op)
6650 {
6651   return ((AOP_TYPE(op) == AOP_LIT)
6652       || ( (AOP_TYPE(op) == AOP_PCODE)
6653           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6654               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6655 }
6656
6657 /*-----------------------------------------------------------------*/
6658 /* is_LitAOp - check if operand has to be treated as literal        */
6659 /*-----------------------------------------------------------------*/
6660 static bool is_LitAOp(asmop *aop)
6661 {
6662   return ((aop->type == AOP_LIT)
6663       || ( (aop->type == AOP_PCODE)
6664           && ( (aop->aopu.pcop->type == PO_LITERAL)
6665               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6666 }
6667
6668
6669
6670 /*-----------------------------------------------------------------*/
6671 /* genCmpEq - generates code for equal to                          */
6672 /*-----------------------------------------------------------------*/
6673 static void genCmpEq (iCode *ic, iCode *ifx)
6674 {
6675   operand *left, *right, *result;
6676   symbol *falselbl = newiTempLabel(NULL);
6677   symbol *donelbl = newiTempLabel(NULL);
6678
6679   int preserve_result = 0;
6680   int generate_result = 0;
6681   int i=0;
6682   unsigned long lit = -1;
6683
6684   FENTRY;
6685   
6686   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6687   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6688   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6689  
6690   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6691
6692   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6693     {
6694       werror(W_POSSBUG2, __FILE__, __LINE__);
6695       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6696       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6697       goto release;
6698     }
6699
6700   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6701     {
6702       operand *tmp = right ;
6703       right = left;
6704       left = tmp;
6705     }
6706
6707   if (AOP_TYPE(right) == AOP_LIT) {
6708     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6709   }
6710
6711   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6712     preserve_result = 1;
6713
6714   if(result && AOP_SIZE(result))
6715     generate_result = 1;
6716
6717   if(generate_result && !preserve_result)
6718     {
6719       for(i = 0; i < AOP_SIZE(result); i++)
6720         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6721     }
6722
6723   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6724   for(i=0; i < AOP_SIZE(left); i++)
6725     {
6726       if(AOP_TYPE(left) != AOP_ACC)
6727         {
6728           if(is_LitOp(left))
6729             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6730           else
6731             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6732         }
6733       if(is_LitOp(right)) {
6734         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6735           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6736         }
6737       } else
6738         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6739
6740       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6741     }
6742
6743   // result == true
6744
6745   if(generate_result && preserve_result)
6746     {
6747       for(i = 0; i < AOP_SIZE(result); i++)
6748         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6749     }
6750
6751   if(generate_result)
6752     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6753
6754   if(generate_result && preserve_result)
6755     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6756
6757   if(ifx && IC_TRUE(ifx))
6758     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6759
6760   if(ifx && IC_FALSE(ifx))
6761     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6762
6763   pic16_emitpLabel(falselbl->key);
6764
6765   // result == false
6766
6767   if(ifx && IC_FALSE(ifx))
6768     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6769
6770   if(generate_result && preserve_result)
6771     {
6772       for(i = 0; i < AOP_SIZE(result); i++)
6773         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6774     }
6775
6776   pic16_emitpLabel(donelbl->key);
6777
6778   if(ifx)
6779     ifx->generated = 1;
6780
6781 release:
6782   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6783   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6784   pic16_freeAsmop(result,NULL,ic,TRUE);
6785
6786 }
6787
6788
6789 #if 0
6790 // old version kept for reference
6791
6792 /*-----------------------------------------------------------------*/
6793 /* genCmpEq - generates code for equal to                          */
6794 /*-----------------------------------------------------------------*/
6795 static void genCmpEq (iCode *ic, iCode *ifx)
6796 {
6797     operand *left, *right, *result;
6798     unsigned long lit = 0L;
6799     int size,offset=0;
6800     symbol *falselbl  = newiTempLabel(NULL);
6801
6802
6803     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6804
6805     if(ifx)
6806       DEBUGpic16_emitcode ("; ifx is non-null","");
6807     else
6808       DEBUGpic16_emitcode ("; ifx is null","");
6809
6810     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6811     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6812     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6813
6814     size = max(AOP_SIZE(left),AOP_SIZE(right));
6815
6816     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6817
6818     /* if literal, literal on the right or 
6819     if the right is in a pointer register and left 
6820     is not */
6821     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6822         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6823       operand *tmp = right ;
6824       right = left;
6825       left = tmp;
6826     }
6827
6828
6829     if(ifx && !AOP_SIZE(result)){
6830         symbol *tlbl;
6831         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6832         /* if they are both bit variables */
6833         if (AOP_TYPE(left) == AOP_CRY &&
6834             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6835                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6836             if(AOP_TYPE(right) == AOP_LIT){
6837                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6838                 if(lit == 0L){
6839                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6840                     pic16_emitcode("cpl","c");
6841                 } else if(lit == 1L) {
6842                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6843                 } else {
6844                     pic16_emitcode("clr","c");
6845                 }
6846                 /* AOP_TYPE(right) == AOP_CRY */
6847             } else {
6848                 symbol *lbl = newiTempLabel(NULL);
6849                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6850                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6851                 pic16_emitcode("cpl","c");
6852                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6853             }
6854             /* if true label then we jump if condition
6855             supplied is true */
6856             tlbl = newiTempLabel(NULL);
6857             if ( IC_TRUE(ifx) ) {
6858                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6859                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6860             } else {
6861                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6862                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6863             }
6864             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6865
6866                 {
6867                 /* left and right are both bit variables, result is carry */
6868                         resolvedIfx rIfx;
6869               
6870                         resolveIfx(&rIfx,ifx);
6871
6872                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6873                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6874                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6875                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6876                         genSkipz2(&rIfx,0);
6877                 }
6878         } else {
6879
6880                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6881
6882                         /* They're not both bit variables. Is the right a literal? */
6883                         if(AOP_TYPE(right) == AOP_LIT) {
6884                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6885             
6886                         switch(size) {
6887
6888                                 case 1:
6889                                         switch(lit & 0xff) {
6890                                                 case 1:
6891                                                                 if ( IC_TRUE(ifx) ) {
6892                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6893                                                                         emitSKPNZ;
6894                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6895                                                                 } else {
6896                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6897                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6898                                                                 }
6899                                                                 break;
6900                                                 case 0xff:
6901                                                                 if ( IC_TRUE(ifx) ) {
6902                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6903                                                                         emitSKPNZ;
6904                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6905                                                                 } else {
6906                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6907                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6908                                                                 }
6909                                                                 break;
6910                                                 default:
6911                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6912                                                                 if(lit)
6913                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6914                                                                 genSkip(ifx,'z');
6915                                         } // switch lit
6916
6917
6918                                         /* end of size == 1 */
6919                                         break;
6920               
6921                                 case 2:
6922                                         genc16bit2lit(left,lit,offset);
6923                                         genSkip(ifx,'z');
6924                                         break;
6925                                         /* end of size == 2 */
6926
6927                                 default:
6928                                         /* size is 4 */
6929                                         if(lit==0) {
6930                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6931                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6932                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6933                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6934                                                 genSkip(ifx,'z');
6935                                         } else {
6936                                                 /* search for patterns that can be optimized */
6937
6938                                                 genc16bit2lit(left,lit,0);
6939                                                 lit >>= 16;
6940                                                 if(lit) {
6941                                                                 if(IC_TRUE(ifx))
6942                                                                 emitSKPZ; // if hi word unequal
6943                                                                 else
6944                                                                 emitSKPNZ; // if hi word equal
6945                                                                 // fail early
6946                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6947                                                         genc16bit2lit(left,lit,2);
6948                                                         genSkip(ifx,'z');
6949                                                 } else {
6950                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6951                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6952                                                         genSkip(ifx,'z');
6953                                                 }
6954                                         }
6955                                                 pic16_emitpLabel(falselbl->key);
6956                                                 break;
6957
6958                         } // switch size
6959           
6960                         ifx->generated = 1;
6961                         goto release ;
6962             
6963
6964           } else if(AOP_TYPE(right) == AOP_CRY ) {
6965             /* we know the left is not a bit, but that the right is */
6966             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6967             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6968                       pic16_popGet(AOP(right),offset));
6969             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6970
6971             /* if the two are equal, then W will be 0 and the Z bit is set
6972              * we could test Z now, or go ahead and check the high order bytes if
6973              * the variable we're comparing is larger than a byte. */
6974
6975             while(--size)
6976               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6977
6978             if ( IC_TRUE(ifx) ) {
6979               emitSKPNZ;
6980               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6981               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6982             } else {
6983               emitSKPZ;
6984               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6985               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6986             }
6987
6988           } else {
6989             /* They're both variables that are larger than bits */
6990             int s = size;
6991
6992             tlbl = newiTempLabel(NULL);
6993
6994             while(size--) {
6995               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6996               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6997
6998               if ( IC_TRUE(ifx) ) {
6999                 if(size) {
7000                   emitSKPZ;
7001                 
7002                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7003
7004                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7005                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7006                 } else {
7007                   emitSKPNZ;
7008
7009                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7010
7011
7012                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7013                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7014                 }
7015               } else {
7016                 emitSKPZ;
7017
7018                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7019
7020                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7021                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7022               }
7023               offset++;
7024             }
7025             if(s>1 && IC_TRUE(ifx)) {
7026               pic16_emitpLabel(tlbl->key);
7027               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7028             }
7029           }
7030         }
7031         /* mark the icode as generated */
7032         ifx->generated = 1;
7033         goto release ;
7034     }
7035
7036     /* if they are both bit variables */
7037     if (AOP_TYPE(left) == AOP_CRY &&
7038         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7039         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7040         if(AOP_TYPE(right) == AOP_LIT){
7041             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7042             if(lit == 0L){
7043                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7044                 pic16_emitcode("cpl","c");
7045             } else if(lit == 1L) {
7046                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7047             } else {
7048                 pic16_emitcode("clr","c");
7049             }
7050             /* AOP_TYPE(right) == AOP_CRY */
7051         } else {
7052             symbol *lbl = newiTempLabel(NULL);
7053             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7054             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7055             pic16_emitcode("cpl","c");
7056             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7057         }
7058         /* c = 1 if egal */
7059         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7060             pic16_outBitC(result);
7061             goto release ;
7062         }
7063         if (ifx) {
7064             genIfxJump (ifx,"c");
7065             goto release ;
7066         }
7067         /* if the result is used in an arithmetic operation
7068         then put the result in place */
7069         pic16_outBitC(result);
7070     } else {
7071       
7072       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7073       gencjne(left,right,result,ifx);
7074 /*
7075       if(ifx) 
7076         gencjne(left,right,newiTempLabel(NULL));
7077       else {
7078         if(IC_TRUE(ifx)->key)
7079           gencjne(left,right,IC_TRUE(ifx)->key);
7080         else
7081           gencjne(left,right,IC_FALSE(ifx)->key);
7082         ifx->generated = 1;
7083         goto release ;
7084       }
7085       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7086         pic16_aopPut(AOP(result),"a",0);
7087         goto release ;
7088       }
7089
7090       if (ifx) {
7091         genIfxJump (ifx,"a");
7092         goto release ;
7093       }
7094 */
7095       /* if the result is used in an arithmetic operation
7096          then put the result in place */
7097 /*
7098       if (AOP_TYPE(result) != AOP_CRY) 
7099         pic16_outAcc(result);
7100 */
7101       /* leave the result in acc */
7102     }
7103
7104 release:
7105     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7106     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7107     pic16_freeAsmop(result,NULL,ic,TRUE);
7108 }
7109 #endif
7110
7111 /*-----------------------------------------------------------------*/
7112 /* ifxForOp - returns the icode containing the ifx for operand     */
7113 /*-----------------------------------------------------------------*/
7114 static iCode *ifxForOp ( operand *op, iCode *ic )
7115 {
7116   FENTRY2;
7117
7118     /* if true symbol then needs to be assigned */
7119     if (IS_TRUE_SYMOP(op))
7120         return NULL ;
7121
7122     /* if this has register type condition and
7123     the next instruction is ifx with the same operand
7124     and live to of the operand is upto the ifx only then */
7125     if (ic->next
7126         && ic->next->op == IFX
7127         && IC_COND(ic->next)->key == op->key
7128         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7129         ) {
7130                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7131           return ic->next;
7132     }
7133
7134     /*
7135     if (ic->next &&
7136         ic->next->op == IFX &&
7137         IC_COND(ic->next)->key == op->key) {
7138       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7139       return ic->next;
7140     }
7141     */
7142
7143     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7144     if (ic->next &&
7145         ic->next->op == IFX)
7146       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7147
7148     if (ic->next &&
7149         ic->next->op == IFX &&
7150         IC_COND(ic->next)->key == op->key) {
7151       DEBUGpic16_emitcode ("; "," key is okay");
7152       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7153                            OP_SYMBOL(op)->liveTo,
7154                            ic->next->seq);
7155     }
7156
7157 #if 0
7158     /* the code below is completely untested
7159      * it just allows ulong2fs.c compile -- VR */
7160          
7161     ic = ic->next;
7162     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7163                                         __FILE__, __FUNCTION__, __LINE__);
7164         
7165     /* if this has register type condition and
7166     the next instruction is ifx with the same operand
7167     and live to of the operand is upto the ifx only then */
7168     if (ic->next &&
7169         ic->next->op == IFX &&
7170         IC_COND(ic->next)->key == op->key &&
7171         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7172         return ic->next;
7173
7174     if (ic->next &&
7175         ic->next->op == IFX &&
7176         IC_COND(ic->next)->key == op->key) {
7177       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7178       return ic->next;
7179     }
7180
7181     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7182                                         __FILE__, __FUNCTION__, __LINE__);
7183
7184 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7185 #endif
7186
7187     return NULL;
7188 }
7189 /*-----------------------------------------------------------------*/
7190 /* genAndOp - for && operation                                     */
7191 /*-----------------------------------------------------------------*/
7192 static void genAndOp (iCode *ic)
7193 {
7194   operand *left,*right, *result;
7195 /*     symbol *tlbl; */
7196
7197     FENTRY;
7198
7199     /* note here that && operations that are in an
7200     if statement are taken away by backPatchLabels
7201     only those used in arthmetic operations remain */
7202     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7203     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7204     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7205
7206     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7207
7208     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7209     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7210     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7211
7212     /* if both are bit variables */
7213 /*     if (AOP_TYPE(left) == AOP_CRY && */
7214 /*         AOP_TYPE(right) == AOP_CRY ) { */
7215 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7216 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7217 /*         pic16_outBitC(result); */
7218 /*     } else { */
7219 /*         tlbl = newiTempLabel(NULL); */
7220 /*         pic16_toBoolean(left);     */
7221 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7222 /*         pic16_toBoolean(right); */
7223 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7224 /*         pic16_outBitAcc(result); */
7225 /*     } */
7226
7227     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7228     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7229     pic16_freeAsmop(result,NULL,ic,TRUE);
7230 }
7231
7232
7233 /*-----------------------------------------------------------------*/
7234 /* genOrOp - for || operation                                      */
7235 /*-----------------------------------------------------------------*/
7236 /*
7237   tsd pic port -
7238   modified this code, but it doesn't appear to ever get called
7239 */
7240
7241 static void genOrOp (iCode *ic)
7242 {
7243   operand *left,*right, *result;
7244   symbol *tlbl;
7245
7246     FENTRY;  
7247
7248   /* note here that || operations that are in an
7249     if statement are taken away by backPatchLabels
7250     only those used in arthmetic operations remain */
7251     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7252     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7253     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7254
7255     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7256
7257     /* if both are bit variables */
7258     if (AOP_TYPE(left) == AOP_CRY &&
7259         AOP_TYPE(right) == AOP_CRY ) {
7260       pic16_emitcode("clrc","");
7261       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7262                AOP(left)->aopu.aop_dir,
7263                AOP(left)->aopu.aop_dir);
7264       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7265                AOP(right)->aopu.aop_dir,
7266                AOP(right)->aopu.aop_dir);
7267       pic16_emitcode("setc","");
7268
7269     } else {
7270         tlbl = newiTempLabel(NULL);
7271         pic16_toBoolean(left);
7272         emitSKPZ;
7273         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7274         pic16_toBoolean(right);
7275         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7276
7277         pic16_outBitAcc(result);
7278     }
7279
7280     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7281     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7282     pic16_freeAsmop(result,NULL,ic,TRUE);            
7283 }
7284
7285 /*-----------------------------------------------------------------*/
7286 /* isLiteralBit - test if lit == 2^n                               */
7287 /*-----------------------------------------------------------------*/
7288 static int isLiteralBit(unsigned long lit)
7289 {
7290     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7291     0x100L,0x200L,0x400L,0x800L,
7292     0x1000L,0x2000L,0x4000L,0x8000L,
7293     0x10000L,0x20000L,0x40000L,0x80000L,
7294     0x100000L,0x200000L,0x400000L,0x800000L,
7295     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7296     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7297     int idx;
7298     
7299     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7300     for(idx = 0; idx < 32; idx++)
7301         if(lit == pw[idx])
7302             return idx+1;
7303     return 0;
7304 }
7305
7306 /*-----------------------------------------------------------------*/
7307 /* continueIfTrue -                                                */
7308 /*-----------------------------------------------------------------*/
7309 static void continueIfTrue (iCode *ic)
7310 {
7311   FENTRY;
7312   if(IC_TRUE(ic))
7313     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7314   ic->generated = 1;
7315 }
7316
7317 /*-----------------------------------------------------------------*/
7318 /* jmpIfTrue -                                                     */
7319 /*-----------------------------------------------------------------*/
7320 static void jumpIfTrue (iCode *ic)
7321 {
7322   FENTRY;
7323   if(!IC_TRUE(ic))
7324     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7325   ic->generated = 1;
7326 }
7327
7328 /*-----------------------------------------------------------------*/
7329 /* jmpTrueOrFalse -                                                */
7330 /*-----------------------------------------------------------------*/
7331 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7332 {
7333   // ugly but optimized by peephole
7334   FENTRY;
7335   if(IC_TRUE(ic)){
7336     symbol *nlbl = newiTempLabel(NULL);
7337       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7338       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7339       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7340       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7341   } else {
7342     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7343     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7344   }
7345   ic->generated = 1;
7346 }
7347
7348 /*-----------------------------------------------------------------*/
7349 /* genAnd  - code for and                                          */
7350 /*-----------------------------------------------------------------*/
7351 static void genAnd (iCode *ic, iCode *ifx)
7352 {
7353   operand *left, *right, *result;
7354   int size, offset=0;  
7355   unsigned long lit = 0L;
7356   int bytelit = 0;
7357   resolvedIfx rIfx;
7358
7359     FENTRY;
7360     
7361   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7362   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7363   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7364
7365   resolveIfx(&rIfx,ifx);
7366
7367   /* if left is a literal & right is not then exchange them */
7368   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7369       AOP_NEEDSACC(left)) {
7370     operand *tmp = right ;
7371     right = left;
7372     left = tmp;
7373   }
7374
7375   /* if result = right then exchange them */
7376   if(pic16_sameRegs(AOP(result),AOP(right))){
7377     operand *tmp = right ;
7378     right = left;
7379     left = tmp;
7380   }
7381
7382   /* if right is bit then exchange them */
7383   if (AOP_TYPE(right) == AOP_CRY &&
7384       AOP_TYPE(left) != AOP_CRY){
7385     operand *tmp = right ;
7386     right = left;
7387     left = tmp;
7388   }
7389   if(AOP_TYPE(right) == AOP_LIT)
7390     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7391
7392   size = AOP_SIZE(result);
7393
7394   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7395
7396   // if(bit & yy)
7397   // result = bit & yy;
7398   if (AOP_TYPE(left) == AOP_CRY){
7399     // c = bit & literal;
7400     if(AOP_TYPE(right) == AOP_LIT){
7401       if(lit & 1) {
7402         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7403           // no change
7404           goto release;
7405         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7406       } else {
7407         // bit(result) = 0;
7408         if(size && (AOP_TYPE(result) == AOP_CRY)){
7409           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7410           goto release;
7411         }
7412         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7413           jumpIfTrue(ifx);
7414           goto release;
7415         }
7416         pic16_emitcode("clr","c");
7417       }
7418     } else {
7419       if (AOP_TYPE(right) == AOP_CRY){
7420         // c = bit & bit;
7421         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7422         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7423       } else {
7424         // c = bit & val;
7425         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7426         // c = lsb
7427         pic16_emitcode("rrc","a");
7428         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7429       }
7430     }
7431     // bit = c
7432     // val = c
7433     if(size)
7434       pic16_outBitC(result);
7435     // if(bit & ...)
7436     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7437       genIfxJump(ifx, "c");           
7438     goto release ;
7439   }
7440
7441   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7442   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7443   if((AOP_TYPE(right) == AOP_LIT) &&
7444      (AOP_TYPE(result) == AOP_CRY) &&
7445      (AOP_TYPE(left) != AOP_CRY)){
7446     int posbit = isLiteralBit(lit);
7447     /* left &  2^n */
7448     if(posbit){
7449       posbit--;
7450       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7451       // bit = left & 2^n
7452       if(size)
7453         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7454       // if(left &  2^n)
7455       else{
7456         if(ifx){
7457 /*
7458           if(IC_TRUE(ifx)) {
7459             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7460             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7461           } else {
7462             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7463             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7464           }
7465 */
7466         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7467         size = AOP_SIZE(left);
7468
7469         {
7470           int bp = posbit, ofs=0;
7471           
7472             while(bp > 7) {
7473               bp -= 8;
7474               ofs++;
7475             }
7476
7477           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7478                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7479
7480         }
7481 /*
7482           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7483                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7484 */
7485           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7486           
7487           ifx->generated = 1;
7488         }
7489         goto release;
7490       }
7491     } else {
7492       symbol *tlbl = newiTempLabel(NULL);
7493       int sizel = AOP_SIZE(left);
7494
7495       if(size)
7496         emitSETC;
7497
7498       while(sizel--) {
7499         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7500
7501           /* patch provided by Aaron Colwell */
7502           if((posbit = isLiteralBit(bytelit)) != 0) {
7503               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7504                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7505                                                 (posbit-1),0, PO_GPR_REGISTER));
7506
7507               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7508 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7509           } else {
7510               if (bytelit == 0xff) {
7511                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7512                    * a peephole could optimize it out -- VR */
7513                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7514               } else {
7515                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7516                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7517               }
7518
7519               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7520                             pic16_popGetLabel(tlbl->key));
7521           }
7522         
7523 #if 0
7524           /* old code, left here for reference -- VR 09/2004 */
7525           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7526           // byte ==  2^n ?
7527           if((posbit = isLiteralBit(bytelit)) != 0)
7528             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7529           else{
7530             if(bytelit != 0x0FFL)
7531               pic16_emitcode("anl","a,%s",
7532                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7533             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7534           }
7535 #endif
7536         }
7537         offset++;
7538       }
7539       // bit = left & literal
7540       if(size) {
7541         emitCLRC;
7542         pic16_emitpLabel(tlbl->key);
7543       }
7544       // if(left & literal)
7545       else {
7546         if(ifx) {
7547           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7548           ifx->generated = 1;
7549         }
7550         pic16_emitpLabel(tlbl->key);
7551         goto release;
7552       }
7553     }
7554
7555     pic16_outBitC(result);
7556     goto release ;
7557   }
7558
7559   /* if left is same as result */
7560   if(pic16_sameRegs(AOP(result),AOP(left))){
7561     int know_W = -1;
7562     for(;size--; offset++,lit>>=8) {
7563       if(AOP_TYPE(right) == AOP_LIT){
7564         switch(lit & 0xff) {
7565         case 0x00:
7566           /*  and'ing with 0 has clears the result */
7567 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7568           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7569           break;
7570         case 0xff:
7571           /* and'ing with 0xff is a nop when the result and left are the same */
7572           break;
7573
7574         default:
7575           {
7576             int p = pic16_my_powof2( (~lit) & 0xff );
7577             if(p>=0) {
7578               /* only one bit is set in the literal, so use a bcf instruction */
7579 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7580               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7581
7582             } else {
7583               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7584               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7585               if(know_W != (lit&0xff))
7586                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7587               know_W = lit &0xff;
7588               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7589             }
7590           }    
7591         }
7592       } else {
7593         if (AOP_TYPE(left) == AOP_ACC) {
7594           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7595         } else {                    
7596           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7597           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7598
7599         }
7600       }
7601     }
7602
7603   } else {
7604     // left & result in different registers
7605     if(AOP_TYPE(result) == AOP_CRY){
7606       // result = bit
7607       // if(size), result in bit
7608       // if(!size && ifx), conditional oper: if(left & right)
7609       symbol *tlbl = newiTempLabel(NULL);
7610       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7611       if(size)
7612         pic16_emitcode("setb","c");
7613       while(sizer--){
7614         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7615         pic16_emitcode("anl","a,%s",
7616                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7617         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7618         offset++;
7619       }
7620       if(size){
7621         CLRC;
7622         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7623         pic16_outBitC(result);
7624       } else if(ifx)
7625         jmpTrueOrFalse(ifx, tlbl);
7626     } else {
7627       for(;(size--);offset++) {
7628         // normal case
7629         // result = left & right
7630         if(AOP_TYPE(right) == AOP_LIT){
7631           int t = (lit >> (offset*8)) & 0x0FFL;
7632           switch(t) { 
7633           case 0x00:
7634             pic16_emitcode("clrf","%s",
7635                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7636             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7637             break;
7638           case 0xff:
7639             pic16_emitcode("movf","%s,w",
7640                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7641             pic16_emitcode("movwf","%s",
7642                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7643             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7644             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7645             break;
7646           default:
7647             pic16_emitcode("movlw","0x%x",t);
7648             pic16_emitcode("andwf","%s,w",
7649                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7650             pic16_emitcode("movwf","%s",
7651                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7652               
7653             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7654             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7655             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7656           }
7657           continue;
7658         }
7659
7660         if (AOP_TYPE(left) == AOP_ACC) {
7661           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7662           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7663         } else {
7664           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7665           pic16_emitcode("andwf","%s,w",
7666                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7667           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7668           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7669         }
7670         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7671         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7672       }
7673     }
7674   }
7675
7676   release :
7677     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7678   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7679   pic16_freeAsmop(result,NULL,ic,TRUE);     
7680 }
7681
7682 /*-----------------------------------------------------------------*/
7683 /* genOr  - code for or                                            */
7684 /*-----------------------------------------------------------------*/
7685 static void genOr (iCode *ic, iCode *ifx)
7686 {
7687     operand *left, *right, *result;
7688     int size, offset=0;
7689     unsigned long lit = 0L;
7690
7691     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7692
7693     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7694     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7695     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7696
7697     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7698
7699     /* if left is a literal & right is not then exchange them */
7700     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7701         AOP_NEEDSACC(left)) {
7702         operand *tmp = right ;
7703         right = left;
7704         left = tmp;
7705     }
7706
7707     /* if result = right then exchange them */
7708     if(pic16_sameRegs(AOP(result),AOP(right))){
7709         operand *tmp = right ;
7710         right = left;
7711         left = tmp;
7712     }
7713
7714     /* if right is bit then exchange them */
7715     if (AOP_TYPE(right) == AOP_CRY &&
7716         AOP_TYPE(left) != AOP_CRY){
7717         operand *tmp = right ;
7718         right = left;
7719         left = tmp;
7720     }
7721
7722     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7723
7724     if(AOP_TYPE(right) == AOP_LIT)
7725         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7726
7727     size = AOP_SIZE(result);
7728
7729     // if(bit | yy)
7730     // xx = bit | yy;
7731     if (AOP_TYPE(left) == AOP_CRY){
7732         if(AOP_TYPE(right) == AOP_LIT){
7733             // c = bit & literal;
7734             if(lit){
7735                 // lit != 0 => result = 1
7736                 if(AOP_TYPE(result) == AOP_CRY){
7737                   if(size)
7738                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7739                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7740                   //     AOP(result)->aopu.aop_dir,
7741                   //     AOP(result)->aopu.aop_dir);
7742                     else if(ifx)
7743                         continueIfTrue(ifx);
7744                     goto release;
7745                 }
7746             } else {
7747                 // lit == 0 => result = left
7748                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7749                     goto release;
7750                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7751             }
7752         } else {
7753             if (AOP_TYPE(right) == AOP_CRY){
7754               if(pic16_sameRegs(AOP(result),AOP(left))){
7755                 // c = bit | bit;
7756                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7757                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7758                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7759
7760                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7761                          AOP(result)->aopu.aop_dir,
7762                          AOP(result)->aopu.aop_dir);
7763                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7764                          AOP(right)->aopu.aop_dir,
7765                          AOP(right)->aopu.aop_dir);
7766                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7767                          AOP(result)->aopu.aop_dir,
7768                          AOP(result)->aopu.aop_dir);
7769               } else {
7770                 if( AOP_TYPE(result) == AOP_ACC) {
7771                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7772                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7773                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7774                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7775
7776                 } else {
7777
7778                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7779                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7780                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7781                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7782
7783                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7784                                  AOP(result)->aopu.aop_dir,
7785                                  AOP(result)->aopu.aop_dir);
7786                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7787                                  AOP(right)->aopu.aop_dir,
7788                                  AOP(right)->aopu.aop_dir);
7789                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7790                                  AOP(left)->aopu.aop_dir,
7791                                  AOP(left)->aopu.aop_dir);
7792                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7793                                  AOP(result)->aopu.aop_dir,
7794                                  AOP(result)->aopu.aop_dir);
7795                 }
7796               }
7797             } else {
7798                 // c = bit | val;
7799                 symbol *tlbl = newiTempLabel(NULL);
7800                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7801
7802
7803                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7804                 if( AOP_TYPE(right) == AOP_ACC) {
7805                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7806                   emitSKPNZ;
7807                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7808                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7809                 }
7810
7811
7812
7813                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7814                     pic16_emitcode(";XXX setb","c");
7815                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7816                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7817                 pic16_toBoolean(right);
7818                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7819                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7820                     jmpTrueOrFalse(ifx, tlbl);
7821                     goto release;
7822                 } else {
7823                     CLRC;
7824                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7825                 }
7826             }
7827         }
7828         // bit = c
7829         // val = c
7830         if(size)
7831             pic16_outBitC(result);
7832         // if(bit | ...)
7833         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7834             genIfxJump(ifx, "c");           
7835         goto release ;
7836     }
7837
7838     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7839     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7840     if((AOP_TYPE(right) == AOP_LIT) &&
7841        (AOP_TYPE(result) == AOP_CRY) &&
7842        (AOP_TYPE(left) != AOP_CRY)){
7843         if(lit){
7844           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7845             // result = 1
7846             if(size)
7847                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7848             else 
7849                 continueIfTrue(ifx);
7850             goto release;
7851         } else {
7852           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7853             // lit = 0, result = boolean(left)
7854             if(size)
7855                 pic16_emitcode(";XXX setb","c");
7856             pic16_toBoolean(right);
7857             if(size){
7858                 symbol *tlbl = newiTempLabel(NULL);
7859                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7860                 CLRC;
7861                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7862             } else {
7863                 genIfxJump (ifx,"a");
7864                 goto release;
7865             }
7866         }
7867         pic16_outBitC(result);
7868         goto release ;
7869     }
7870
7871     /* if left is same as result */
7872     if(pic16_sameRegs(AOP(result),AOP(left))){
7873       int know_W = -1;
7874       for(;size--; offset++,lit>>=8) {
7875         if(AOP_TYPE(right) == AOP_LIT){
7876           if((lit & 0xff) == 0)
7877             /*  or'ing with 0 has no effect */
7878             continue;
7879           else {
7880             int p = pic16_my_powof2(lit & 0xff);
7881             if(p>=0) {
7882               /* only one bit is set in the literal, so use a bsf instruction */
7883               pic16_emitpcode(POC_BSF,
7884                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7885             } else {
7886               if(know_W != (lit & 0xff))
7887                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7888               know_W = lit & 0xff;
7889               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7890             }
7891                     
7892           }
7893         } else {
7894           if (AOP_TYPE(left) == AOP_ACC) {
7895             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7896 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7897           } else {                  
7898             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7899             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7900
7901 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7902 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7903
7904           }
7905         }
7906       }
7907     } else {
7908         // left & result in different registers
7909         if(AOP_TYPE(result) == AOP_CRY){
7910             // result = bit
7911             // if(size), result in bit
7912             // if(!size && ifx), conditional oper: if(left | right)
7913             symbol *tlbl = newiTempLabel(NULL);
7914             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7915             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7916
7917
7918             if(size)
7919                 pic16_emitcode(";XXX setb","c");
7920             while(sizer--){
7921                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7922                 pic16_emitcode(";XXX orl","a,%s",
7923                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7924                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7925                 offset++;
7926             }
7927             if(size){
7928                 CLRC;
7929                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7930                 pic16_outBitC(result);
7931             } else if(ifx)
7932                 jmpTrueOrFalse(ifx, tlbl);
7933         } else for(;(size--);offset++){
7934           // normal case
7935           // result = left & right
7936           if(AOP_TYPE(right) == AOP_LIT){
7937             int t = (lit >> (offset*8)) & 0x0FFL;
7938             switch(t) { 
7939             case 0x00:
7940               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7941               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7942
7943 //            pic16_emitcode("movf","%s,w",
7944 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7945 //            pic16_emitcode("movwf","%s",
7946 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7947               break;
7948             default:
7949               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7950               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7951               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7952
7953 //            pic16_emitcode("movlw","0x%x",t);
7954 //            pic16_emitcode("iorwf","%s,w",
7955 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7956 //            pic16_emitcode("movwf","%s",
7957 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7958               
7959             }
7960             continue;
7961           }
7962
7963           // faster than result <- left, anl result,right
7964           // and better if result is SFR
7965           if (AOP_TYPE(left) == AOP_ACC) {
7966             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7967 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7968           } else {
7969             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7970             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7971
7972 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7973 //          pic16_emitcode("iorwf","%s,w",
7974 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7975           }
7976           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7977 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7978         }
7979     }
7980
7981 release :
7982     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7983     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7984     pic16_freeAsmop(result,NULL,ic,TRUE);     
7985 }
7986
7987 /*-----------------------------------------------------------------*/
7988 /* genXor - code for xclusive or                                   */
7989 /*-----------------------------------------------------------------*/
7990 static void genXor (iCode *ic, iCode *ifx)
7991 {
7992   operand *left, *right, *result;
7993   int size, offset=0;
7994   unsigned long lit = 0L;
7995
7996   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7997
7998   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7999   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8000   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8001
8002   /* if left is a literal & right is not ||
8003      if left needs acc & right does not */
8004   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8005       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8006     operand *tmp = right ;
8007     right = left;
8008     left = tmp;
8009   }
8010
8011   /* if result = right then exchange them */
8012   if(pic16_sameRegs(AOP(result),AOP(right))){
8013     operand *tmp = right ;
8014     right = left;
8015     left = tmp;
8016   }
8017
8018   /* if right is bit then exchange them */
8019   if (AOP_TYPE(right) == AOP_CRY &&
8020       AOP_TYPE(left) != AOP_CRY){
8021     operand *tmp = right ;
8022     right = left;
8023     left = tmp;
8024   }
8025   if(AOP_TYPE(right) == AOP_LIT)
8026     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8027
8028   size = AOP_SIZE(result);
8029
8030   // if(bit ^ yy)
8031   // xx = bit ^ yy;
8032   if (AOP_TYPE(left) == AOP_CRY){
8033     if(AOP_TYPE(right) == AOP_LIT){
8034       // c = bit & literal;
8035       if(lit>>1){
8036         // lit>>1  != 0 => result = 1
8037         if(AOP_TYPE(result) == AOP_CRY){
8038           if(size)
8039             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8040             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8041           else if(ifx)
8042             continueIfTrue(ifx);
8043           goto release;
8044         }
8045         pic16_emitcode("setb","c");
8046       } else{
8047         // lit == (0 or 1)
8048         if(lit == 0){
8049           // lit == 0, result = left
8050           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8051             goto release;
8052           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8053         } else{
8054           // lit == 1, result = not(left)
8055           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8056             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8057             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8058             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8059             goto release;
8060           } else {
8061             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8062             pic16_emitcode("cpl","c");
8063           }
8064         }
8065       }
8066
8067     } else {
8068       // right != literal
8069       symbol *tlbl = newiTempLabel(NULL);
8070       if (AOP_TYPE(right) == AOP_CRY){
8071         // c = bit ^ bit;
8072         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8073       }
8074       else{
8075         int sizer = AOP_SIZE(right);
8076         // c = bit ^ val
8077         // if val>>1 != 0, result = 1
8078         pic16_emitcode("setb","c");
8079         while(sizer){
8080           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8081           if(sizer == 1)
8082             // test the msb of the lsb
8083             pic16_emitcode("anl","a,#0xfe");
8084           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8085           sizer--;
8086         }
8087         // val = (0,1)
8088         pic16_emitcode("rrc","a");
8089       }
8090       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8091       pic16_emitcode("cpl","c");
8092       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8093     }
8094     // bit = c
8095     // val = c
8096     if(size)
8097       pic16_outBitC(result);
8098     // if(bit | ...)
8099     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8100       genIfxJump(ifx, "c");           
8101     goto release ;
8102   }
8103
8104   if(pic16_sameRegs(AOP(result),AOP(left))){
8105     /* if left is same as result */
8106     for(;size--; offset++) {
8107       if(AOP_TYPE(right) == AOP_LIT){
8108         int t  = (lit >> (offset*8)) & 0x0FFL;
8109         if(t == 0x00L)
8110           continue;
8111         else
8112           if (IS_AOP_PREG(left)) {
8113             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8114             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8115             pic16_aopPut(AOP(result),"a",offset);
8116           } else {
8117             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8118             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8119             pic16_emitcode("xrl","%s,%s",
8120                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8121                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8122           }
8123       } else {
8124         if (AOP_TYPE(left) == AOP_ACC)
8125           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8126         else {
8127           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8128           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8129 /*
8130           if (IS_AOP_PREG(left)) {
8131             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8132             pic16_aopPut(AOP(result),"a",offset);
8133           } else
8134             pic16_emitcode("xrl","%s,a",
8135                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8136 */
8137         }
8138       }
8139     }
8140   } else {
8141     // left & result in different registers
8142     if(AOP_TYPE(result) == AOP_CRY){
8143       // result = bit
8144       // if(size), result in bit
8145       // if(!size && ifx), conditional oper: if(left ^ right)
8146       symbol *tlbl = newiTempLabel(NULL);
8147       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8148       if(size)
8149         pic16_emitcode("setb","c");
8150       while(sizer--){
8151         if((AOP_TYPE(right) == AOP_LIT) &&
8152            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8153           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8154         } else {
8155           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8156           pic16_emitcode("xrl","a,%s",
8157                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8158         }
8159         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8160         offset++;
8161       }
8162       if(size){
8163         CLRC;
8164         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8165         pic16_outBitC(result);
8166       } else if(ifx)
8167         jmpTrueOrFalse(ifx, tlbl);
8168     } else for(;(size--);offset++){
8169       // normal case
8170       // result = left & right
8171       if(AOP_TYPE(right) == AOP_LIT){
8172         int t = (lit >> (offset*8)) & 0x0FFL;
8173         switch(t) { 
8174         case 0x00:
8175           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8176           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8177           pic16_emitcode("movf","%s,w",
8178                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179           pic16_emitcode("movwf","%s",
8180                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8181           break;
8182         case 0xff:
8183           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8184           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8185           pic16_emitcode("comf","%s,w",
8186                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8187           pic16_emitcode("movwf","%s",
8188                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8189           break;
8190         default:
8191           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8192           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8193           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8194           pic16_emitcode("movlw","0x%x",t);
8195           pic16_emitcode("xorwf","%s,w",
8196                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8197           pic16_emitcode("movwf","%s",
8198                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8199
8200         }
8201         continue;
8202       }
8203
8204       // faster than result <- left, anl result,right
8205       // and better if result is SFR
8206       if (AOP_TYPE(left) == AOP_ACC) {
8207         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8208         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8209       } else {
8210         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8211         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8212         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8213         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8214       }
8215       if ( AOP_TYPE(result) != AOP_ACC){
8216         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8217         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8218       }
8219     }
8220   }
8221
8222   release :
8223     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8224   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8225   pic16_freeAsmop(result,NULL,ic,TRUE);     
8226 }
8227
8228 /*-----------------------------------------------------------------*/
8229 /* genInline - write the inline code out                           */
8230 /*-----------------------------------------------------------------*/
8231 static void genInline (iCode *ic)
8232 {
8233   char *buffer, *bp, *bp1;
8234     
8235         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8236
8237         _G.inLine += (!options.asmpeep);
8238
8239         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8240         strcpy(buffer,IC_INLINE(ic));
8241         
8242         while((bp1=strstr(bp, "\\n"))) {
8243           *bp1++ = '\n';
8244           *bp1++ = ' ';
8245           bp = bp1;
8246         }
8247         bp = bp1 = buffer;
8248
8249 #if 0
8250   /* This is an experimental code for #pragma inline
8251      and is temporarily disabled for 2.5.0 release */
8252         if(asmInlineMap)
8253         {
8254           symbol *sym;
8255           char *s;
8256           char *cbuf;
8257           int cblen;
8258
8259             cbuf = Safe_strdup(buffer);
8260             cblen = strlen(buffer)+1;
8261             memset(cbuf, 0, cblen);
8262
8263             bp = buffer;
8264             bp1 = cbuf;
8265             while(*bp) {
8266               if(*bp != '%')*bp1++ = *bp++;
8267               else {
8268                 int i;
8269
8270                   bp++;
8271                   i = *bp - '0';
8272                   if(i>elementsInSet(asmInlineMap))break;
8273                   
8274                   bp++;
8275                   s = indexSet(asmInlineMap, i);
8276                   DEBUGpc("searching symbol s = `%s'", s);
8277                   sym = findSym(SymbolTab, NULL, s);
8278
8279                   if(sym->reqv) {
8280                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8281                   } else {
8282                     strcat(bp1, sym->rname);
8283                   }
8284                   
8285                   while(*bp1)bp1++;
8286               }
8287               
8288               if(strlen(bp1) > cblen - 16) {
8289                 int i = strlen(cbuf);
8290                 cblen += 50;
8291                 cbuf = realloc(cbuf, cblen);
8292                 memset(cbuf+i, 0, 50);
8293                 bp1 = cbuf + i;
8294               }
8295             }
8296             
8297             free(buffer);
8298             buffer = Safe_strdup( cbuf );
8299             free(cbuf);
8300             
8301             bp = bp1 = buffer;
8302         }
8303 #endif  /* 0 */
8304
8305         /* emit each line as a code */
8306         while (*bp) {
8307                 if (*bp == '\n') {
8308                         *bp++ = '\0';
8309
8310                         if(*bp1)
8311                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8312                         bp1 = bp;
8313                 } else {
8314                         if (*bp == ':') {
8315                                 bp++;
8316                                 *bp = '\0';
8317                                 bp++;
8318
8319                                 /* print label, use this special format with NULL directive
8320                                  * to denote that the argument should not be indented with tab */
8321                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8322                                 bp1 = bp;
8323                         } if (*bp == ';') {
8324                                 /* advance to end of line (prevent splitting of comments at ':' */
8325                                 while (*bp && *bp != '\n') {
8326                                         bp++;
8327                                 } // while
8328                         } else
8329                                 bp++;
8330                 }
8331         }
8332
8333         if ((bp1 != bp) && *bp1)
8334                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8335
8336
8337     Safe_free(buffer);
8338
8339     _G.inLine -= (!options.asmpeep);
8340 }
8341
8342 /*-----------------------------------------------------------------*/
8343 /* genRRC - rotate right with carry                                */
8344 /*-----------------------------------------------------------------*/
8345 static void genRRC (iCode *ic)
8346 {
8347   operand *left , *result ;
8348   int size, offset = 0, same;
8349
8350   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8351
8352   /* rotate right with carry */
8353   left = IC_LEFT(ic);
8354   result=IC_RESULT(ic);
8355   pic16_aopOp (left,ic,FALSE);
8356   pic16_aopOp (result,ic,TRUE);
8357
8358   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8359
8360   same = pic16_sameRegs(AOP(result),AOP(left));
8361
8362   size = AOP_SIZE(result);    
8363
8364   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8365
8366   /* get the lsb and put it into the carry */
8367   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8368
8369   offset = 0 ;
8370
8371   while(size--) {
8372
8373     if(same) {
8374       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8375     } else {
8376       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8377       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8378     }
8379
8380     offset++;
8381   }
8382
8383   pic16_freeAsmop(left,NULL,ic,TRUE);
8384   pic16_freeAsmop(result,NULL,ic,TRUE);
8385 }
8386
8387 /*-----------------------------------------------------------------*/
8388 /* genRLC - generate code for rotate left with carry               */
8389 /*-----------------------------------------------------------------*/
8390 static void genRLC (iCode *ic)
8391 {    
8392   operand *left , *result ;
8393   int size, offset = 0;
8394   int same;
8395
8396   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8397   /* rotate right with carry */
8398   left = IC_LEFT(ic);
8399   result=IC_RESULT(ic);
8400   pic16_aopOp (left,ic,FALSE);
8401   pic16_aopOp (result,ic,TRUE);
8402
8403   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8404
8405   same = pic16_sameRegs(AOP(result),AOP(left));
8406
8407   /* move it to the result */
8408   size = AOP_SIZE(result);    
8409
8410   /* get the msb and put it into the carry */
8411   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8412
8413   offset = 0 ;
8414
8415   while(size--) {
8416
8417     if(same) {
8418       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8419     } else {
8420       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8421       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8422     }
8423
8424     offset++;
8425   }
8426
8427
8428   pic16_freeAsmop(left,NULL,ic,TRUE);
8429   pic16_freeAsmop(result,NULL,ic,TRUE);
8430 }
8431
8432
8433 /* gpasm can get the highest order bit with HIGH/UPPER
8434  * so the following probably is not needed -- VR */
8435  
8436 /*-----------------------------------------------------------------*/
8437 /* genGetHbit - generates code get highest order bit               */
8438 /*-----------------------------------------------------------------*/
8439 static void genGetHbit (iCode *ic)
8440 {
8441     operand *left, *result;
8442     left = IC_LEFT(ic);
8443     result=IC_RESULT(ic);
8444     pic16_aopOp (left,ic,FALSE);
8445     pic16_aopOp (result,ic,FALSE);
8446
8447     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8448     /* get the highest order byte into a */
8449     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8450     if(AOP_TYPE(result) == AOP_CRY){
8451         pic16_emitcode("rlc","a");
8452         pic16_outBitC(result);
8453     }
8454     else{
8455         pic16_emitcode("rl","a");
8456         pic16_emitcode("anl","a,#0x01");
8457         pic16_outAcc(result);
8458     }
8459
8460
8461     pic16_freeAsmop(left,NULL,ic,TRUE);
8462     pic16_freeAsmop(result,NULL,ic,TRUE);
8463 }
8464
8465 #if 0
8466 /*-----------------------------------------------------------------*/
8467 /* AccRol - rotate left accumulator by known count                 */
8468 /*-----------------------------------------------------------------*/
8469 static void AccRol (int shCount)
8470 {
8471     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8472     shCount &= 0x0007;              // shCount : 0..7
8473     switch(shCount){
8474         case 0 :
8475             break;
8476         case 1 :
8477             pic16_emitcode("rl","a");
8478             break;
8479         case 2 :
8480             pic16_emitcode("rl","a");
8481             pic16_emitcode("rl","a");
8482             break;
8483         case 3 :
8484             pic16_emitcode("swap","a");
8485             pic16_emitcode("rr","a");
8486             break;
8487         case 4 :
8488             pic16_emitcode("swap","a");
8489             break;
8490         case 5 :
8491             pic16_emitcode("swap","a");
8492             pic16_emitcode("rl","a");
8493             break;
8494         case 6 :
8495             pic16_emitcode("rr","a");
8496             pic16_emitcode("rr","a");
8497             break;
8498         case 7 :
8499             pic16_emitcode("rr","a");
8500             break;
8501     }
8502 }
8503 #endif
8504
8505 /*-----------------------------------------------------------------*/
8506 /* AccLsh - left shift accumulator by known count                  */
8507 /*-----------------------------------------------------------------*/
8508 static void AccLsh (int shCount, int doMask)
8509 {
8510         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8511         switch(shCount){
8512                 case 0 :
8513                         return;
8514                         break;
8515                 case 1 :
8516                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8517                         break;
8518                 case 2 :
8519                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8520                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8521                         break;
8522                 case 3 :
8523                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8524                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8525                         break;
8526                 case 4 :
8527                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8528                         break;
8529                 case 5 :
8530                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8531                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8532                         break;
8533                 case 6 :
8534                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8535                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8536                         break;
8537                 case 7 :
8538                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8539                         break;
8540         }
8541         if (doMask) {
8542                 /* no masking is required in genPackBits */
8543                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8544         }
8545 }
8546
8547 /*-----------------------------------------------------------------*/
8548 /* AccRsh - right shift accumulator by known count                 */
8549 /*-----------------------------------------------------------------*/
8550 static void AccRsh (int shCount, int andmask)
8551 {
8552         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8553         switch(shCount){
8554                 case 0 :
8555                         return; break;
8556                 case 1 :
8557                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8558                         break;
8559                 case 2 :
8560                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8561                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8562                         break;
8563                 case 3 :
8564                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8565                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566                         break;
8567                 case 4 :
8568                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8569                         break;
8570                 case 5 :
8571                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8572                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8573                         break;
8574                 case 6 :
8575                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8576                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8577                         break;
8578                 case 7 :
8579                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8580                         break;
8581         }
8582         
8583         if(andmask)
8584                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8585         else
8586                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8587 }
8588
8589 #if 0
8590 /*-----------------------------------------------------------------*/
8591 /* AccSRsh - signed right shift accumulator by known count                 */
8592 /*-----------------------------------------------------------------*/
8593 static void AccSRsh (int shCount)
8594 {
8595     symbol *tlbl ;
8596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8597     if(shCount != 0){
8598         if(shCount == 1){
8599             pic16_emitcode("mov","c,acc.7");
8600             pic16_emitcode("rrc","a");
8601         } else if(shCount == 2){
8602             pic16_emitcode("mov","c,acc.7");
8603             pic16_emitcode("rrc","a");
8604             pic16_emitcode("mov","c,acc.7");
8605             pic16_emitcode("rrc","a");
8606         } else {
8607             tlbl = newiTempLabel(NULL);
8608             /* rotate right accumulator */
8609             AccRol(8 - shCount);
8610             /* and kill the higher order bits */
8611             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8612             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8613             pic16_emitcode("orl","a,#0x%02x",
8614                      (unsigned char)~SRMask[shCount]);
8615             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8616         }
8617     }
8618 }
8619 #endif
8620
8621 /*-----------------------------------------------------------------*/
8622 /* shiftR1Left2Result - shift right one byte from left to result   */
8623 /*-----------------------------------------------------------------*/
8624 static void shiftR1Left2ResultSigned (operand *left, int offl,
8625                                 operand *result, int offr,
8626                                 int shCount)
8627 {
8628   int same;
8629
8630   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8631
8632   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8633
8634   switch(shCount) {
8635   case 1:
8636     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8637     if(same) 
8638       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8639     else {
8640       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8641       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8642     }
8643
8644     break;
8645   case 2:
8646
8647     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8648     if(same) 
8649       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8650     else {
8651       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8652       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8653     }
8654     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8655     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8656
8657     break;
8658
8659   case 3:
8660     if(same)
8661       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8662     else {
8663       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8664       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8665     }
8666
8667     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8668     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8669     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8670
8671     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8672     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8673
8674     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8675     break;
8676
8677   case 4:
8678     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8679     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8680     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8681     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8682     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8683     break;
8684   case 5:
8685     if(same) {
8686       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8687     } else {
8688       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8689       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8690     }
8691     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8692     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8693     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8694     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8695     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8696     break;
8697
8698   case 6:
8699     if(same) {
8700       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8701       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8702       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8703       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8704       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8705       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8706     } else {
8707       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8708       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8709       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8710       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8711       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8712     }
8713     break;
8714
8715   case 7:
8716     if(same) {
8717       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8718       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8719       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8720       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8721     } else {
8722       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8723       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8724       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8725     }
8726
8727   default:
8728     break;
8729   }
8730 }
8731
8732 /*-----------------------------------------------------------------*/
8733 /* shiftR1Left2Result - shift right one byte from left to result   */
8734 /*-----------------------------------------------------------------*/
8735 static void shiftR1Left2Result (operand *left, int offl,
8736                                 operand *result, int offr,
8737                                 int shCount, int sign)
8738 {
8739   int same;
8740
8741   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8742
8743   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8744
8745   /* Copy the msb into the carry if signed. */
8746   if(sign) {
8747     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8748     return;
8749   }
8750
8751
8752
8753   switch(shCount) {
8754   case 1:
8755     emitCLRC;
8756     if(same) 
8757       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8758     else {
8759       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8760       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8761     }
8762     break;
8763   case 2:
8764     emitCLRC;
8765     if(same) {
8766       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8767     } else {
8768       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8769       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8770     }
8771     emitCLRC;
8772     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8773
8774     break;
8775   case 3:
8776     if(same)
8777       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8778     else {
8779       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8780       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8781     }
8782
8783     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8784     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8785     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8786     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8787     break;
8788       
8789   case 4:
8790     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8791     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8792     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8793     break;
8794
8795   case 5:
8796     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8797     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8798     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8799     //emitCLRC;
8800     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8801
8802     break;
8803   case 6:
8804
8805     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8806     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8807     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8808     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8809     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8810     break;
8811
8812   case 7:
8813
8814     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8815     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8816     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8817
8818     break;
8819
8820   default:
8821     break;
8822   }
8823 }
8824
8825 /*-----------------------------------------------------------------*/
8826 /* shiftL1Left2Result - shift left one byte from left to result    */
8827 /*-----------------------------------------------------------------*/
8828 static void shiftL1Left2Result (operand *left, int offl,
8829                                 operand *result, int offr, int shCount)
8830 {
8831   int same;
8832
8833   //    char *l;
8834   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8835
8836   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8837   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8838     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8839     //    MOVA(l);
8840     /* shift left accumulator */
8841     //AccLsh(shCount, 1); // don't comment out just yet...
8842   //    pic16_aopPut(AOP(result),"a",offr);
8843
8844   switch(shCount) {
8845   case 1:
8846     /* Shift left 1 bit position */
8847     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8848     if(same) {
8849       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8850     } else {
8851       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8852       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8853     }
8854     break;
8855   case 2:
8856     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8857     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8858     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8859     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8860     break;
8861   case 3:
8862     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8863     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8864     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8865     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8866     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8867     break;
8868   case 4:
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     break;
8873   case 5:
8874     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8875     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8876     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8877     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8878     break;
8879   case 6:
8880     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8881     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8882     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8883     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8884     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8885     break;
8886   case 7:
8887     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8888     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8889     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8890     break;
8891
8892   default:
8893     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8894   }
8895
8896 }
8897
8898 /*-----------------------------------------------------------------*/
8899 /* movLeft2Result - move byte from left to result                  */
8900 /*-----------------------------------------------------------------*/
8901 static void movLeft2Result (operand *left, int offl,
8902                             operand *result, int offr)
8903 {
8904   char *l;
8905   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8906   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8907     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8908
8909     if (*l == '@' && (IS_AOP_PREG(result))) {
8910       pic16_emitcode("mov","a,%s",l);
8911       pic16_aopPut(AOP(result),"a",offr);
8912     } else {
8913       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8914       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8915     }
8916   }
8917 }
8918
8919 /*-----------------------------------------------------------------*/
8920 /* shiftL2Left2Result - shift left two bytes from left to result   */
8921 /*-----------------------------------------------------------------*/
8922 static void shiftL2Left2Result (operand *left, int offl,
8923                                 operand *result, int offr, int shCount)
8924 {
8925   int same = pic16_sameRegs(AOP(result), AOP(left));
8926   int i;
8927
8928   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8929
8930   if (same && (offl != offr)) { // shift bytes
8931     if (offr > offl) {
8932        for(i=1;i>-1;i--) {
8933          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8934          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8935        }
8936     } else { // just treat as different later on
8937                 same = 0;
8938     }
8939   }
8940
8941   if(same) {
8942     switch(shCount) {
8943     case 0:
8944       break;
8945     case 1:
8946     case 2:
8947     case 3:
8948
8949       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8950       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8951       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8952
8953       while(--shCount) {
8954                 emitCLRC;
8955                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8956                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8957       }
8958
8959       break;
8960     case 4:
8961     case 5:
8962       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8963       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8964       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8965       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8966       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8967       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8968       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8969       if(shCount >=5) {
8970                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8971                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8972       }
8973       break;
8974     case 6:
8975       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8976       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8977       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8978       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8979       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8980       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8981       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8982       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8983       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8984       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8985       break;
8986     case 7:
8987       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8988       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8989       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8990       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8991       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8992     }
8993
8994   } else {
8995     switch(shCount) {
8996     case 0:
8997       break;
8998     case 1:
8999     case 2:
9000     case 3:
9001       /* note, use a mov/add for the shift since the mov has a
9002          chance of getting optimized out */
9003       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9004       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9005       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9006       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9007       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9008
9009       while(--shCount) {
9010                 emitCLRC;
9011                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9012                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9013       }
9014       break;
9015
9016     case 4:
9017     case 5:
9018       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9019       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9020       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9021       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9022       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9023       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9024       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9025       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9026
9027
9028       if(shCount == 5) {
9029                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9030                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9031       }
9032       break;
9033     case 6:
9034       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9035       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9036       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9037       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9038
9039       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9040       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9041       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9042       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9043       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9044       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9045       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9046       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9047       break;
9048     case 7:
9049       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9050       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9051       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9052       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9053       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9054     }
9055   }
9056
9057 }
9058 /*-----------------------------------------------------------------*/
9059 /* shiftR2Left2Result - shift right two bytes from left to result  */
9060 /*-----------------------------------------------------------------*/
9061 static void shiftR2Left2Result (operand *left, int offl,
9062                                 operand *result, int offr,
9063                                 int shCount, int sign)
9064 {
9065   int same = pic16_sameRegs(AOP(result), AOP(left));
9066   int i;
9067   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9068
9069   if (same && (offl != offr)) { // shift right bytes
9070     if (offr < offl) {
9071        for(i=0;i<2;i++) {
9072          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9073          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9074        }
9075     } else { // just treat as different later on
9076                 same = 0;
9077     }
9078   }
9079
9080   switch(shCount) {
9081   case 0:
9082     break;
9083   case 1:
9084   case 2:
9085   case 3:
9086     if(sign)
9087       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9088     else
9089       emitCLRC;
9090
9091     if(same) {
9092       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9093       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9094     } else {
9095       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9096       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9097       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9098       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9099     }
9100
9101     while(--shCount) {
9102       if(sign)
9103                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9104       else
9105                 emitCLRC;
9106       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9107       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9108     }
9109     break;
9110   case 4:
9111   case 5:
9112     if(same) {
9113
9114       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9115       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9116       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9117
9118       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9119       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9120       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9121       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9122     } else {
9123       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9124       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9125       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9126
9127       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9128       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9129       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9130       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9131       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9132     }
9133
9134     if(shCount >=5) {
9135       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9136       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9137     }
9138
9139     if(sign) {
9140       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9141       pic16_emitpcode(POC_BTFSC, 
9142                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9143       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9144     }
9145
9146     break;
9147
9148   case 6:
9149     if(same) {
9150
9151       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9152       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9153
9154       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9155       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9156       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9157       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9158       if(sign) {
9159         pic16_emitpcode(POC_BTFSC, 
9160                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9161         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9162       }
9163       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9164       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9165       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9166       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9167     } else {
9168       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9169       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9170       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9171       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9172       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9173       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9174       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9175       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9176       if(sign) {
9177         pic16_emitpcode(POC_BTFSC, 
9178                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9179         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9180       }
9181       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9182       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9183
9184         
9185     }
9186
9187     break;
9188   case 7:
9189     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9190     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9191     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9192     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9193     if(sign) {
9194       emitSKPNC;
9195       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9196     } else 
9197       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9198   }
9199 }
9200
9201
9202 /*-----------------------------------------------------------------*/
9203 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9204 /*-----------------------------------------------------------------*/
9205 static void shiftLLeftOrResult (operand *left, int offl,
9206                                 operand *result, int offr, int shCount)
9207 {
9208     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9209
9210     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9211     /* shift left accumulator */
9212     AccLsh(shCount, 1);
9213     /* or with result */
9214     /* back to result */
9215     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9216 }
9217
9218 /*-----------------------------------------------------------------*/
9219 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9220 /*-----------------------------------------------------------------*/
9221 static void shiftRLeftOrResult (operand *left, int offl,
9222                                 operand *result, int offr, int shCount)
9223 {
9224     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9225     
9226     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9227     /* shift right accumulator */
9228     AccRsh(shCount, 1);
9229     /* or with result */
9230     /* back to result */
9231     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9232 }
9233
9234 /*-----------------------------------------------------------------*/
9235 /* genlshOne - left shift a one byte quantity by known count       */
9236 /*-----------------------------------------------------------------*/
9237 static void genlshOne (operand *result, operand *left, int shCount)
9238 {       
9239     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9240     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9241 }
9242
9243 /*-----------------------------------------------------------------*/
9244 /* genlshTwo - left shift two bytes by known amount != 0           */
9245 /*-----------------------------------------------------------------*/
9246 static void genlshTwo (operand *result,operand *left, int shCount)
9247 {
9248     int size;
9249     
9250     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9251     size = pic16_getDataSize(result);
9252
9253     /* if shCount >= 8 */
9254     if (shCount >= 8) {
9255         shCount -= 8 ;
9256
9257         if (size > 1){
9258             if (shCount)
9259                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9260             else 
9261                 movLeft2Result(left, LSB, result, MSB16);
9262         }
9263         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9264     }
9265
9266     /*  1 <= shCount <= 7 */
9267     else {  
9268         if(size == 1)
9269             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9270         else 
9271             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9272     }
9273 }
9274
9275 /*-----------------------------------------------------------------*/
9276 /* shiftLLong - shift left one long from left to result            */
9277 /* offr = LSB or MSB16                                             */
9278 /*-----------------------------------------------------------------*/
9279 static void shiftLLong (operand *left, operand *result, int offr )
9280 {
9281     int size = AOP_SIZE(result);
9282     int same = pic16_sameRegs(AOP(left),AOP(result));
9283         int i;
9284
9285     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9286
9287         if (same && (offr == MSB16)) { //shift one byte
9288                 for(i=size-1;i>=MSB16;i--) {
9289                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9290                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9291                 }
9292         } else {
9293                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9294         }
9295         
9296     if (size > LSB+offr ){
9297                 if (same) {
9298                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9299                 } else {
9300                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9301                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9302                 }
9303          }
9304
9305     if(size > MSB16+offr){
9306                 if (same) {
9307                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9308                 } else {
9309                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9310                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9311                 }
9312     }
9313
9314     if(size > MSB24+offr){
9315                 if (same) {
9316                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9317                 } else {
9318                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9319                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9320                 }
9321     }
9322
9323     if(size > MSB32+offr){
9324                 if (same) {
9325                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9326                 } else {
9327                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9328                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9329                 }
9330     }
9331     if(offr != LSB)
9332                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9333
9334 }
9335
9336 /*-----------------------------------------------------------------*/
9337 /* genlshFour - shift four byte by a known amount != 0             */
9338 /*-----------------------------------------------------------------*/
9339 static void genlshFour (operand *result, operand *left, int shCount)
9340 {
9341     int size;
9342
9343     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9344     size = AOP_SIZE(result);
9345
9346     /* if shifting more that 3 bytes */
9347     if (shCount >= 24 ) {
9348         shCount -= 24;
9349         if (shCount)
9350             /* lowest order of left goes to the highest
9351             order of the destination */
9352             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9353         else
9354             movLeft2Result(left, LSB, result, MSB32);
9355
9356                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9357                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9358                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9359
9360         return;
9361     }
9362
9363     /* more than two bytes */
9364     else if ( shCount >= 16 ) {
9365         /* lower order two bytes goes to higher order two bytes */
9366         shCount -= 16;
9367         /* if some more remaining */
9368         if (shCount)
9369             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9370         else {
9371             movLeft2Result(left, MSB16, result, MSB32);
9372             movLeft2Result(left, LSB, result, MSB24);
9373         }
9374                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9375                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9376         return;
9377     }    
9378
9379     /* if more than 1 byte */
9380     else if ( shCount >= 8 ) {
9381         /* lower order three bytes goes to higher order  three bytes */
9382         shCount -= 8;
9383         if(size == 2){
9384             if(shCount)
9385                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9386             else
9387                 movLeft2Result(left, LSB, result, MSB16);
9388         }
9389         else{   /* size = 4 */
9390             if(shCount == 0){
9391                 movLeft2Result(left, MSB24, result, MSB32);
9392                 movLeft2Result(left, MSB16, result, MSB24);
9393                 movLeft2Result(left, LSB, result, MSB16);
9394                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9395             }
9396             else if(shCount == 1)
9397                 shiftLLong(left, result, MSB16);
9398             else{
9399                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9400                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9401                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9402                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9403             }
9404         }
9405     }
9406
9407     /* 1 <= shCount <= 7 */
9408     else if(shCount <= 3)
9409     { 
9410         shiftLLong(left, result, LSB);
9411         while(--shCount >= 1)
9412             shiftLLong(result, result, LSB);
9413     }
9414     /* 3 <= shCount <= 7, optimize */
9415     else{
9416         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9417         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9418         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9419     }
9420 }
9421
9422 /*-----------------------------------------------------------------*/
9423 /* genLeftShiftLiteral - left shifting by known count              */
9424 /*-----------------------------------------------------------------*/
9425 void pic16_genLeftShiftLiteral (operand *left,
9426                                  operand *right,
9427                                  operand *result,
9428                                  iCode *ic)
9429 {    
9430     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9431     int size;
9432
9433     FENTRY;
9434     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9435     pic16_freeAsmop(right,NULL,ic,TRUE);
9436
9437     pic16_aopOp(left,ic,FALSE);
9438     pic16_aopOp(result,ic,TRUE);
9439
9440     size = getSize(operandType(result));
9441
9442 #if VIEW_SIZE
9443     pic16_emitcode("; shift left ","result %d, left %d",size,
9444              AOP_SIZE(left));
9445 #endif
9446
9447     /* I suppose that the left size >= result size */
9448     if(shCount == 0){
9449         while(size--){
9450             movLeft2Result(left, size, result, size);
9451         }
9452     }
9453
9454     else if(shCount >= (size * 8))
9455         while(size--)
9456             pic16_aopPut(AOP(result),zero,size);
9457     else{
9458         switch (size) {
9459             case 1:
9460                 genlshOne (result,left,shCount);
9461                 break;
9462
9463             case 2:
9464             case 3:
9465                 genlshTwo (result,left,shCount);
9466                 break;
9467
9468             case 4:
9469                 genlshFour (result,left,shCount);
9470                 break;
9471         }
9472     }
9473     pic16_freeAsmop(left,NULL,ic,TRUE);
9474     pic16_freeAsmop(result,NULL,ic,TRUE);
9475 }
9476
9477 /*-----------------------------------------------------------------*
9478  * genMultiAsm - repeat assembly instruction for size of register.
9479  * if endian == 1, then the high byte (i.e base address + size of 
9480  * register) is used first else the low byte is used first;
9481  *-----------------------------------------------------------------*/
9482 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9483 {
9484
9485   int offset = 0;
9486
9487   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9488
9489   if(!reg)
9490     return;
9491
9492   if(!endian) {
9493     endian = 1;
9494   } else {
9495     endian = -1;
9496     offset = size-1;
9497   }
9498
9499   while(size--) {
9500     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9501     offset += endian;
9502   }
9503
9504 }
9505
9506 #if !(USE_GENERIC_SIGNED_SHIFT)
9507 /*-----------------------------------------------------------------*/
9508 /* genLeftShift - generates code for left shifting                 */
9509 /*-----------------------------------------------------------------*/
9510 static void genLeftShift (iCode *ic)
9511 {
9512   operand *left,*right, *result;
9513   int size, offset;
9514 //  char *l;
9515   symbol *tlbl , *tlbl1;
9516   pCodeOp *pctemp;
9517
9518   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9519
9520   right = IC_RIGHT(ic);
9521   left  = IC_LEFT(ic);
9522   result = IC_RESULT(ic);
9523
9524   pic16_aopOp(right,ic,FALSE);
9525
9526   /* if the shift count is known then do it 
9527      as efficiently as possible */
9528   if (AOP_TYPE(right) == AOP_LIT) {
9529     pic16_genLeftShiftLiteral (left,right,result,ic);
9530     return ;
9531   }
9532
9533   /* shift count is unknown then we have to form
9534    * a loop. Get the loop count in WREG : Note: we take
9535    * only the lower order byte since shifting
9536    * more than 32 bits make no sense anyway, ( the
9537    * largest size of an object can be only 32 bits ) */
9538   
9539   pic16_aopOp(left,ic,FALSE);
9540   pic16_aopOp(result,ic,FALSE);
9541
9542   /* now move the left to the result if they are not the
9543    * same, and if size > 1,
9544    * and if right is not same to result (!!!) -- VR */
9545   if (!pic16_sameRegs(AOP(left),AOP(result))
9546       && (AOP_SIZE(result) > 1)) {
9547
9548     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9549
9550     size = AOP_SIZE(result);
9551     offset=0;
9552     while (size--) {
9553
9554 #if 0
9555       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9556       if (*l == '@' && (IS_AOP_PREG(result))) {
9557
9558           pic16_emitcode("mov","a,%s",l);
9559           pic16_aopPut(AOP(result),"a",offset);
9560       } else
9561 #endif
9562       {
9563         /* we don't know if left is a literal or a register, take care -- VR */
9564         pic16_mov2f(AOP(result), AOP(left), offset);
9565       }
9566       offset++;
9567     }
9568   }
9569
9570   size = AOP_SIZE(result);
9571
9572   /* if it is only one byte then */
9573   if (size == 1) {
9574     if(optimized_for_speed) {
9575       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9576       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9577       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9578       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9579       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9580       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9581       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9582       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9583       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9584       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9585       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9586       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9587     } else {
9588
9589       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9590
9591       tlbl = newiTempLabel(NULL);
9592
9593 #if 1
9594       /* this is already done, why change it? */
9595       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9596                 pic16_mov2f(AOP(result), AOP(left), 0);
9597       }
9598 #endif
9599
9600       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9601       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9602       pic16_emitpLabel(tlbl->key);
9603       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9604       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9605       emitSKPC;
9606       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9607     }
9608     goto release ;
9609   }
9610     
9611   if (pic16_sameRegs(AOP(left),AOP(result))) {
9612
9613     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9614     
9615     tlbl = newiTempLabel(NULL);
9616     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9617     genMultiAsm(POC_RRCF, result, size,1);
9618     pic16_emitpLabel(tlbl->key);
9619     genMultiAsm(POC_RLCF, result, size,0);
9620     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9621     emitSKPC;
9622     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9623     goto release;
9624   }
9625
9626   //tlbl = newiTempLabel(NULL);
9627   //offset = 0 ;   
9628   //tlbl1 = newiTempLabel(NULL);
9629
9630   //reAdjustPreg(AOP(result));    
9631     
9632   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9633   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9634   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9635   //MOVA(l);
9636   //pic16_emitcode("add","a,acc");         
9637   //pic16_aopPut(AOP(result),"a",offset++);
9638   //while (--size) {
9639   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9640   //  MOVA(l);
9641   //  pic16_emitcode("rlc","a");         
9642   //  pic16_aopPut(AOP(result),"a",offset++);
9643   //}
9644   //reAdjustPreg(AOP(result));
9645
9646   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9647   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9648
9649
9650   tlbl = newiTempLabel(NULL);
9651   tlbl1= newiTempLabel(NULL);
9652
9653   size = AOP_SIZE(result);
9654   offset = 1;
9655
9656   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9657
9658   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9659
9660   /* offset should be 0, 1 or 3 */
9661   
9662   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9663   emitSKPNZ;
9664   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9665
9666   pic16_emitpcode(POC_MOVWF, pctemp);
9667
9668
9669   pic16_emitpLabel(tlbl->key);
9670
9671   emitCLRC;
9672   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9673   while(--size)
9674     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9675
9676   pic16_emitpcode(POC_DECFSZ,  pctemp);
9677   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9678   pic16_emitpLabel(tlbl1->key);
9679
9680   pic16_popReleaseTempReg(pctemp,1);
9681
9682
9683  release:
9684   pic16_freeAsmop (right,NULL,ic,TRUE);
9685   pic16_freeAsmop(left,NULL,ic,TRUE);
9686   pic16_freeAsmop(result,NULL,ic,TRUE);
9687 }
9688 #endif
9689
9690
9691 #if 0
9692 #error old code (left here for reference)
9693 /*-----------------------------------------------------------------*/
9694 /* genLeftShift - generates code for left shifting                 */
9695 /*-----------------------------------------------------------------*/
9696 static void genLeftShift (iCode *ic)
9697 {
9698   operand *left,*right, *result;
9699   int size, offset;
9700   char *l;
9701   symbol *tlbl , *tlbl1;
9702   pCodeOp *pctemp;
9703
9704   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9705
9706   right = IC_RIGHT(ic);
9707   left  = IC_LEFT(ic);
9708   result = IC_RESULT(ic);
9709
9710   pic16_aopOp(right,ic,FALSE);
9711
9712   /* if the shift count is known then do it 
9713      as efficiently as possible */
9714   if (AOP_TYPE(right) == AOP_LIT) {
9715     pic16_genLeftShiftLiteral (left,right,result,ic);
9716     return ;
9717   }
9718
9719   /* shift count is unknown then we have to form 
9720      a loop get the loop count in B : Note: we take
9721      only the lower order byte since shifting
9722      more that 32 bits make no sense anyway, ( the
9723      largest size of an object can be only 32 bits ) */  
9724
9725     
9726   pic16_aopOp(left,ic,FALSE);
9727   pic16_aopOp(result,ic,FALSE);
9728
9729   /* now move the left to the result if they are not the
9730      same */
9731   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9732       AOP_SIZE(result) > 1) {
9733
9734     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9735
9736     size = AOP_SIZE(result);
9737     offset=0;
9738     while (size--) {
9739       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9740       if (*l == '@' && (IS_AOP_PREG(result))) {
9741
9742         pic16_emitcode("mov","a,%s",l);
9743         pic16_aopPut(AOP(result),"a",offset);
9744       } else {
9745
9746         /* we don't know if left is a literal or a register, take care -- VR */
9747         pic16_mov2f(AOP(result), AOP(left), offset);
9748       }
9749       offset++;
9750     }
9751   }
9752
9753   size = AOP_SIZE(result);
9754
9755   /* if it is only one byte then */
9756   if (size == 1) {
9757     if(optimized_for_speed) {
9758       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9759       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9760       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9761       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9762       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9763       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9764       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9765       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9766       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9767       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9768       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9769       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9770     } else {
9771
9772       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9773
9774       tlbl = newiTempLabel(NULL);
9775       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9776                 pic16_mov2f(AOP(result), AOP(left), 0);
9777                 
9778 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9779 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9780       }
9781
9782       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9783       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9784       pic16_emitpLabel(tlbl->key);
9785       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9786       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9787       emitSKPC;
9788       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9789     }
9790     goto release ;
9791   }
9792     
9793   if (pic16_sameRegs(AOP(left),AOP(result))) {
9794
9795     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9796     
9797     tlbl = newiTempLabel(NULL);
9798     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9799     genMultiAsm(POC_RRCF, result, size,1);
9800     pic16_emitpLabel(tlbl->key);
9801     genMultiAsm(POC_RLCF, result, size,0);
9802     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9803     emitSKPC;
9804     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9805     goto release;
9806   }
9807
9808   //tlbl = newiTempLabel(NULL);
9809   //offset = 0 ;   
9810   //tlbl1 = newiTempLabel(NULL);
9811
9812   //reAdjustPreg(AOP(result));    
9813     
9814   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9815   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9816   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9817   //MOVA(l);
9818   //pic16_emitcode("add","a,acc");         
9819   //pic16_aopPut(AOP(result),"a",offset++);
9820   //while (--size) {
9821   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9822   //  MOVA(l);
9823   //  pic16_emitcode("rlc","a");         
9824   //  pic16_aopPut(AOP(result),"a",offset++);
9825   //}
9826   //reAdjustPreg(AOP(result));
9827
9828   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9829   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9830
9831
9832   tlbl = newiTempLabel(NULL);
9833   tlbl1= newiTempLabel(NULL);
9834
9835   size = AOP_SIZE(result);
9836   offset = 1;
9837
9838   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9839
9840   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9841
9842   /* offset should be 0, 1 or 3 */
9843   
9844   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9845   emitSKPNZ;
9846   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9847
9848   pic16_emitpcode(POC_MOVWF, pctemp);
9849
9850
9851   pic16_emitpLabel(tlbl->key);
9852
9853   emitCLRC;
9854   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9855   while(--size)
9856     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9857
9858   pic16_emitpcode(POC_DECFSZ,  pctemp);
9859   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9860   pic16_emitpLabel(tlbl1->key);
9861
9862   pic16_popReleaseTempReg(pctemp,1);
9863
9864
9865  release:
9866   pic16_freeAsmop (right,NULL,ic,TRUE);
9867   pic16_freeAsmop(left,NULL,ic,TRUE);
9868   pic16_freeAsmop(result,NULL,ic,TRUE);
9869 }
9870 #endif
9871
9872 /*-----------------------------------------------------------------*/
9873 /* genrshOne - right shift a one byte quantity by known count      */
9874 /*-----------------------------------------------------------------*/
9875 static void genrshOne (operand *result, operand *left,
9876                        int shCount, int sign)
9877 {
9878     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9879     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9880 }
9881
9882 /*-----------------------------------------------------------------*/
9883 /* genrshTwo - right shift two bytes by known amount != 0          */
9884 /*-----------------------------------------------------------------*/
9885 static void genrshTwo (operand *result,operand *left,
9886                        int shCount, int sign)
9887 {
9888   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9889   /* if shCount >= 8 */
9890   if (shCount >= 8) {
9891     shCount -= 8 ;
9892     if (shCount)
9893       shiftR1Left2Result(left, MSB16, result, LSB,
9894                          shCount, sign);
9895     else
9896       movLeft2Result(left, MSB16, result, LSB);
9897
9898     pic16_addSign (result, 1, sign);
9899   }
9900
9901   /*  1 <= shCount <= 7 */
9902   else
9903     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9904 }
9905
9906 /*-----------------------------------------------------------------*/
9907 /* shiftRLong - shift right one long from left to result           */
9908 /* offl = LSB or MSB16                                             */
9909 /*-----------------------------------------------------------------*/
9910 static void shiftRLong (operand *left, int offl,
9911                         operand *result, int sign)
9912 {
9913     int size = AOP_SIZE(result);
9914     int same = pic16_sameRegs(AOP(left),AOP(result));
9915     int i;
9916     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9917
9918         if (same && (offl == MSB16)) { //shift one byte right
9919                 for(i=MSB16;i<size;i++) {
9920                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9921                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9922                 }
9923         }
9924
9925     if(sign)
9926                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9927         else
9928                 emitCLRC;
9929
9930         if (same) {
9931                 if (offl == LSB)
9932                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9933         } else {
9934         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9935         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9936         }
9937
9938     if(offl == MSB16) {
9939         /* add sign of "a" */
9940         pic16_addSign(result, MSB32, sign);
9941         }
9942
9943         if (same) {
9944         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9945         } else {
9946         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9947         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9948         }
9949         
9950         if (same) {
9951         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9952         } else {
9953         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9954         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9955         }
9956
9957         if (same) {
9958         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9959         } else {
9960         if(offl == LSB){
9961                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9962                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9963         }
9964         }
9965 }
9966
9967 /*-----------------------------------------------------------------*/
9968 /* genrshFour - shift four byte by a known amount != 0             */
9969 /*-----------------------------------------------------------------*/
9970 static void genrshFour (operand *result, operand *left,
9971                         int shCount, int sign)
9972 {
9973   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9974   /* if shifting more that 3 bytes */
9975   if(shCount >= 24 ) {
9976     shCount -= 24;
9977     if(shCount)
9978       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9979     else
9980       movLeft2Result(left, MSB32, result, LSB);
9981
9982     pic16_addSign(result, MSB16, sign);
9983   }
9984   else if(shCount >= 16){
9985     shCount -= 16;
9986     if(shCount)
9987       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9988     else{
9989       movLeft2Result(left, MSB24, result, LSB);
9990       movLeft2Result(left, MSB32, result, MSB16);
9991     }
9992     pic16_addSign(result, MSB24, sign);
9993   }
9994   else if(shCount >= 8){
9995     shCount -= 8;
9996     if(shCount == 1)
9997       shiftRLong(left, MSB16, result, sign);
9998     else if(shCount == 0){
9999       movLeft2Result(left, MSB16, result, LSB);
10000       movLeft2Result(left, MSB24, result, MSB16);
10001       movLeft2Result(left, MSB32, result, MSB24);
10002       pic16_addSign(result, MSB32, sign);
10003     }
10004     else{ //shcount >= 2
10005       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10006       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10007       /* the last shift is signed */
10008       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10009       pic16_addSign(result, MSB32, sign);
10010     }
10011   }
10012   else{   /* 1 <= shCount <= 7 */
10013     if(shCount <= 2){
10014       shiftRLong(left, LSB, result, sign);
10015       if(shCount == 2)
10016         shiftRLong(result, LSB, result, sign);
10017     }
10018     else{
10019       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10020       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10021       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10022     }
10023   }
10024 }
10025
10026 /*-----------------------------------------------------------------*/
10027 /* genRightShiftLiteral - right shifting by known count            */
10028 /*-----------------------------------------------------------------*/
10029 static void genRightShiftLiteral (operand *left,
10030                                   operand *right,
10031                                   operand *result,
10032                                   iCode *ic,
10033                                   int sign)
10034 {    
10035   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10036   int lsize,res_size;
10037
10038   pic16_freeAsmop(right,NULL,ic,TRUE);
10039
10040   pic16_aopOp(left,ic,FALSE);
10041   pic16_aopOp(result,ic,TRUE);
10042
10043   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10044
10045 #if VIEW_SIZE
10046   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10047                  AOP_SIZE(left));
10048 #endif
10049
10050   lsize = pic16_getDataSize(left);
10051   res_size = pic16_getDataSize(result);
10052   /* test the LEFT size !!! */
10053
10054   /* I suppose that the left size >= result size */
10055   if(shCount == 0){
10056     assert (res_size <= lsize);
10057     while (res_size--) {
10058       pic16_mov2f (AOP(result), AOP(left), res_size);
10059     } // for
10060   }
10061
10062   else if(shCount >= (lsize * 8)){
10063
10064     if(res_size == 1) {
10065       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10066       if(sign) {
10067         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10068         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10069       }
10070     } else {
10071
10072       if(sign) {
10073         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10074         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10075         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10076         while(res_size--)
10077           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10078
10079       } else {
10080
10081         while(res_size--)
10082           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10083       }
10084     }
10085   } else {
10086
10087     switch (res_size) {
10088     case 1:
10089       genrshOne (result,left,shCount,sign);
10090       break;
10091
10092     case 2:
10093       genrshTwo (result,left,shCount,sign);
10094       break;
10095
10096     case 4:
10097       genrshFour (result,left,shCount,sign);
10098       break;
10099     default :
10100       break;
10101     }
10102
10103   }
10104
10105   pic16_freeAsmop(left,NULL,ic,TRUE);
10106   pic16_freeAsmop(result,NULL,ic,TRUE);
10107 }
10108
10109 #if !(USE_GENERIC_SIGNED_SHIFT)
10110 /*-----------------------------------------------------------------*/
10111 /* genSignedRightShift - right shift of signed number              */
10112 /*-----------------------------------------------------------------*/
10113 static void genSignedRightShift (iCode *ic)
10114 {
10115   operand *right, *left, *result;
10116   int size, offset;
10117   //  char *l;
10118   symbol *tlbl, *tlbl1 ;
10119   pCodeOp *pctemp;
10120
10121   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10122
10123   /* we do it the hard way put the shift count in b
10124      and loop thru preserving the sign */
10125   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10126
10127   right = IC_RIGHT(ic);
10128   left  = IC_LEFT(ic);
10129   result = IC_RESULT(ic);
10130
10131   pic16_aopOp(right,ic,FALSE);  
10132   pic16_aopOp(left,ic,FALSE);
10133   pic16_aopOp(result,ic,FALSE);
10134
10135
10136   if ( AOP_TYPE(right) == AOP_LIT) {
10137     genRightShiftLiteral (left,right,result,ic,1);
10138     return ;
10139   }
10140   /* shift count is unknown then we have to form 
10141      a loop get the loop count in B : Note: we take
10142      only the lower order byte since shifting
10143      more that 32 bits make no sense anyway, ( the
10144      largest size of an object can be only 32 bits ) */  
10145
10146   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10147   //pic16_emitcode("inc","b");
10148   //pic16_freeAsmop (right,NULL,ic,TRUE);
10149   //pic16_aopOp(left,ic,FALSE);
10150   //pic16_aopOp(result,ic,FALSE);
10151
10152   /* now move the left to the result if they are not the
10153      same */
10154   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10155       AOP_SIZE(result) > 1) {
10156
10157     size = AOP_SIZE(result);
10158     offset=0;
10159     while (size--) { 
10160       /*
10161         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10162         if (*l == '@' && IS_AOP_PREG(result)) {
10163
10164         pic16_emitcode("mov","a,%s",l);
10165         pic16_aopPut(AOP(result),"a",offset);
10166         } else
10167         pic16_aopPut(AOP(result),l,offset);
10168       */
10169       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10170       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10171
10172       offset++;
10173     }
10174   }
10175
10176   /* mov the highest order bit to OVR */    
10177   tlbl = newiTempLabel(NULL);
10178   tlbl1= newiTempLabel(NULL);
10179
10180   size = AOP_SIZE(result);
10181   offset = size - 1;
10182
10183   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10184
10185   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10186
10187   /* offset should be 0, 1 or 3 */
10188   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10189   emitSKPNZ;
10190   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10191
10192   pic16_emitpcode(POC_MOVWF, pctemp);
10193
10194
10195   pic16_emitpLabel(tlbl->key);
10196
10197   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10198   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10199
10200   while(--size) {
10201     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10202   }
10203
10204   pic16_emitpcode(POC_DECFSZ,  pctemp);
10205   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10206   pic16_emitpLabel(tlbl1->key);
10207
10208   pic16_popReleaseTempReg(pctemp,1);
10209 #if 0
10210   size = AOP_SIZE(result);
10211   offset = size - 1;
10212   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10213   pic16_emitcode("rlc","a");
10214   pic16_emitcode("mov","ov,c");
10215   /* if it is only one byte then */
10216   if (size == 1) {
10217     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10218     MOVA(l);
10219     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10220     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10221     pic16_emitcode("mov","c,ov");
10222     pic16_emitcode("rrc","a");
10223     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10224     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10225     pic16_aopPut(AOP(result),"a",0);
10226     goto release ;
10227   }
10228
10229   reAdjustPreg(AOP(result));
10230   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10231   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10232   pic16_emitcode("mov","c,ov");
10233   while (size--) {
10234     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10235     MOVA(l);
10236     pic16_emitcode("rrc","a");         
10237     pic16_aopPut(AOP(result),"a",offset--);
10238   }
10239   reAdjustPreg(AOP(result));
10240   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10241   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10242
10243  release:
10244 #endif
10245
10246   pic16_freeAsmop(left,NULL,ic,TRUE);
10247   pic16_freeAsmop(result,NULL,ic,TRUE);
10248   pic16_freeAsmop(right,NULL,ic,TRUE);
10249 }
10250 #endif
10251
10252 #if !(USE_GENERIC_SIGNED_SHIFT)
10253 #warning This implementation of genRightShift() is incomplete!
10254 /*-----------------------------------------------------------------*/
10255 /* genRightShift - generate code for right shifting                */
10256 /*-----------------------------------------------------------------*/
10257 static void genRightShift (iCode *ic)
10258 {
10259     operand *right, *left, *result;
10260     sym_link *letype ;
10261     int size, offset;
10262     char *l;
10263     symbol *tlbl, *tlbl1 ;
10264
10265     /* if signed then we do it the hard way preserve the
10266     sign bit moving it inwards */
10267     letype = getSpec(operandType(IC_LEFT(ic)));
10268     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10269
10270     if (!SPEC_USIGN(letype)) {
10271         genSignedRightShift (ic);
10272         return ;
10273     }
10274
10275     /* signed & unsigned types are treated the same : i.e. the
10276     signed is NOT propagated inwards : quoting from the
10277     ANSI - standard : "for E1 >> E2, is equivalent to division
10278     by 2**E2 if unsigned or if it has a non-negative value,
10279     otherwise the result is implementation defined ", MY definition
10280     is that the sign does not get propagated */
10281
10282     right = IC_RIGHT(ic);
10283     left  = IC_LEFT(ic);
10284     result = IC_RESULT(ic);
10285
10286     pic16_aopOp(right,ic,FALSE);
10287
10288     /* if the shift count is known then do it 
10289     as efficiently as possible */
10290     if (AOP_TYPE(right) == AOP_LIT) {
10291         genRightShiftLiteral (left,right,result,ic, 0);
10292         return ;
10293     }
10294
10295     /* shift count is unknown then we have to form 
10296     a loop get the loop count in B : Note: we take
10297     only the lower order byte since shifting
10298     more that 32 bits make no sense anyway, ( the
10299     largest size of an object can be only 32 bits ) */  
10300
10301     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10302     pic16_emitcode("inc","b");
10303     pic16_aopOp(left,ic,FALSE);
10304     pic16_aopOp(result,ic,FALSE);
10305
10306     /* now move the left to the result if they are not the
10307     same */
10308     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10309         AOP_SIZE(result) > 1) {
10310
10311         size = AOP_SIZE(result);
10312         offset=0;
10313         while (size--) {
10314             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10315             if (*l == '@' && IS_AOP_PREG(result)) {
10316
10317                 pic16_emitcode("mov","a,%s",l);
10318                 pic16_aopPut(AOP(result),"a",offset);
10319             } else
10320                 pic16_aopPut(AOP(result),l,offset);
10321             offset++;
10322         }
10323     }
10324
10325     tlbl = newiTempLabel(NULL);
10326     tlbl1= newiTempLabel(NULL);
10327     size = AOP_SIZE(result);
10328     offset = size - 1;
10329
10330     /* if it is only one byte then */
10331     if (size == 1) {
10332
10333       tlbl = newiTempLabel(NULL);
10334       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10335         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10336         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10337       }
10338
10339       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10340       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10341       pic16_emitpLabel(tlbl->key);
10342       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10343       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10344       emitSKPC;
10345       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10346
10347       goto release ;
10348     }
10349
10350     reAdjustPreg(AOP(result));
10351     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10352     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10353     CLRC;
10354     while (size--) {
10355         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10356         MOVA(l);
10357         pic16_emitcode("rrc","a");         
10358         pic16_aopPut(AOP(result),"a",offset--);
10359     }
10360     reAdjustPreg(AOP(result));
10361
10362     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10363     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10364
10365 release:
10366     pic16_freeAsmop(left,NULL,ic,TRUE);
10367     pic16_freeAsmop (right,NULL,ic,TRUE);
10368     pic16_freeAsmop(result,NULL,ic,TRUE);
10369 }
10370 #endif
10371
10372 #if (USE_GENERIC_SIGNED_SHIFT)
10373 /*-----------------------------------------------------------------*/
10374 /* genGenericShift - generates code for left or right shifting     */
10375 /*-----------------------------------------------------------------*/
10376 static void genGenericShift (iCode *ic, int isShiftLeft) {
10377   operand *left,*right, *result;
10378   int offset;
10379   int sign, signedCount;
10380   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10381   PIC_OPCODE pos_shift, neg_shift;
10382
10383   FENTRY;
10384
10385   right = IC_RIGHT(ic);
10386   left  = IC_LEFT(ic);
10387   result = IC_RESULT(ic);
10388
10389   pic16_aopOp(right,ic,FALSE);
10390   pic16_aopOp(left,ic,FALSE);
10391   pic16_aopOp(result,ic,TRUE);
10392
10393   sign = !SPEC_USIGN(operandType (left));
10394   signedCount = !SPEC_USIGN(operandType (right));
10395
10396   /* if the shift count is known then do it 
10397      as efficiently as possible */
10398   if (AOP_TYPE(right) == AOP_LIT) {
10399     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10400     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10401     // we should modify right->aopu.aop_lit here!
10402     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10403     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10404     if (isShiftLeft)
10405       pic16_genLeftShiftLiteral (left,right,result,ic);
10406     else
10407       genRightShiftLiteral (left,right,result,ic, sign);
10408
10409     goto release;
10410   } // if (right is literal)
10411
10412   /* shift count is unknown then we have to form a loop.
10413    * Note: we take only the lower order byte since shifting
10414    * more than 32 bits make no sense anyway, ( the
10415    * largest size of an object can be only 32 bits )
10416    * Note: we perform arithmetic shifts if the left operand is
10417    * signed and we do an (effective) right shift, i. e. we
10418    * shift in the sign bit from the left. */
10419    
10420   label_complete = newiTempLabel ( NULL );
10421   label_loop_pos = newiTempLabel ( NULL );
10422   label_loop_neg = NULL;
10423   label_negative = NULL;
10424   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10425   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10426
10427   if (signedCount) {
10428     // additional labels needed
10429     label_loop_neg = newiTempLabel ( NULL );
10430     label_negative = newiTempLabel ( NULL );
10431   } // if
10432
10433   // copy source to result -- this will effectively truncate the left operand to the size of result!
10434   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10435   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10436   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10437     pic16_mov2f (AOP(result),AOP(left), offset);
10438   } // for
10439
10440   // if result is longer than left, fill with zeros (or sign)
10441   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10442     if (sign && AOP_SIZE(left) > 0) {
10443       // shift signed operand -- fill with sign
10444       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10445       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10446       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10447       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10448         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10449       } // for
10450     } else {
10451       // shift unsigned operand -- fill result with zeros
10452       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10453         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10454       } // for
10455     }
10456   } // if (size mismatch)
10457
10458   pic16_mov2w (AOP(right), 0);
10459   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10460   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10461   
10462 #if 0
10463   // perform a shift by one (shift count is positive)
10464   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10465   // 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])
10466   pic16_emitpLabel (label_loop_pos->key);
10467   emitCLRC;
10468   if (sign && (pos_shift == POC_RRCF)) {
10469     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10470     emitSETC;
10471   } // if
10472   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10473   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10474   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10475 #else
10476   // perform a shift by one (shift count is positive)
10477   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10478   // 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])
10479   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10480   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10481   emitCLRC;
10482   pic16_emitpLabel (label_loop_pos->key);
10483   if (sign && (pos_shift == POC_RRCF)) {
10484     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10485     emitSETC;
10486   } // if
10487   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10488   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10489   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10490   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10491 #endif
10492
10493   if (signedCount) {
10494     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10495
10496     pic16_emitpLabel (label_negative->key);
10497     // perform a shift by -1 (shift count is negative)
10498     // 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)
10499     emitCLRC;
10500     pic16_emitpLabel (label_loop_neg->key);
10501     if (sign && (neg_shift == POC_RRCF)) {
10502       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10503       emitSETC;
10504     } // if
10505     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10506     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10507     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10508     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10509   } // if (signedCount)
10510
10511   pic16_emitpLabel (label_complete->key);
10512
10513 release:
10514   pic16_freeAsmop (right,NULL,ic,TRUE);
10515   pic16_freeAsmop(left,NULL,ic,TRUE);
10516   pic16_freeAsmop(result,NULL,ic,TRUE);
10517 }
10518
10519 static void genLeftShift (iCode *ic) {
10520   genGenericShift (ic, 1);
10521 }
10522
10523 static void genRightShift (iCode *ic) {
10524   genGenericShift (ic, 0);
10525 }
10526 #endif
10527
10528
10529 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10530 void pic16_loadFSR0(operand *op, int lit)
10531 {
10532   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10533     if (AOP_TYPE(op) == AOP_LIT) {
10534       /* handle 12 bit integers correctly */
10535       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10536       if ((val & 0x0fff) != val) {
10537         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10538                 val, (val & 0x0fff) );
10539         val &= 0x0fff;
10540       }
10541       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10542     } else {
10543       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10544     }
10545   } else {
10546     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10547     // set up FSR0 with address of result
10548     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10549     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10550   }
10551 }
10552
10553 /*----------------------------------------------------------------*/
10554 /* pic16_derefPtr - move one byte from the location ptr points to */
10555 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10556 /*                  to the location ptr points to (doWrite != 0)   */
10557 /*----------------------------------------------------------------*/
10558 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10559 {
10560   if (!IS_PTR(operandType(ptr)))
10561   {
10562     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10563     else pic16_mov2w (AOP(ptr), 0);
10564     return;
10565   }
10566
10567   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10568   /* We might determine pointer type right here: */
10569   p_type = DCL_TYPE(operandType(ptr));
10570
10571   switch (p_type) {
10572     case FPOINTER:
10573     case POINTER:
10574       if (!fsr0_setup || !*fsr0_setup)
10575       {
10576         pic16_loadFSR0( ptr, 0 );
10577         if (fsr0_setup) *fsr0_setup = 1;
10578       }
10579       if (doWrite)
10580         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10581       else
10582         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10583       break;
10584
10585     case GPOINTER:
10586       if (AOP(ptr)->aopu.aop_reg[2]) {
10587         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10588         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10589         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10590         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10591         pic16_mov2w(AOP(ptr), 2);
10592         pic16_callGenericPointerRW(doWrite, 1);
10593       } else {
10594         // data pointer (just 2 byte given)
10595         if (!fsr0_setup || !*fsr0_setup)
10596         {
10597           pic16_loadFSR0( ptr, 0 );
10598           if (fsr0_setup) *fsr0_setup = 1;
10599         }
10600         if (doWrite)
10601           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10602         else
10603           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10604       }
10605       break;
10606
10607     default:
10608       assert (0 && "invalid pointer type specified");
10609       break;
10610   }
10611 }
10612
10613 /*-----------------------------------------------------------------*/
10614 /* genUnpackBits - generates code for unpacking bits               */
10615 /*-----------------------------------------------------------------*/
10616 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10617 {    
10618   int shCnt ;
10619   sym_link *etype, *letype;
10620   int blen=0, bstr=0;
10621   int lbstr;
10622   int same;
10623   pCodeOp *op;
10624
10625   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10626   etype = getSpec(operandType(result));
10627   letype = getSpec(operandType(left));
10628
10629   //    if(IS_BITFIELD(etype)) {
10630   blen = SPEC_BLEN(etype);
10631   bstr = SPEC_BSTR(etype);
10632   //    }
10633
10634   lbstr = SPEC_BSTR( letype );
10635
10636   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10637       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10638
10639 #if 1
10640   if((blen == 1) && (bstr < 8)
10641       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10642     /* it is a single bit, so use the appropriate bit instructions */
10643     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10644
10645     same = pic16_sameRegs(AOP(left),AOP(result));
10646     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10647     pic16_emitpcode(POC_CLRF, op);
10648
10649     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10650       /* workaround to reduce the extra lfsr instruction */
10651       pic16_emitpcode(POC_BTFSC,
10652           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10653     } else {
10654       assert (PIC_IS_DATA_PTR (operandType(left)));
10655       pic16_loadFSR0 (left, 0);
10656       pic16_emitpcode(POC_BTFSC,
10657           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10658     }
10659
10660     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10661       /* unsigned bitfields result in either 0 or 1 */
10662       pic16_emitpcode(POC_INCF, op);
10663     } else {
10664       /* signed bitfields result in either 0 or -1 */
10665       pic16_emitpcode(POC_DECF, op);
10666     }
10667     if (same) {
10668       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10669     }
10670
10671     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10672     return;
10673   }
10674
10675 #endif
10676
10677   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10678     // access symbol directly
10679     pic16_mov2w (AOP(left), 0);
10680   } else {
10681     pic16_derefPtr (left, ptype, 0, NULL);
10682   }
10683
10684   /* if we have bitdisplacement then it fits   */
10685   /* into this byte completely or if length is */
10686   /* less than a byte                          */
10687   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10688
10689     /* shift right acc */
10690     AccRsh(shCnt, 0);
10691
10692     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10693           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10694
10695     /* VR -- normally I would use the following, but since we use the hack,
10696      * to avoid the masking from AccRsh, why not mask it right now? */
10697
10698     /*
10699        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10700      */
10701
10702     /* extend signed bitfields to 8 bits */
10703     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10704     {
10705       assert (blen + bstr > 0);
10706       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10707       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10708     }
10709
10710     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10711
10712     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10713     return ;
10714   }
10715
10716   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10717   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10718   exit(-1);
10719
10720   return ;
10721 }
10722
10723
10724 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10725 {
10726   int size, offset = 0, leoffset=0 ;
10727
10728         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10729         pic16_aopOp(result, ic, TRUE);
10730
10731         FENTRY;
10732
10733         size = AOP_SIZE(result);
10734 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10735
10736
10737 #if 1
10738         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10739                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10740                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10741                 goto release;
10742         }
10743 #endif
10744
10745         if(AOP(left)->aopu.pcop->type == PO_DIR)
10746                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10747
10748         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10749
10750         while (size--) {
10751                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10752                 
10753 //              pic16_DumpOp("(result)",result);
10754                 if(is_LitAOp(AOP(result))) {
10755                         pic16_mov2w(AOP(left), offset); // patch 8
10756                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10757                 } else {
10758                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10759                                 pic16_popGet(AOP(left), offset), //patch 8
10760                                 pic16_popGet(AOP(result), offset)));
10761                 }
10762
10763                 offset++;
10764                 leoffset++;
10765         }
10766
10767 release:
10768     pic16_freeAsmop(result,NULL,ic,TRUE);
10769 }
10770
10771
10772
10773 /*-----------------------------------------------------------------*/
10774 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10775 /*-----------------------------------------------------------------*/
10776 static void genNearPointerGet (operand *left, 
10777                                operand *result, 
10778                                iCode *ic)
10779 {
10780 //  asmop *aop = NULL;
10781   //regs *preg = NULL ;
10782   sym_link *rtype, *retype;
10783   sym_link *ltype, *letype;
10784
10785     FENTRY;
10786     
10787     rtype = operandType(result);
10788     retype= getSpec(rtype);
10789     ltype = operandType(left);
10790     letype= getSpec(ltype);
10791     
10792     pic16_aopOp(left,ic,FALSE);
10793
10794 //    pic16_DumpOp("(left)",left);
10795 //    pic16_DumpOp("(result)",result);
10796
10797     /* if left is rematerialisable and
10798      * result is not bit variable type and
10799      * the left is pointer to data space i.e
10800      * lower 128 bytes of space */
10801     
10802     if (AOP_TYPE(left) == AOP_PCODE
10803       && !IS_BITFIELD(retype)
10804       && DCL_TYPE(ltype) == POINTER) {
10805
10806         genDataPointerGet (left,result,ic);
10807         pic16_freeAsmop(left, NULL, ic, TRUE);
10808         return ;
10809     }
10810     
10811     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10812     pic16_aopOp (result,ic,TRUE);
10813     
10814     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10815
10816 #if 1
10817     if(IS_BITFIELD( retype )
10818       && (SPEC_BLEN(operandType(result))==1)
10819     ) {
10820       iCode *nextic;
10821       pCodeOp *jop;
10822       int bitstrt, bytestrt;
10823
10824         /* if this is bitfield of size 1, see if we are checking the value
10825          * of a single bit in an if-statement,
10826          * if yes, then don't generate usual code, but execute the
10827          * genIfx directly -- VR */
10828
10829         nextic = ic->next;
10830
10831         /* CHECK: if next iCode is IFX
10832          * and current result operand is nextic's conditional operand
10833          * and current result operand live ranges ends at nextic's key number
10834          */
10835         if((nextic->op == IFX)
10836           && (result == IC_COND(nextic))
10837           && (OP_LIVETO(result) == nextic->seq)
10838           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10839           ) {
10840             /* everything is ok then */
10841             /* find a way to optimize the genIfx iCode */
10842
10843             bytestrt = SPEC_BSTR(operandType(result))/8;
10844             bitstrt = SPEC_BSTR(operandType(result))%8;
10845             
10846             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10847
10848             genIfxpCOpJump(nextic, jop);
10849             
10850             pic16_freeAsmop(left, NULL, ic, TRUE);
10851             pic16_freeAsmop(result, NULL, ic, TRUE);
10852             return;
10853         }
10854     }
10855 #endif
10856
10857     /* if bitfield then unpack the bits */
10858     if (IS_BITFIELD(letype)) 
10859       genUnpackBits (result, left, NULL, POINTER);
10860     else {
10861       /* we have can just get the values */
10862       int size = AOP_SIZE(result);
10863       int offset = 0;   
10864         
10865       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10866
10867       pic16_loadFSR0( left, 0 );
10868
10869       while(size--) {
10870         if(size) {
10871           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10872                 pic16_popGet(AOP(result), offset++)));
10873         } else {
10874           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10875                 pic16_popGet(AOP(result), offset++)));
10876         }
10877       }
10878     }
10879
10880 #if 0
10881     /* now some housekeeping stuff */
10882     if (aop) {
10883       /* we had to allocate for this iCode */
10884       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10885       pic16_freeAsmop(NULL,aop,ic,TRUE);
10886     } else { 
10887       /* we did not allocate which means left
10888        * already in a pointer register, then
10889        * if size > 0 && this could be used again
10890        * we have to point it back to where it 
10891        * belongs */
10892       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10893       if (AOP_SIZE(result) > 1
10894         && !OP_SYMBOL(left)->remat
10895         && ( OP_SYMBOL(left)->liveTo > ic->seq
10896             || ic->depth )) {
10897 //        int size = AOP_SIZE(result) - 1;
10898 //        while (size--)
10899 //          pic16_emitcode("dec","%s",rname);
10900         }
10901     }
10902 #endif
10903
10904     /* done */
10905     pic16_freeAsmop(left,NULL,ic,TRUE);
10906     pic16_freeAsmop(result,NULL,ic,TRUE);
10907 }
10908
10909 /*-----------------------------------------------------------------*/
10910 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10911 /*-----------------------------------------------------------------*/
10912 static void genPagedPointerGet (operand *left, 
10913                                operand *result, 
10914                                iCode *ic)
10915 {
10916     asmop *aop = NULL;
10917     regs *preg = NULL ;
10918     char *rname ;
10919     sym_link *rtype, *retype;    
10920
10921     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10922
10923     rtype = operandType(result);
10924     retype= getSpec(rtype);
10925     
10926     pic16_aopOp(left,ic,FALSE);
10927
10928   /* if the value is already in a pointer register
10929        then don't need anything more */
10930     if (!AOP_INPREG(AOP(left))) {
10931         /* otherwise get a free pointer register */
10932         aop = newAsmop(0);
10933         preg = getFreePtr(ic,&aop,FALSE);
10934         pic16_emitcode("mov","%s,%s",
10935                 preg->name,
10936                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10937         rname = preg->name ;
10938     } else
10939         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10940     
10941     pic16_freeAsmop(left,NULL,ic,TRUE);
10942     pic16_aopOp (result,ic,TRUE);
10943
10944     /* if bitfield then unpack the bits */
10945     if (IS_BITFIELD(retype)) 
10946         genUnpackBits (result,left,rname,PPOINTER);
10947     else {
10948         /* we have can just get the values */
10949         int size = AOP_SIZE(result);
10950         int offset = 0 ;        
10951         
10952         while (size--) {
10953             
10954             pic16_emitcode("movx","a,@%s",rname);
10955             pic16_aopPut(AOP(result),"a",offset);
10956             
10957             offset++ ;
10958             
10959             if (size)
10960                 pic16_emitcode("inc","%s",rname);
10961         }
10962     }
10963
10964     /* now some housekeeping stuff */
10965     if (aop) {
10966         /* we had to allocate for this iCode */
10967         pic16_freeAsmop(NULL,aop,ic,TRUE);
10968     } else { 
10969         /* we did not allocate which means left
10970            already in a pointer register, then
10971            if size > 0 && this could be used again
10972            we have to point it back to where it 
10973            belongs */
10974         if (AOP_SIZE(result) > 1 &&
10975             !OP_SYMBOL(left)->remat &&
10976             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10977               ic->depth )) {
10978             int size = AOP_SIZE(result) - 1;
10979             while (size--)
10980                 pic16_emitcode("dec","%s",rname);
10981         }
10982     }
10983
10984     /* done */
10985     pic16_freeAsmop(result,NULL,ic,TRUE);
10986     
10987         
10988 }
10989
10990 #if 0
10991 /* This code is not adjusted to PIC16 and fails utterly.
10992  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10993
10994 /*-----------------------------------------------------------------*/
10995 /* genFarPointerGet - gget value from far space                    */
10996 /*-----------------------------------------------------------------*/
10997 static void genFarPointerGet (operand *left,
10998                               operand *result, iCode *ic)
10999 {
11000     int size, offset ;
11001     sym_link *retype = getSpec(operandType(result));
11002
11003     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11004
11005     pic16_aopOp(left,ic,FALSE);
11006
11007     /* if the operand is already in dptr 
11008     then we do nothing else we move the value to dptr */
11009     if (AOP_TYPE(left) != AOP_STR) {
11010         /* if this is remateriazable */
11011         if (AOP_TYPE(left) == AOP_IMMD)
11012             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11013         else { /* we need to get it byte by byte */
11014             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11015             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11016             if (options.model == MODEL_FLAT24)
11017             {
11018                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11019             }
11020         }
11021     }
11022     /* so dptr know contains the address */
11023     pic16_freeAsmop(left,NULL,ic,TRUE);
11024     pic16_aopOp(result,ic,TRUE);
11025
11026     /* if bit then unpack */
11027     if (IS_BITFIELD(retype)) 
11028         genUnpackBits(result,left,"dptr",FPOINTER);
11029     else {
11030         size = AOP_SIZE(result);
11031         offset = 0 ;
11032
11033         while (size--) {
11034             pic16_emitcode("movx","a,@dptr");
11035             pic16_aopPut(AOP(result),"a",offset++);
11036             if (size)
11037                 pic16_emitcode("inc","dptr");
11038         }
11039     }
11040
11041     pic16_freeAsmop(result,NULL,ic,TRUE);
11042 }
11043 #endif
11044
11045 #if 0
11046 /*-----------------------------------------------------------------*/
11047 /* genCodePointerGet - get value from code space                  */
11048 /*-----------------------------------------------------------------*/
11049 static void genCodePointerGet (operand *left,
11050                                 operand *result, iCode *ic)
11051 {
11052     int size, offset ;
11053     sym_link *retype = getSpec(operandType(result));
11054
11055     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11056
11057     pic16_aopOp(left,ic,FALSE);
11058
11059     /* if the operand is already in dptr 
11060     then we do nothing else we move the value to dptr */
11061     if (AOP_TYPE(left) != AOP_STR) {
11062         /* if this is remateriazable */
11063         if (AOP_TYPE(left) == AOP_IMMD)
11064             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11065         else { /* we need to get it byte by byte */
11066             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11067             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11068             if (options.model == MODEL_FLAT24)
11069             {
11070                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11071             }
11072         }
11073     }
11074     /* so dptr know contains the address */
11075     pic16_freeAsmop(left,NULL,ic,TRUE);
11076     pic16_aopOp(result,ic,FALSE);
11077
11078     /* if bit then unpack */
11079     if (IS_BITFIELD(retype)) 
11080         genUnpackBits(result,left,"dptr",CPOINTER);
11081     else {
11082         size = AOP_SIZE(result);
11083         offset = 0 ;
11084
11085         while (size--) {
11086             pic16_emitcode("clr","a");
11087             pic16_emitcode("movc","a,@a+dptr");
11088             pic16_aopPut(AOP(result),"a",offset++);
11089             if (size)
11090                 pic16_emitcode("inc","dptr");
11091         }
11092     }
11093
11094     pic16_freeAsmop(result,NULL,ic,TRUE);
11095 }
11096 #endif
11097
11098 #if 0
11099 /*-----------------------------------------------------------------*/
11100 /* genGenPointerGet - gget value from generic pointer space        */
11101 /*-----------------------------------------------------------------*/
11102 static void genGenPointerGet (operand *left,
11103                               operand *result, iCode *ic)
11104 {
11105   int size, offset, lit;
11106   sym_link *retype = getSpec(operandType(result));
11107
11108         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11109         pic16_aopOp(left,ic,FALSE);
11110         pic16_aopOp(result,ic,FALSE);
11111         size = AOP_SIZE(result);
11112
11113         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11114
11115         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11116
11117                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11118                 // load FSR0 from immediate
11119                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11120
11121 //              pic16_loadFSR0( left );
11122
11123                 offset = 0;
11124                 while(size--) {
11125                         if(size) {
11126                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11127                         } else {
11128                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11129                         }
11130                         offset++;
11131                 }
11132                 goto release;
11133
11134         }
11135         else { /* we need to get it byte by byte */
11136                 // set up FSR0 with address from left
11137                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11138                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11139                 
11140                 offset = 0 ;
11141
11142                 while(size--) {
11143                         if(size) {
11144                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11145                         } else {
11146                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11147                         }
11148                         offset++;
11149                 }
11150                 goto release;
11151         }
11152
11153   /* if bit then unpack */
11154         if (IS_BITFIELD(retype)) 
11155                 genUnpackBits(result,left,"BAD",GPOINTER);
11156
11157         release:
11158         pic16_freeAsmop(left,NULL,ic,TRUE);
11159         pic16_freeAsmop(result,NULL,ic,TRUE);
11160
11161 }
11162 #endif
11163
11164
11165 /*-----------------------------------------------------------------*/
11166 /* genGenPointerGet - gget value from generic pointer space        */
11167 /*-----------------------------------------------------------------*/
11168 static void genGenPointerGet (operand *left,
11169                               operand *result, iCode *ic)
11170 {
11171   int size, offset, lit;
11172   sym_link *letype = getSpec(operandType(left));
11173
11174     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11175     pic16_aopOp(left,ic,FALSE);
11176     pic16_aopOp(result,ic,TRUE);
11177     size = AOP_SIZE(result);
11178
11179     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11180   
11181     /* if bit then unpack */
11182     if (IS_BITFIELD(letype)) {
11183       genUnpackBits(result,left,"BAD",GPOINTER);
11184       goto release;
11185     }
11186
11187     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11188
11189       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11190       // load FSR0 from immediate
11191       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11192
11193       werror(W_POSSBUG2, __FILE__, __LINE__);
11194
11195       offset = 0;
11196       while(size--) {
11197         if(size) {
11198           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11199         } else {
11200           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11201         }
11202         offset++;
11203       }
11204
11205       goto release;
11206
11207     } else { /* we need to get it byte by byte */
11208
11209       /* set up WREG:PRODL:FSR0L with address from left */
11210       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11211       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11212       pic16_mov2w(AOP(left), 2);
11213       pic16_callGenericPointerRW(0, size);
11214       
11215       assignResultValue(result, 1);
11216       
11217       goto release;
11218     }
11219
11220 release:
11221   pic16_freeAsmop(left,NULL,ic,TRUE);
11222   pic16_freeAsmop(result,NULL,ic,TRUE);
11223 }
11224
11225 /*-----------------------------------------------------------------*/
11226 /* genConstPointerGet - get value from const generic pointer space */
11227 /*-----------------------------------------------------------------*/
11228 static void genConstPointerGet (operand *left,
11229                                 operand *result, iCode *ic)
11230 {
11231   //sym_link *retype = getSpec(operandType(result));
11232   // symbol *albl = newiTempLabel(NULL);        // patch 15
11233   // symbol *blbl = newiTempLabel(NULL);        //
11234   // PIC_OPCODE poc;                            // patch 15
11235   int size;
11236   int offset = 0;
11237
11238   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11239   pic16_aopOp(left,ic,FALSE);
11240   pic16_aopOp(result,ic,TRUE);
11241   size = AOP_SIZE(result);
11242
11243   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11244
11245   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11246
11247   // set up table pointer
11248   if( (AOP_TYPE(left) == AOP_PCODE) 
11249       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11250           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11251     {
11252       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11253       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11254       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11255       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11256       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11257       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11258   } else {
11259     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11260     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11261     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11262   }
11263
11264   while(size--) {
11265     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11266     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11267     offset++;
11268   }
11269     
11270   pic16_freeAsmop(left,NULL,ic,TRUE);
11271   pic16_freeAsmop(result,NULL,ic,TRUE);
11272 }
11273
11274
11275 /*-----------------------------------------------------------------*/
11276 /* genPointerGet - generate code for pointer get                   */
11277 /*-----------------------------------------------------------------*/
11278 static void genPointerGet (iCode *ic)
11279 {
11280   operand *left, *result ;
11281   sym_link *type, *etype;
11282   int p_type;
11283
11284     FENTRY;
11285     
11286     left = IC_LEFT(ic);
11287     result = IC_RESULT(ic) ;
11288
11289     /* depending on the type of pointer we need to
11290     move it to the correct pointer register */
11291     type = operandType(left);
11292     etype = getSpec(type);
11293
11294 #if 0
11295     if (IS_PTR_CONST(type))
11296 #else
11297     if (IS_CODEPTR(type))
11298 #endif
11299       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11300
11301     /* if left is of type of pointer then it is simple */
11302     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11303       p_type = DCL_TYPE(type);
11304     else {
11305       /* we have to go by the storage class */
11306       p_type = PTR_TYPE(SPEC_OCLS(etype));
11307
11308       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11309
11310       if (SPEC_OCLS(etype)->codesp ) {
11311         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11312         //p_type = CPOINTER ;   
11313       } else
11314       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11315         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11316         /*p_type = FPOINTER ;*/ 
11317       } else
11318       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11319         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11320         /* p_type = PPOINTER; */
11321       } else
11322       if (SPEC_OCLS(etype) == idata ) {
11323         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11324         /* p_type = IPOINTER; */
11325       } else {
11326         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11327         /* p_type = POINTER ; */
11328       }
11329     }
11330
11331     /* now that we have the pointer type we assign
11332     the pointer values */
11333     switch (p_type) {
11334       case POINTER:     
11335       case FPOINTER:
11336       case IPOINTER:
11337         genNearPointerGet (left,result,ic);
11338         break;
11339
11340       case PPOINTER:
11341         genPagedPointerGet(left,result,ic);
11342         break;
11343
11344 #if 0
11345       /* PICs do not support FAR pointers... */
11346       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11347       case FPOINTER:
11348         genFarPointerGet (left,result,ic);
11349         break;
11350 #endif
11351
11352       case CPOINTER:
11353         genConstPointerGet (left,result,ic);
11354         //pic16_emitcodePointerGet (left,result,ic);
11355         break;
11356
11357       case GPOINTER:
11358 #if 0
11359       if (IS_PTR_CONST(type))
11360         genConstPointerGet (left,result,ic);
11361       else
11362 #endif
11363         genGenPointerGet (left,result,ic);
11364       break;
11365
11366     default:
11367       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11368               "genPointerGet: illegal pointer type");
11369     
11370     }
11371 }
11372
11373 /*-----------------------------------------------------------------*/
11374 /* genPackBits - generates code for packed bit storage             */
11375 /*-----------------------------------------------------------------*/
11376 static void genPackBits (sym_link    *etype , operand *result,
11377                          operand *right ,
11378                          char *rname, int p_type)
11379 {
11380   int shCnt = 0 ;
11381   int offset = 0  ;
11382   int rLen = 0 ;
11383   int blen, bstr ;   
11384   int shifted_and_masked = 0;
11385   unsigned long lit = (unsigned long)-1;
11386   sym_link *retype;
11387
11388   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11389   blen = SPEC_BLEN(etype);
11390   bstr = SPEC_BSTR(etype);
11391
11392   retype = getSpec(operandType(right));
11393
11394   if(AOP_TYPE(right) == AOP_LIT) {
11395     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11396     
11397     if((blen == 1) && (bstr < 8)) {
11398       /* it is a single bit, so use the appropriate bit instructions */
11399
11400       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11401
11402       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11403         /* workaround to reduce the extra lfsr instruction */
11404         if(lit) {
11405           pic16_emitpcode(POC_BSF,
11406               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11407         } else {
11408           pic16_emitpcode(POC_BCF,
11409               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11410         }
11411       } else {
11412         if (PIC_IS_DATA_PTR(operandType(result))) {
11413           pic16_loadFSR0(result, 0);
11414           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11415               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11416         } else {
11417           /* get old value */
11418           pic16_derefPtr (result, p_type, 0, NULL);
11419           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11420               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11421           /* write back new value */
11422           pic16_derefPtr (result, p_type, 1, NULL);
11423         }
11424       }
11425
11426       return;
11427     }
11428     /* IORLW below is more efficient */
11429     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11430     lit = (lit & ((1UL << blen) - 1)) << bstr;
11431     shifted_and_masked = 1;
11432     offset++;
11433   } else
11434     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11435         && IS_BITFIELD(retype) 
11436         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11437         && (blen == 1)) {
11438       int rblen, rbstr;
11439
11440       rblen = SPEC_BLEN( retype );
11441       rbstr = SPEC_BSTR( retype );
11442
11443       if(IS_BITFIELD(etype)) {
11444         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11445         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11446       } else {
11447         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11448       }
11449
11450       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11451
11452       if(IS_BITFIELD(etype)) {
11453         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11454       } else {
11455         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11456       }
11457
11458       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11459
11460       return;
11461     } else {
11462       /* move right to W */
11463       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11464     }
11465
11466   /* if the bit length is less than or   */
11467   /* it exactly fits a byte then         */
11468   if((shCnt=SPEC_BSTR(etype))
11469       || SPEC_BLEN(etype) <= 8 )  {
11470     int fsr0_setup = 0;
11471
11472     if (blen != 8 || bstr != 0) {
11473       // we need to combine the value with the old value
11474       if(!shifted_and_masked)
11475       {
11476         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11477
11478         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11479             SPEC_BSTR(etype), SPEC_BLEN(etype));
11480
11481         /* shift left acc, do NOT mask the result again */
11482         AccLsh(shCnt, 0);
11483
11484         /* using PRODH as a temporary register here */
11485         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11486       }
11487
11488       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11489         || IS_DIRECT(result)) {
11490         /* access symbol directly */
11491         pic16_mov2w (AOP(result), 0);
11492       } else {
11493         /* get old value */
11494         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11495       }
11496 #if 1
11497       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11498             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11499                             (unsigned char)(0xff >> (8-bstr))) ));
11500       if (!shifted_and_masked) {
11501         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11502       } else {
11503         /* We have the shifted and masked (literal) right value in `lit' */
11504         if (lit != 0)
11505           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11506       }
11507     } // if (blen != 8 || bstr != 0)
11508
11509     /* write new value back */
11510     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11511         || IS_DIRECT(result)) {
11512       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11513     } else {
11514       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11515     }
11516 #endif
11517
11518     return;
11519   }
11520
11521
11522 #if 0
11523   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11524   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11525   exit(-1);
11526 #endif
11527
11528
11529   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11530   rLen = SPEC_BLEN(etype)-8;
11531
11532   /* now generate for lengths greater than one byte */
11533   while (1) {
11534     rLen -= 8 ;
11535     if (rLen <= 0 ) {
11536       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11537       break ;
11538     }
11539
11540     switch (p_type) {
11541       case POINTER:
11542         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11543         break;
11544
11545         /*
11546            case FPOINTER:
11547            MOVA(l);
11548            pic16_emitcode("movx","@dptr,a");
11549            break;
11550
11551            case GPOINTER:
11552            MOVA(l);
11553            DEBUGpic16_emitcode(";lcall","__gptrput");
11554            break;  
11555          */
11556       default:
11557         assert(0);
11558     }   
11559
11560
11561     pic16_mov2w(AOP(right), offset++);
11562   }
11563
11564   /* last last was not complete */
11565   if (rLen)   {
11566     /* save the byte & read byte */
11567     switch (p_type) {
11568       case POINTER:
11569         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11570         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11571         break;
11572
11573         /*
11574            case FPOINTER:
11575            pic16_emitcode ("mov","b,a");
11576            pic16_emitcode("movx","a,@dptr");
11577            break;
11578
11579            case GPOINTER:
11580            pic16_emitcode ("push","b");
11581            pic16_emitcode ("push","acc");
11582            pic16_emitcode ("lcall","__gptrget");
11583            pic16_emitcode ("pop","b");
11584            break;
11585          */
11586       default:
11587         assert(0);
11588     }
11589     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11590     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11591     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11592     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11593     //        pic16_emitcode ("orl","a,b");
11594   }
11595
11596   //    if (p_type == GPOINTER)
11597   //        pic16_emitcode("pop","b");
11598
11599   switch (p_type) {
11600
11601     case POINTER:
11602       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11603       //        pic16_emitcode("mov","@%s,a",rname);
11604       break;
11605       /*
11606          case FPOINTER:
11607          pic16_emitcode("movx","@dptr,a");
11608          break;
11609
11610          case GPOINTER:
11611          DEBUGpic16_emitcode(";lcall","__gptrput");
11612          break;                 
11613        */
11614     default:
11615       assert(0);
11616   }
11617
11618   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11619 }
11620
11621 /*-----------------------------------------------------------------*/
11622 /* genDataPointerSet - remat pointer to data space                 */
11623 /*-----------------------------------------------------------------*/
11624 static void genDataPointerSet(operand *right,
11625                               operand *result,
11626                               iCode *ic)
11627 {
11628   int size, offset = 0, resoffset=0 ;
11629
11630     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11631     pic16_aopOp(right,ic,FALSE);
11632
11633     size = AOP_SIZE(right);
11634
11635 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11636
11637 #if 0
11638     if ( AOP_TYPE(result) == AOP_PCODE) {
11639       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11640               AOP(result)->aopu.pcop->name,
11641                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11642               PCOR(AOP(result)->aopu.pcop)->instance:
11643               PCOI(AOP(result)->aopu.pcop)->offset);
11644     }
11645 #endif
11646
11647     if(AOP(result)->aopu.pcop->type == PO_DIR)
11648       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11649
11650     while (size--) {
11651       if (AOP_TYPE(right) == AOP_LIT) {
11652         unsigned int lit;
11653
11654           if(!IS_FLOAT(operandType( right )))
11655             lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11656           else {
11657             union {
11658               unsigned long lit_int;
11659               float lit_float;
11660             } info;
11661         
11662               /* take care if literal is a float */
11663               info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11664               lit = info.lit_int;
11665           }
11666                     lit = lit >> (8*offset);
11667                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11668                 } else {
11669                   pic16_mov2w(AOP(right), offset);
11670                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11671                 }
11672                 offset++;
11673                 resoffset++;
11674         }
11675
11676     pic16_freeAsmop(right,NULL,ic,TRUE);
11677 }
11678
11679
11680
11681 /*-----------------------------------------------------------------*/
11682 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11683 /*-----------------------------------------------------------------*/
11684 static void genNearPointerSet (operand *right,
11685                                operand *result, 
11686                                iCode *ic)
11687 {
11688   asmop *aop = NULL;
11689   sym_link *retype;
11690   sym_link *ptype = operandType(result);
11691   sym_link *resetype;
11692     
11693     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11694     retype= getSpec(operandType(right));
11695     resetype = getSpec(operandType(result));
11696   
11697     pic16_aopOp(result,ic,FALSE);
11698     
11699     /* if the result is rematerializable &
11700      * in data space & not a bit variable */
11701         
11702     /* and result is not a bit variable */
11703     if (AOP_TYPE(result) == AOP_PCODE
11704 //      && AOP_TYPE(result) == AOP_IMMD
11705       && DCL_TYPE(ptype) == POINTER
11706       && !IS_BITFIELD(retype)
11707       && !IS_BITFIELD(resetype)) {
11708
11709         genDataPointerSet (right,result,ic);
11710         pic16_freeAsmop(result,NULL,ic,TRUE);
11711       return;
11712     }
11713
11714     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11715     pic16_aopOp(right,ic,FALSE);
11716     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11717
11718     /* if bitfield then unpack the bits */
11719     if (IS_BITFIELD(resetype)) {
11720       genPackBits (resetype, result, right, NULL, POINTER);
11721     } else {
11722       /* we have can just get the values */
11723       int size = AOP_SIZE(right);
11724       int offset = 0 ;    
11725
11726         pic16_loadFSR0(result, 0);
11727             
11728         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11729         while (size--) {
11730           if (AOP_TYPE(right) == AOP_LIT) {
11731             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11732             if (size) {
11733               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11734             } else {
11735               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11736             }
11737           } else { // no literal
11738             if(size) {
11739               pic16_emitpcode(POC_MOVFF,
11740                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11741                   pic16_popCopyReg(&pic16_pc_postinc0)));
11742             } else {
11743               pic16_emitpcode(POC_MOVFF,
11744                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11745                   pic16_popCopyReg(&pic16_pc_indf0)));
11746             }
11747           }
11748           
11749           offset++;
11750         }
11751     }
11752
11753     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11754     /* now some housekeeping stuff */
11755     if (aop) {
11756       /* we had to allocate for this iCode */
11757       pic16_freeAsmop(NULL,aop,ic,TRUE);
11758     } else { 
11759       /* we did not allocate which means left
11760        * already in a pointer register, then
11761        * if size > 0 && this could be used again
11762        * we have to point it back to where it 
11763        * belongs */
11764       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11765       if (AOP_SIZE(right) > 1
11766         && !OP_SYMBOL(result)->remat
11767         && ( OP_SYMBOL(result)->liveTo > ic->seq
11768         || ic->depth )) {
11769
11770           int size = AOP_SIZE(right) - 1;
11771
11772             while (size--)
11773               pic16_emitcode("decf","fsr0,f");
11774               //pic16_emitcode("dec","%s",rname);
11775       }
11776     }
11777
11778     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11779     /* done */
11780 //release:
11781     pic16_freeAsmop(right,NULL,ic,TRUE);
11782     pic16_freeAsmop(result,NULL,ic,TRUE);
11783 }
11784
11785 /*-----------------------------------------------------------------*/
11786 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11787 /*-----------------------------------------------------------------*/
11788 static void genPagedPointerSet (operand *right,
11789                                operand *result, 
11790                                iCode *ic)
11791 {
11792     asmop *aop = NULL;
11793     regs *preg = NULL ;
11794     char *rname , *l;
11795     sym_link *retype;
11796        
11797     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11798
11799     retype= getSpec(operandType(right));
11800     
11801     pic16_aopOp(result,ic,FALSE);
11802     
11803     /* if the value is already in a pointer register
11804        then don't need anything more */
11805     if (!AOP_INPREG(AOP(result))) {
11806         /* otherwise get a free pointer register */
11807         aop = newAsmop(0);
11808         preg = getFreePtr(ic,&aop,FALSE);
11809         pic16_emitcode("mov","%s,%s",
11810                 preg->name,
11811                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11812         rname = preg->name ;
11813     } else
11814         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11815     
11816     pic16_freeAsmop(result,NULL,ic,TRUE);
11817     pic16_aopOp (right,ic,FALSE);
11818
11819     /* if bitfield then unpack the bits */
11820     if (IS_BITFIELD(retype)) 
11821         genPackBits (retype,result,right,rname,PPOINTER);
11822     else {
11823         /* we have can just get the values */
11824         int size = AOP_SIZE(right);
11825         int offset = 0 ;        
11826         
11827         while (size--) {
11828             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11829             
11830             MOVA(l);
11831             pic16_emitcode("movx","@%s,a",rname);
11832
11833             if (size)
11834                 pic16_emitcode("inc","%s",rname);
11835
11836             offset++;
11837         }
11838     }
11839     
11840     /* now some housekeeping stuff */
11841     if (aop) {
11842         /* we had to allocate for this iCode */
11843         pic16_freeAsmop(NULL,aop,ic,TRUE);
11844     } else { 
11845         /* we did not allocate which means left
11846            already in a pointer register, then
11847            if size > 0 && this could be used again
11848            we have to point it back to where it 
11849            belongs */
11850         if (AOP_SIZE(right) > 1 &&
11851             !OP_SYMBOL(result)->remat &&
11852             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11853               ic->depth )) {
11854             int size = AOP_SIZE(right) - 1;
11855             while (size--)
11856                 pic16_emitcode("dec","%s",rname);
11857         }
11858     }
11859
11860     /* done */
11861     pic16_freeAsmop(right,NULL,ic,TRUE);
11862     
11863         
11864 }
11865
11866 #if 0
11867 /* This code is not adjusted to PIC16 and fails utterly...
11868  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11869
11870 /*-----------------------------------------------------------------*/
11871 /* genFarPointerSet - set value from far space                     */
11872 /*-----------------------------------------------------------------*/
11873 static void genFarPointerSet (operand *right,
11874                               operand *result, iCode *ic)
11875 {
11876     int size, offset ;
11877     sym_link *retype = getSpec(operandType(right));
11878
11879     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11880     pic16_aopOp(result,ic,FALSE);
11881
11882     /* if the operand is already in dptr 
11883     then we do nothing else we move the value to dptr */
11884     if (AOP_TYPE(result) != AOP_STR) {
11885         /* if this is remateriazable */
11886         if (AOP_TYPE(result) == AOP_IMMD)
11887             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11888         else { /* we need to get it byte by byte */
11889             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11890             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11891             if (options.model == MODEL_FLAT24)
11892             {
11893                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11894             }
11895         }
11896     }
11897     /* so dptr know contains the address */
11898     pic16_freeAsmop(result,NULL,ic,TRUE);
11899     pic16_aopOp(right,ic,FALSE);
11900
11901     /* if bit then unpack */
11902     if (IS_BITFIELD(retype)) 
11903         genPackBits(retype,result,right,"dptr",FPOINTER);
11904     else {
11905         size = AOP_SIZE(right);
11906         offset = 0 ;
11907
11908         while (size--) {
11909             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11910             MOVA(l);
11911             pic16_emitcode("movx","@dptr,a");
11912             if (size)
11913                 pic16_emitcode("inc","dptr");
11914         }
11915     }
11916
11917     pic16_freeAsmop(right,NULL,ic,TRUE);
11918 }
11919 #endif
11920
11921 /*-----------------------------------------------------------------*/
11922 /* genGenPointerSet - set value from generic pointer space         */
11923 /*-----------------------------------------------------------------*/
11924 #if 0
11925 static void genGenPointerSet (operand *right,
11926                               operand *result, iCode *ic)
11927 {
11928         int i, size, offset, lit;
11929         sym_link *retype = getSpec(operandType(right));
11930
11931         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11932
11933         pic16_aopOp(result,ic,FALSE);
11934         pic16_aopOp(right,ic,FALSE);
11935         size = AOP_SIZE(right);
11936         offset = 0;
11937
11938         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11939
11940         /* if the operand is already in dptr 
11941                 then we do nothing else we move the value to dptr */
11942         if (AOP_TYPE(result) != AOP_STR) {
11943                 /* if this is remateriazable */
11944                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11945                 // WARNING: anythig until "else" is untested!
11946                 if (AOP_TYPE(result) == AOP_IMMD) {
11947                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11948                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11949                         // load FSR0 from immediate
11950                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11951                         offset = 0;
11952                         while(size--) {
11953                                 if(size) {
11954                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11955                                 } else {
11956                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11957                                 }
11958                                 offset++;
11959                         }
11960                         goto release;
11961                 }
11962                 else { /* we need to get it byte by byte */
11963                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11964                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11965
11966                         // set up FSR0 with address of result
11967                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11968                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11969
11970                         /* hack hack! see if this the FSR. If so don't load W */
11971                         if(AOP_TYPE(right) != AOP_ACC) {
11972
11973                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11974
11975                                 if(AOP_TYPE(right) == AOP_LIT)
11976                                 {
11977                                         // copy literal
11978                                         // note: pic16_popGet handles sign extension
11979                                         for(i=0;i<size;i++) {
11980                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11981                                                 if(i < size-1)
11982                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11983                                                 else
11984                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11985                                         }
11986                                 } else {
11987                                         // copy regs
11988
11989                                         for(i=0;i<size;i++) {
11990                                                 if(i < size-1)
11991                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11992                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11993                                                 else
11994                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11995                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11996                                         }
11997                                 }
11998                                 goto release;
11999                         } 
12000                         // right = ACC
12001                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12002                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12003                         goto release;
12004         } // if (AOP_TYPE(result) != AOP_IMMD)
12005
12006         } // if (AOP_TYPE(result) != AOP_STR)
12007         /* so dptr know contains the address */
12008
12009
12010         /* if bit then unpack */
12011         if (IS_BITFIELD(retype)) 
12012                 genPackBits(retype,result,right,"dptr",GPOINTER);
12013         else {
12014                 size = AOP_SIZE(right);
12015                 offset = 0 ;
12016
12017                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12018
12019                 // set up FSR0 with address of result
12020                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12021                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12022         
12023                 while (size--) {
12024                         if (AOP_TYPE(right) == AOP_LIT) {
12025                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12026                                 if (size) {
12027                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12028                                 } else {
12029                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12030                                 }
12031                         } else { // no literal
12032                                 if(size) {
12033                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12034                                 } else {
12035                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12036                                 }
12037                         }
12038                         offset++;
12039                 }
12040         }
12041
12042         release:
12043         pic16_freeAsmop(right,NULL,ic,TRUE);
12044         pic16_freeAsmop(result,NULL,ic,TRUE);
12045 }
12046 #endif
12047
12048 static void genGenPointerSet (operand *right,
12049                               operand *result, iCode *ic)
12050 {
12051   int size;
12052   sym_link *retype = getSpec(operandType(result));
12053
12054     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12055
12056     pic16_aopOp(result,ic,FALSE);
12057     pic16_aopOp(right,ic,FALSE);
12058     size = AOP_SIZE(right);
12059
12060     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12061
12062
12063     /* if bit then unpack */
12064     if (IS_BITFIELD(retype)) {
12065 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12066       genPackBits(retype,result,right,"dptr",GPOINTER);
12067       goto release;
12068     }
12069
12070     size = AOP_SIZE(right);
12071
12072     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12073
12074
12075     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12076
12077     /* value of right+0 is placed on stack, which will be retrieved
12078      * by the support function thus restoring the stack. The important
12079      * thing is that there is no need to manually restore stack pointer
12080      * here */
12081     pushaop(AOP(right), 0);
12082 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12083     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12084     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12085     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12086     
12087     /* load address to write to in WREG:FSR0H:FSR0L */
12088     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12089                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12090     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12091                                 pic16_popCopyReg(&pic16_pc_prodl)));
12092     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12093     
12094     pic16_callGenericPointerRW(1, size);
12095
12096 release:
12097     pic16_freeAsmop(right,NULL,ic,TRUE);
12098     pic16_freeAsmop(result,NULL,ic,TRUE);
12099 }
12100
12101 /*-----------------------------------------------------------------*/
12102 /* genPointerSet - stores the value into a pointer location        */
12103 /*-----------------------------------------------------------------*/
12104 static void genPointerSet (iCode *ic)
12105 {    
12106   operand *right, *result ;
12107   sym_link *type, *etype;
12108   int p_type;
12109
12110     FENTRY;
12111
12112     right = IC_RIGHT(ic);
12113     result = IC_RESULT(ic) ;
12114
12115     /* depending on the type of pointer we need to
12116     move it to the correct pointer register */
12117     type = operandType(result);
12118     etype = getSpec(type);
12119     
12120     /* if left is of type of pointer then it is simple */
12121     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12122         p_type = DCL_TYPE(type);
12123     }
12124     else {
12125         /* we have to go by the storage class */
12126         p_type = PTR_TYPE(SPEC_OCLS(etype));
12127
12128 /*      if (SPEC_OCLS(etype)->codesp ) { */
12129 /*          p_type = CPOINTER ;  */
12130 /*      } */
12131 /*      else */
12132 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12133 /*              p_type = FPOINTER ; */
12134 /*          else */
12135 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12136 /*                  p_type = PPOINTER ; */
12137 /*              else */
12138 /*                  if (SPEC_OCLS(etype) == idata ) */
12139 /*                      p_type = IPOINTER ; */
12140 /*                  else */
12141 /*                      p_type = POINTER ; */
12142     }
12143
12144     /* now that we have the pointer type we assign
12145     the pointer values */
12146     switch (p_type) {
12147       case POINTER:
12148       case FPOINTER:
12149       case IPOINTER:
12150         genNearPointerSet (right,result,ic);
12151         break;
12152
12153       case PPOINTER:
12154         genPagedPointerSet (right,result,ic);
12155         break;
12156
12157 #if 0
12158       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12159       case FPOINTER:
12160         genFarPointerSet (right,result,ic);
12161         break;
12162 #endif
12163         
12164       case GPOINTER:
12165         genGenPointerSet (right,result,ic);
12166         break;
12167
12168       default:
12169         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12170           "genPointerSet: illegal pointer type");
12171     }
12172 }
12173
12174 /*-----------------------------------------------------------------*/
12175 /* genIfx - generate code for Ifx statement                        */
12176 /*-----------------------------------------------------------------*/
12177 static void genIfx (iCode *ic, iCode *popIc)
12178 {
12179   operand *cond = IC_COND(ic);
12180   int isbit =0;
12181
12182     FENTRY;
12183
12184     pic16_aopOp(cond,ic,FALSE);
12185
12186     /* get the value into acc */
12187     if (AOP_TYPE(cond) != AOP_CRY)
12188       pic16_toBoolean(cond);
12189     else
12190       isbit = 1;
12191     /* the result is now in the accumulator */
12192     pic16_freeAsmop(cond,NULL,ic,TRUE);
12193
12194     /* if there was something to be popped then do it */
12195     if (popIc)
12196       genIpop(popIc);
12197
12198     /* if the condition is  a bit variable */
12199     if (isbit && IS_ITEMP(cond) && 
12200         SPIL_LOC(cond)) {
12201       genIfxJump(ic,"c");
12202       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12203     } else {
12204       if (isbit && !IS_ITEMP(cond))
12205         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12206         else
12207         genIfxJump(ic,"a");
12208     }
12209     ic->generated = 1;
12210 }
12211
12212 /*-----------------------------------------------------------------*/
12213 /* genAddrOf - generates code for address of                       */
12214 /*-----------------------------------------------------------------*/
12215 static void genAddrOf (iCode *ic)
12216 {
12217   operand *result, *left;
12218   int size;
12219   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12220   pCodeOp *pcop0, *pcop1, *pcop2;
12221
12222     FENTRY;
12223
12224     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12225
12226     sym = OP_SYMBOL( IC_LEFT(ic) );
12227     
12228     if(sym->onStack) {
12229       /* get address of symbol on stack */
12230       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12231 #if 0
12232       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12233                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12234 #endif
12235
12236       // operands on stack are accessible via "FSR2 + index" with index
12237       // starting at 2 for arguments and growing from 0 downwards for
12238       // local variables (index == 0 is not assigned so we add one here)
12239       {
12240         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12241
12242           if (soffs <= 0) {
12243             assert (soffs < 0);
12244             soffs++;
12245           } // if
12246
12247           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12248           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12249           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12250           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12251           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12252           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12253           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12254       }
12255
12256       goto release;
12257     }
12258         
12259 //      if(pic16_debug_verbose) {
12260 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12261 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12262 //      }
12263         
12264     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12265     size = AOP_SIZE(IC_RESULT(ic));
12266
12267     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12268     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12269     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12270         
12271     if (size == 3) {
12272       pic16_emitpcode(POC_MOVLW, pcop0);
12273       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12274       pic16_emitpcode(POC_MOVLW, pcop1);
12275       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12276       pic16_emitpcode(POC_MOVLW, pcop2);
12277       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12278     } else
12279     if (size == 2) {
12280       pic16_emitpcode(POC_MOVLW, pcop0);
12281       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12282       pic16_emitpcode(POC_MOVLW, pcop1);
12283     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12284     } else {
12285       pic16_emitpcode(POC_MOVLW, pcop0);
12286       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12287     }
12288
12289     pic16_freeAsmop(left, NULL, ic, FALSE);
12290 release:
12291     pic16_freeAsmop(result,NULL,ic,TRUE);
12292 }
12293
12294
12295 #if 0
12296 /*-----------------------------------------------------------------*/
12297 /* genFarFarAssign - assignment when both are in far space         */
12298 /*-----------------------------------------------------------------*/
12299 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12300 {
12301     int size = AOP_SIZE(right);
12302     int offset = 0;
12303     char *l ;
12304     /* first push the right side on to the stack */
12305     while (size--) {
12306         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12307         MOVA(l);
12308         pic16_emitcode ("push","acc");
12309     }
12310     
12311     pic16_freeAsmop(right,NULL,ic,FALSE);
12312     /* now assign DPTR to result */
12313     pic16_aopOp(result,ic,FALSE);
12314     size = AOP_SIZE(result);
12315     while (size--) {
12316         pic16_emitcode ("pop","acc");
12317         pic16_aopPut(AOP(result),"a",--offset);
12318     }
12319     pic16_freeAsmop(result,NULL,ic,FALSE);
12320         
12321 }
12322 #endif
12323
12324 /*-----------------------------------------------------------------*/
12325 /* genAssign - generate code for assignment                        */
12326 /*-----------------------------------------------------------------*/
12327 static void genAssign (iCode *ic)
12328 {
12329   operand *result, *right;
12330   sym_link *restype, *rtype;
12331   int size, offset,know_W;
12332   unsigned long lit = 0L;
12333
12334     result = IC_RESULT(ic);
12335     right  = IC_RIGHT(ic) ;
12336
12337     FENTRY;
12338   
12339     /* if they are the same */
12340     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12341       return ;
12342
12343     /* reversed order operands are aopOp'ed so that result operand
12344      * is effective in case right is a stack symbol. This maneauver
12345      * allows to use the _G.resDirect flag later */
12346      pic16_aopOp(result,ic,TRUE);
12347     pic16_aopOp(right,ic,FALSE);
12348
12349     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12350
12351     /* if they are the same registers */
12352     if (pic16_sameRegs(AOP(right),AOP(result)))
12353       goto release;
12354
12355     /* if the result is a bit */
12356     if (AOP_TYPE(result) == AOP_CRY) {
12357       /* if the right size is a literal then
12358          we know what the value is */
12359       if (AOP_TYPE(right) == AOP_LIT) {
12360           
12361         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12362             pic16_popGet(AOP(result),0));
12363
12364         if (((int) operandLitValue(right))) 
12365           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12366               AOP(result)->aopu.aop_dir,
12367               AOP(result)->aopu.aop_dir);
12368         else
12369           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12370               AOP(result)->aopu.aop_dir,
12371               AOP(result)->aopu.aop_dir);
12372         
12373         goto release;
12374       }
12375
12376       /* the right is also a bit variable */
12377       if (AOP_TYPE(right) == AOP_CRY) {
12378         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12379         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12380         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12381
12382         goto release ;
12383       }
12384
12385       /* we need to or */
12386       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12387       pic16_toBoolean(right);
12388       emitSKPZ;
12389       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12390       //pic16_aopPut(AOP(result),"a",0);
12391       goto release ;
12392     }
12393
12394     /* bit variables done */
12395     /* general case */
12396     size = AOP_SIZE(result);
12397     offset = 0 ;
12398
12399   /* bit variables done */
12400   /* general case */
12401   size = AOP_SIZE(result);
12402   restype = operandType(result);
12403   rtype = operandType(right);
12404   offset = 0 ;
12405
12406   if(AOP_TYPE(right) == AOP_LIT) {
12407     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12408     {
12409       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12410
12411       /* patch tag for literals that are cast to pointers */
12412       if (IS_CODEPTR(restype)) {
12413         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12414         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12415       } else {
12416         if (IS_GENPTR(restype))
12417         {
12418           if (IS_CODEPTR(rtype)) {
12419             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12420             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12421           } else if (PIC_IS_DATA_PTR(rtype)) {
12422             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12423             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12424           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12425             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12426           } else if (IS_PTR(rtype)) {
12427             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12428             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12429           }
12430         }
12431       }
12432     } else {
12433       union {
12434         unsigned long lit_int;
12435         float lit_float;
12436       } info;
12437
12438
12439       if(IS_FIXED16X16(operandType(right))) {
12440         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12441       } else {
12442         /* take care if literal is a float */
12443         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12444         lit = info.lit_int;
12445       }
12446     }
12447   }
12448
12449 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12450 //                      sizeof(unsigned long int), sizeof(float));
12451
12452
12453     if (AOP_TYPE(right) == AOP_REG) {
12454       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12455       while (size--) {
12456         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12457       } // while
12458       goto release;
12459     }
12460
12461     /* when do we have to read the program memory?
12462      * - if right itself is a symbol in code space
12463      *   (we don't care what it points to if it's a pointer)
12464      * - AND right is not a function (we would want its address)
12465      */
12466     if(AOP_TYPE(right) != AOP_LIT
12467       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12468       && !IS_FUNC(OP_SYM_TYPE(right))
12469       && !IS_ITEMP(right)) {
12470
12471       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12472       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12473       
12474       // set up table pointer
12475       if(is_LitOp(right)) {
12476 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12477         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12478         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12479         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12480         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12481         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12482         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12483       } else {
12484 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12485         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12486             pic16_popCopyReg(&pic16_pc_tblptrl)));
12487         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12488             pic16_popCopyReg(&pic16_pc_tblptrh)));
12489         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12490             pic16_popCopyReg(&pic16_pc_tblptru)));
12491       }
12492
12493       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12494       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12495       while(size--) {
12496         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12497         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12498             pic16_popGet(AOP(result),offset)));
12499         offset++;
12500       }
12501
12502       /* FIXME: for pointers we need to extend differently (according
12503        * to pointer type DATA/CODE/EEPROM/... :*/
12504       size = getSize(OP_SYM_TYPE(right));
12505       if(AOP_SIZE(result) > size) {
12506         size = AOP_SIZE(result) - size;
12507         while(size--) {
12508           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12509           offset++;
12510         }
12511       }
12512       goto release;
12513     }
12514
12515 #if 0
12516     /* VR - What is this?! */
12517     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12518       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12519       
12520       if(aopIdx(AOP(result),0) == 4) {
12521         /* this is a workaround to save value of right into wreg too,
12522          * value of wreg is going to be used later */
12523         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12524         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12525         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12526         goto release;
12527       } else
12528 //      assert(0);
12529       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12530     }
12531 #endif
12532
12533   know_W=-1;
12534   while (size--) {
12535     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12536     if(AOP_TYPE(right) == AOP_LIT) {
12537       if(lit&0xff) {
12538         if(know_W != (lit&0xff))
12539           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12540         know_W = lit&0xff;
12541         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12542       } else
12543         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12544
12545       lit >>= 8;
12546
12547     } else if (AOP_TYPE(right) == AOP_CRY) {
12548       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12549       if(offset == 0) {
12550         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12551         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12552         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12553       }
12554     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12555         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12556         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12557     } else {
12558       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12559
12560       if(!_G.resDirect) {                                               /* use this aopForSym feature */
12561           if(AOP_TYPE(result) == AOP_ACC) {
12562             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12563           } else
12564           if(AOP_TYPE(right) == AOP_ACC) {
12565             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12566           } else {
12567             pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12568           }
12569       }
12570     }
12571       
12572       offset++;
12573     }
12574   
12575 release:
12576   pic16_freeAsmop (right,NULL,ic,FALSE);
12577   pic16_freeAsmop (result,NULL,ic,TRUE);
12578
12579
12580 /*-----------------------------------------------------------------*/
12581 /* genJumpTab - generates code for jump table                       */
12582 /*-----------------------------------------------------------------*/
12583 static void genJumpTab (iCode *ic)
12584 {
12585   symbol *jtab;
12586   char *l;
12587   pCodeOp *jt_offs;
12588   pCodeOp *jt_offs_hi;
12589   pCodeOp *jt_label;
12590
12591     FENTRY;
12592
12593     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12594     /* get the condition into accumulator */
12595     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12596     MOVA(l);
12597     /* multiply by three */
12598     pic16_emitcode("add","a,acc");
12599     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12600
12601     jtab = newiTempLabel(NULL);
12602     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12603     pic16_emitcode("jmp","@a+dptr");
12604     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12605
12606 #if 0
12607     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12608     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12609     emitSKPNC;
12610     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12611     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12612     pic16_emitpLabel(jtab->key);
12613
12614 #else
12615
12616     jt_offs = pic16_popGetTempReg(0);
12617     jt_offs_hi = pic16_popGetTempReg(1);
12618     jt_label = pic16_popGetLabel (jtab->key);
12619     //fprintf (stderr, "Creating jump table...\n");
12620
12621     // calculate offset into jump table (idx * sizeof (GOTO))
12622     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12623     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12624     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12625     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12626     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12627     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12628     pic16_emitpcode(POC_MOVWF , jt_offs);
12629
12630     // prepare PCLATx (set to first entry in jump table)
12631     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12632     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12633     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12634     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12635     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12636
12637     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12638     pic16_emitpcode(POC_ADDWF , jt_offs);
12639     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12640     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12641     emitSKPNC;
12642     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12643
12644     // release temporaries and prepare jump into table (new PCL --> WREG)
12645     pic16_emitpcode(POC_MOVFW , jt_offs);
12646     pic16_popReleaseTempReg (jt_offs_hi, 1);
12647     pic16_popReleaseTempReg (jt_offs, 0);
12648
12649     // jump into the table
12650     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12651
12652     pic16_emitpLabelFORCE(jtab->key);
12653 #endif
12654
12655     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12656 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12657
12658     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12659     /* now generate the jump labels */
12660     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12661          jtab = setNextItem(IC_JTLABELS(ic))) {
12662 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12663         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12664         
12665     }
12666     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12667
12668 }
12669
12670 /*-----------------------------------------------------------------*/
12671 /* genMixedOperation - gen code for operators between mixed types  */
12672 /*-----------------------------------------------------------------*/
12673 /*
12674   TSD - Written for the PIC port - but this unfortunately is buggy.
12675   This routine is good in that it is able to efficiently promote 
12676   types to different (larger) sizes. Unfortunately, the temporary
12677   variables that are optimized out by this routine are sometimes
12678   used in other places. So until I know how to really parse the 
12679   iCode tree, I'm going to not be using this routine :(.
12680 */
12681 static int genMixedOperation (iCode *ic)
12682 {
12683 #if 0
12684   operand *result = IC_RESULT(ic);
12685   sym_link *ctype = operandType(IC_LEFT(ic));
12686   operand *right = IC_RIGHT(ic);
12687   int ret = 0;
12688   int big,small;
12689   int offset;
12690
12691   iCode *nextic;
12692   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12693
12694   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12695
12696   nextic = ic->next;
12697   if(!nextic)
12698     return 0;
12699
12700   nextright = IC_RIGHT(nextic);
12701   nextleft  = IC_LEFT(nextic);
12702   nextresult = IC_RESULT(nextic);
12703
12704   pic16_aopOp(right,ic,FALSE);
12705   pic16_aopOp(result,ic,FALSE);
12706   pic16_aopOp(nextright,  nextic, FALSE);
12707   pic16_aopOp(nextleft,   nextic, FALSE);
12708   pic16_aopOp(nextresult, nextic, FALSE);
12709
12710   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12711
12712     operand *t = right;
12713     right = nextright;
12714     nextright = t; 
12715
12716     pic16_emitcode(";remove right +","");
12717
12718   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12719 /*
12720     operand *t = right;
12721     right = nextleft;
12722     nextleft = t; 
12723 */
12724     pic16_emitcode(";remove left +","");
12725   } else
12726     return 0;
12727
12728   big = AOP_SIZE(nextleft);
12729   small = AOP_SIZE(nextright);
12730
12731   switch(nextic->op) {
12732
12733   case '+':
12734     pic16_emitcode(";optimize a +","");
12735     /* if unsigned or not an integral type */
12736     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12737       pic16_emitcode(";add a bit to something","");
12738     } else {
12739
12740       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12741
12742       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12743         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12744         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12745       } else
12746         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12747
12748       offset = 0;
12749       while(--big) {
12750
12751         offset++;
12752
12753         if(--small) {
12754           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12755             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12756             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12757           }
12758
12759           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12760           emitSKPNC;
12761           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12762                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12763                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12764           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12765           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12766
12767         } else {
12768           pic16_emitcode("rlf","known_zero,w");
12769
12770           /*
12771             if right is signed
12772               btfsc  right,7
12773                addlw ff
12774           */
12775           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12776             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12777             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12778           } else {
12779             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12780           }
12781         }
12782       }
12783       ret = 1;
12784     }
12785   }
12786   ret = 1;
12787
12788 release:
12789   pic16_freeAsmop(right,NULL,ic,TRUE);
12790   pic16_freeAsmop(result,NULL,ic,TRUE);
12791   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12792   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12793   if(ret)
12794     nextic->generated = 1;
12795
12796   return ret;
12797 #else
12798   return 0;
12799 #endif
12800 }
12801 /*-----------------------------------------------------------------*/
12802 /* genCast - gen code for casting                                  */
12803 /*-----------------------------------------------------------------*/
12804 static void genCast (iCode *ic)
12805 {
12806   operand *result = IC_RESULT(ic);
12807   sym_link *ctype = operandType(IC_LEFT(ic));
12808   sym_link *rtype = operandType(IC_RIGHT(ic));
12809   sym_link *restype = operandType(IC_RESULT(ic));
12810   operand *right = IC_RIGHT(ic);
12811   int size, offset ;
12812
12813
12814     FENTRY;
12815
12816         /* if they are equivalent then do nothing */
12817 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12818 //              return ;
12819
12820         pic16_aopOp(result,ic,FALSE);
12821         pic16_aopOp(right,ic,FALSE) ;
12822
12823         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12824
12825
12826         /* if the result is a bit */
12827         if (AOP_TYPE(result) == AOP_CRY) {
12828         
12829                 /* if the right size is a literal then
12830                  * we know what the value is */
12831                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12832
12833                 if (AOP_TYPE(right) == AOP_LIT) {
12834                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12835                                 pic16_popGet(AOP(result),0));
12836
12837                         if (((int) operandLitValue(right))) 
12838                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12839                                         AOP(result)->aopu.aop_dir,
12840                                         AOP(result)->aopu.aop_dir);
12841                         else
12842                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12843                                         AOP(result)->aopu.aop_dir,
12844                                         AOP(result)->aopu.aop_dir);
12845                         goto release;
12846                 }
12847
12848                 /* the right is also a bit variable */
12849                 if (AOP_TYPE(right) == AOP_CRY) {
12850                         emitCLRC;
12851                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12852
12853                         pic16_emitcode("clrc","");
12854                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12855                                 AOP(right)->aopu.aop_dir,
12856                                 AOP(right)->aopu.aop_dir);
12857                         pic16_aopPut(AOP(result),"c",0);
12858                         goto release ;
12859                 }
12860
12861                 /* we need to or */
12862                 if (AOP_TYPE(right) == AOP_REG) {
12863                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12864                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12865                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12866                 }
12867                 pic16_toBoolean(right);
12868                 pic16_aopPut(AOP(result),"a",0);
12869                 goto release ;
12870         }
12871
12872         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12873           int offset = 1;
12874
12875                 size = AOP_SIZE(result);
12876
12877                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12878
12879                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12880                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12881                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12882
12883                 while (size--)
12884                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12885
12886                 goto release;
12887         }
12888
12889         if(IS_BITFIELD(getSpec(restype))
12890           && IS_BITFIELD(getSpec(rtype))) {
12891           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12892         }
12893         
12894         /* port from pic14 to cope with generic pointers */
12895         if (PIC_IS_TAGGED(restype))
12896         {
12897           operand *result = IC_RESULT(ic);
12898           //operand *left = IC_LEFT(ic);
12899           operand *right = IC_RIGHT(ic);
12900           int tag = 0xff;
12901
12902           /* copy common part */
12903           int max, size = AOP_SIZE(result);
12904           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12905           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12906
12907           max = size;
12908           while (size--)
12909           {
12910             pic16_mov2w (AOP(right), size);
12911             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12912           } // while
12913
12914           /* upcast into generic pointer type? */
12915           if (IS_GENPTR(restype)
12916               && !PIC_IS_TAGGED(rtype)
12917               && (AOP_SIZE(result) > max))
12918           {
12919             /* determine appropriate tag for right */
12920             if (PIC_IS_DATA_PTR(rtype))
12921               tag = GPTR_TAG_DATA;
12922             else if (IS_CODEPTR(rtype))
12923               tag = GPTR_TAG_CODE;
12924             else if (PIC_IS_DATA_PTR(ctype)) {
12925               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12926               tag = GPTR_TAG_DATA;
12927             } else if (IS_CODEPTR(ctype)) {
12928               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12929               tag = GPTR_TAG_CODE;
12930             } else if (IS_PTR(rtype)) {
12931               PERFORM_ONCE(weirdcast,
12932               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12933               );
12934               tag = GPTR_TAG_DATA;
12935             } else {
12936               PERFORM_ONCE(weirdcast,
12937               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12938               );
12939               tag = GPTR_TAG_DATA;
12940             }
12941
12942             assert (AOP_SIZE(result) == 3);
12943             /* zero-extend address... */
12944             for (size = max; size < AOP_SIZE(result)-1; size++)
12945               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12946             /* ...and add tag */
12947             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12948           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12949             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12950             for (size = max; size < AOP_SIZE(result)-1; size++)
12951               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12952             /* add __code tag */
12953             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12954           } else if (AOP_SIZE(result) > max) {
12955             /* extend non-pointers */
12956             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12957             pic16_addSign(result, max, 0);
12958           } // if
12959           goto release;
12960         }
12961
12962         /* if they are the same size : or less */
12963         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12964
12965                 /* if they are in the same place */
12966                 if (pic16_sameRegs(AOP(right),AOP(result)))
12967                         goto release;
12968
12969                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12970 #if 0
12971                 if (IS_PTR_CONST(rtype))
12972 #else
12973                 if (IS_CODEPTR(rtype))
12974 #endif
12975                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12976
12977 #if 0
12978                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12979 #else
12980                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12981 #endif
12982                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12983
12984 #if 0
12985                 if(AOP_TYPE(right) == AOP_IMMD) {
12986                   pCodeOp *pcop0, *pcop1, *pcop2;
12987                   symbol *sym = OP_SYMBOL( right );
12988
12989                         size = AOP_SIZE(result);
12990                         /* low */
12991                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12992                         /* high */
12993                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12994                         /* upper */
12995                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12996         
12997                         if (size == 3) {
12998                                 pic16_emitpcode(POC_MOVLW, pcop0);
12999                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13000                                 pic16_emitpcode(POC_MOVLW, pcop1);
13001                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13002                                 pic16_emitpcode(POC_MOVLW, pcop2);
13003                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13004                         } else
13005                         if (size == 2) {
13006                                 pic16_emitpcode(POC_MOVLW, pcop0);
13007                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13008                                 pic16_emitpcode(POC_MOVLW, pcop1);
13009                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13010                         } else {
13011                                 pic16_emitpcode(POC_MOVLW, pcop0);
13012                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13013                         }
13014                 } else
13015 #endif
13016                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13017                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13018                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13019                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13020                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13021                         if(AOP_SIZE(result) <2)
13022                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
13023                 } else {
13024                         /* if they in different places then copy */
13025                         size = AOP_SIZE(result);
13026                         offset = 0 ;
13027                         while (size--) {
13028                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13029                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13030                                 offset++;
13031                         }
13032                 }
13033                 goto release;
13034         }
13035
13036         /* if the result is of type pointer */
13037         if (IS_PTR(ctype)) {
13038           int p_type;
13039           sym_link *type = operandType(right);
13040           sym_link *etype = getSpec(type);
13041
13042                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13043
13044                 /* pointer to generic pointer */
13045                 if (IS_GENPTR(ctype)) {
13046                   char *l = zero;
13047             
13048                         if (IS_PTR(type)) 
13049                                 p_type = DCL_TYPE(type);
13050                         else {
13051                 /* we have to go by the storage class */
13052                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13053
13054 /*              if (SPEC_OCLS(etype)->codesp )  */
13055 /*                  p_type = CPOINTER ;  */
13056 /*              else */
13057 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13058 /*                      p_type = FPOINTER ; */
13059 /*                  else */
13060 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13061 /*                          p_type = PPOINTER; */
13062 /*                      else */
13063 /*                          if (SPEC_OCLS(etype) == idata ) */
13064 /*                              p_type = IPOINTER ; */
13065 /*                          else */
13066 /*                              p_type = POINTER ; */
13067             }
13068                 
13069             /* the first two bytes are known */
13070       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13071             size = GPTRSIZE - 1; 
13072             offset = 0 ;
13073             while (size--) {
13074               if(offset < AOP_SIZE(right)) {
13075                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13076                 pic16_mov2f(AOP(result), AOP(right), offset);
13077 /*
13078                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13079                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13080                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13081                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13082                 } else { 
13083                   
13084                   pic16_aopPut(AOP(result),
13085                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13086                          offset);
13087                 }
13088 */
13089               } else 
13090                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13091               offset++;
13092             }
13093             /* the last byte depending on type */
13094             switch (p_type) {
13095             case IPOINTER:
13096             case POINTER:
13097             case FPOINTER:
13098                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13099                 break;
13100
13101             case CPOINTER:
13102                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13103                 break;
13104
13105             case PPOINTER:
13106               pic16_emitcode(";BUG!? ","%d",__LINE__);
13107                 l = "#0x03";
13108                 break;
13109
13110             case GPOINTER:
13111                 if (GPTRSIZE > AOP_SIZE(right)) {
13112                   // assume __data pointer... THIS MIGHT BE WRONG!
13113                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13114                 } else {
13115                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13116                 }
13117               break;
13118               
13119             default:
13120                 /* this should never happen */
13121                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13122                        "got unknown pointer type");
13123                 exit(1);
13124             }
13125             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13126             goto release ;
13127         }
13128         
13129         
13130         assert( 0 );
13131         /* just copy the pointers */
13132         size = AOP_SIZE(result);
13133         offset = 0 ;
13134         while (size--) {
13135             pic16_aopPut(AOP(result),
13136                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13137                    offset);
13138             offset++;
13139         }
13140         goto release ;
13141     }
13142     
13143
13144
13145     /* so we now know that the size of destination is greater
13146     than the size of the source.
13147     Now, if the next iCode is an operator then we might be
13148     able to optimize the operation without performing a cast.
13149     */
13150     if(genMixedOperation(ic))
13151       goto release;
13152
13153     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13154     
13155     /* we move to result for the size of source */
13156     size = AOP_SIZE(right);
13157     offset = 0 ;
13158
13159     while (size--) {
13160       if(!_G.resDirect)
13161         pic16_mov2f(AOP(result), AOP(right), offset);
13162       offset++;
13163     }
13164
13165     /* now depending on the sign of the destination */
13166     size = AOP_SIZE(result) - AOP_SIZE(right);
13167     /* if unsigned or not an integral type */
13168     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13169       while (size--)
13170         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13171     } else {
13172       /* we need to extend the sign :( */
13173
13174       if(size == 1) {
13175         /* Save one instruction of casting char to int */
13176         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13177         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13178         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13179       } else {
13180         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13181
13182         if(offset)
13183           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13184         else
13185           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13186         
13187         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13188
13189         while (size--)
13190           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13191       }
13192     }
13193
13194 release:
13195     pic16_freeAsmop(right,NULL,ic,TRUE);
13196     pic16_freeAsmop(result,NULL,ic,TRUE);
13197
13198 }
13199
13200 /*-----------------------------------------------------------------*/
13201 /* genDjnz - generate decrement & jump if not zero instrucion      */
13202 /*-----------------------------------------------------------------*/
13203 static int genDjnz (iCode *ic, iCode *ifx)
13204 {
13205     symbol *lbl, *lbl1;
13206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13207
13208     if (!ifx)
13209         return 0;
13210     
13211     /* if the if condition has a false label
13212        then we cannot save */
13213     if (IC_FALSE(ifx))
13214         return 0;
13215
13216     /* if the minus is not of the form 
13217        a = a - 1 */
13218     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13219         !IS_OP_LITERAL(IC_RIGHT(ic)))
13220         return 0;
13221
13222     if (operandLitValue(IC_RIGHT(ic)) != 1)
13223         return 0;
13224
13225     /* if the size of this greater than one then no
13226        saving */
13227     if (getSize(operandType(IC_RESULT(ic))) > 1)
13228         return 0;
13229
13230     /* otherwise we can save BIG */
13231     lbl = newiTempLabel(NULL);
13232     lbl1= newiTempLabel(NULL);
13233
13234     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13235     
13236     if (IS_AOP_PREG(IC_RESULT(ic))) {
13237         pic16_emitcode("dec","%s",
13238                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13239         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13240         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13241     } else {    
13242
13243
13244       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13245       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13246
13247       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13248       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13249
13250     }
13251     
13252     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13253     ifx->generated = 1;
13254     return 1;
13255 }
13256
13257 /*-----------------------------------------------------------------*/
13258 /* genReceive - generate code for a receive iCode                  */
13259 /*-----------------------------------------------------------------*/
13260 static void genReceive (iCode *ic)
13261 {    
13262
13263   FENTRY;
13264
13265 #if 0
13266   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13267         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13268 #endif
13269 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13270
13271   if (isOperandInFarSpace(IC_RESULT(ic))
13272       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13273           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13274
13275     int size = getSize(operandType(IC_RESULT(ic)));
13276     int offset =  pic16_fReturnSizePic - size;
13277
13278       assert( 0 );
13279       while (size--) {
13280         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13281                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13282                       offset++;
13283         }
13284
13285       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13286
13287       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13288       size = AOP_SIZE(IC_RESULT(ic));
13289       offset = 0;
13290       while (size--) {
13291         pic16_emitcode ("pop","acc");
13292         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13293       }
13294   } else {
13295     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13296     _G.accInUse++;
13297     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13298     _G.accInUse--;
13299
13300     /* set pseudo stack pointer to where it should be - dw*/
13301     GpsuedoStkPtr = ic->parmBytes;
13302
13303     /* setting GpsuedoStkPtr has side effects here: */
13304     assignResultValue(IC_RESULT(ic), 0);
13305   }
13306
13307   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13308 }
13309
13310 /*-----------------------------------------------------------------*/
13311 /* genDummyRead - generate code for dummy read of volatiles        */
13312 /*-----------------------------------------------------------------*/
13313 static void
13314 genDummyRead (iCode * ic)
13315 {
13316   operand *op;
13317   int i;
13318
13319   op = IC_RIGHT(ic);
13320   if (op && IS_SYMOP(op)) {
13321     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13322       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13323       return;
13324     }
13325     pic16_aopOp (op, ic, FALSE);
13326     for (i=0; i < AOP_SIZE(op); i++) {
13327       // may need to protect this from the peepholer -- this is not nice but works...
13328       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13329       pic16_mov2w (AOP(op),i);
13330       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13331     } // for i
13332     pic16_freeAsmop (op, NULL, ic, TRUE);
13333   } else if (op) {
13334     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13335   } // if
13336 }
13337
13338 /*-----------------------------------------------------------------*/
13339 /* genpic16Code - generate code for pic16 based controllers        */
13340 /*-----------------------------------------------------------------*/
13341 /*
13342  * At this point, ralloc.c has gone through the iCode and attempted
13343  * to optimize in a way suitable for a PIC. Now we've got to generate
13344  * PIC instructions that correspond to the iCode.
13345  *
13346  * Once the instructions are generated, we'll pass through both the
13347  * peep hole optimizer and the pCode optimizer.
13348  *-----------------------------------------------------------------*/
13349
13350 void genpic16Code (iCode *lic)
13351 {
13352   iCode *ic;
13353   int cln = 0;
13354
13355     lineHead = lineCurr = NULL;
13356
13357     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13358     pic16_addpBlock(pb);
13359
13360 #if 0
13361     /* if debug information required */
13362     if (options.debug && currFunc) {
13363       if (currFunc) {
13364         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13365       }
13366     }
13367 #endif
13368
13369     for (ic = lic ; ic ; ic = ic->next ) {
13370
13371       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13372       if ( cln != ic->lineno ) {
13373         if ( options.debug ) {
13374           debugFile->writeCLine (ic);
13375         }
13376         
13377         if(!options.noCcodeInAsm) {
13378           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13379               printCLine(ic->filename, ic->lineno)));
13380         }
13381
13382         cln = ic->lineno ;
13383       }
13384         
13385       if(options.iCodeInAsm) {
13386         char *l;
13387
13388           /* insert here code to print iCode as comment */
13389           l = Safe_strdup(printILine(ic));
13390           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13391       }
13392
13393       /* if the result is marked as
13394        * spilt and rematerializable or code for
13395        * this has already been generated then
13396        * do nothing */
13397       if (resultRemat(ic) || ic->generated ) 
13398         continue ;
13399         
13400       /* depending on the operation */
13401       switch (ic->op) {
13402         case '!' :
13403           pic16_genNot(ic);
13404           break;
13405             
13406         case '~' :
13407           pic16_genCpl(ic);
13408           break;
13409             
13410         case UNARYMINUS:
13411           genUminus (ic);
13412           break;
13413             
13414         case IPUSH:
13415           genIpush (ic);
13416           break;
13417             
13418         case IPOP:
13419           /* IPOP happens only when trying to restore a 
13420            * spilt live range, if there is an ifx statement
13421            * following this pop then the if statement might
13422            * be using some of the registers being popped which
13423            * would destroy the contents of the register so
13424            * we need to check for this condition and handle it */
13425            if (ic->next
13426              && ic->next->op == IFX
13427              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13428                genIfx (ic->next,ic);
13429           else
13430             genIpop (ic);
13431           break; 
13432             
13433         case CALL:
13434           genCall (ic);
13435           break;
13436             
13437         case PCALL:
13438           genPcall (ic);
13439           break;
13440             
13441         case FUNCTION:
13442           genFunction (ic);
13443           break;
13444             
13445         case ENDFUNCTION:
13446           genEndFunction (ic);
13447           break;
13448             
13449         case RETURN:
13450           genRet (ic);
13451           break;
13452             
13453         case LABEL:
13454           genLabel (ic);
13455           break;
13456             
13457         case GOTO:
13458           genGoto (ic);
13459           break;
13460             
13461         case '+' :
13462           pic16_genPlus (ic) ;
13463           break;
13464             
13465         case '-' :
13466           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13467             pic16_genMinus (ic);
13468           break;
13469
13470         case '*' :
13471           genMult (ic);
13472           break;
13473             
13474         case '/' :
13475           genDiv (ic) ;
13476           break;
13477             
13478         case '%' :
13479           genMod (ic);
13480           break;
13481             
13482         case '>' :
13483           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13484           break;
13485             
13486         case '<' :
13487           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13488           break;
13489             
13490         case LE_OP:
13491         case GE_OP:
13492         case NE_OP:
13493           /* note these two are xlated by algebraic equivalence
13494            * during parsing SDCC.y */
13495           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13496             "got '>=' or '<=' shouldn't have come here");
13497           break;
13498
13499         case EQ_OP:
13500           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13501           break;            
13502             
13503         case AND_OP:
13504           genAndOp (ic);
13505           break;
13506             
13507         case OR_OP:
13508           genOrOp (ic);
13509           break;
13510             
13511         case '^' :
13512           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13513           break;
13514             
13515         case '|' :
13516           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13517           break;
13518             
13519         case BITWISEAND:
13520           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13521           break;
13522             
13523         case INLINEASM:
13524           genInline (ic);
13525           break;
13526             
13527         case RRC:
13528           genRRC (ic);
13529           break;
13530             
13531         case RLC:
13532           genRLC (ic);
13533           break;
13534             
13535         case GETHBIT:
13536           genGetHbit (ic);
13537           break;
13538             
13539         case LEFT_OP:
13540           genLeftShift (ic);
13541           break;
13542             
13543         case RIGHT_OP:
13544           genRightShift (ic);
13545           break;
13546             
13547         case GET_VALUE_AT_ADDRESS:
13548           genPointerGet(ic);
13549           break;
13550             
13551         case '=' :
13552           if (POINTER_SET(ic))
13553             genPointerSet(ic);
13554           else
13555             genAssign(ic);
13556           break;
13557             
13558         case IFX:
13559           genIfx (ic,NULL);
13560           break;
13561             
13562         case ADDRESS_OF:
13563           genAddrOf (ic);
13564           break;
13565             
13566         case JUMPTABLE:
13567           genJumpTab (ic);
13568           break;
13569             
13570         case CAST:
13571           genCast (ic);
13572           break;
13573             
13574         case RECEIVE:
13575           genReceive(ic);
13576           break;
13577             
13578         case SEND:
13579           addSet(&_G.sendSet,ic);
13580           break;
13581
13582         case DUMMY_READ_VOLATILE:
13583           genDummyRead (ic);
13584           break;
13585
13586         default :
13587           ic = ic;
13588       }
13589     }
13590
13591
13592     /* now we are ready to call the
13593        peep hole optimizer */
13594     if (!options.nopeep)
13595       peepHole (&lineHead);
13596
13597     /* now do the actual printing */
13598     printLine (lineHead, codeOutFile);
13599
13600 #ifdef PCODE_DEBUG
13601     DFPRINTF((stderr,"printing pBlock\n\n"));
13602     pic16_printpBlock(stdout,pb);
13603 #endif
13604
13605     return;
13606 }
13607