* src/pic/{gen.c,main.h,pcode.c},
[fw/sdcc] / src / pic16 / gen.c
1  /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
10   Bug Fixes  -  Raphael Neider rneider@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           for(i=0;i<aop->size;i++) {
711             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
712             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
713           }
714         }
715
716
717 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
718
719 #if 1
720         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
721
722         // we do not need to load the value if it is to be defined...
723         if (result) return aop;
724
725         if(_G.accInUse) {
726                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
727         }
728         
729         for(i=0;i<aop->size;i++) {
730
731           /* initialise for stack access via frame pointer */
732           // operands on stack are accessible via "{FRAME POINTER} + index" with index
733           // starting at 2 for arguments and growing from 0 downwards for
734           // local variables (index == 0 is not assigned so we add one here)
735           {
736             int soffs = sym->stack;
737             if (soffs <= 0) {
738               assert (soffs < 0);
739               soffs++;
740             } // if
741
742             if(1 && ic->op == SEND) {
743               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
744               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
745                     pic16_popCopyReg( pic16_frame_plusw ),
746                     pic16_popCopyReg(pic16_stack_postdec )));
747             } else {
748               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
749               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
750                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
751             }
752           }
753         }
754         
755         if(_G.accInUse) {
756                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
757         }
758         
759         return (aop);
760 #endif
761
762 #if 0
763         /* now assign the address of the variable to 
764         the pointer register */
765         if (aop->type != AOP_STK) {
766
767             if (sym->onStack) {
768                     if ( _G.accInUse )
769                         pic16_emitcode("push","acc");
770
771                     pic16_emitcode("mov","a,_bp");
772                     pic16_emitcode("add","a,#0x%02x",
773                              ((sym->stack < 0) ?
774                               ((char)(sym->stack - _G.nRegsSaved )) :
775                               ((char)sym->stack)) & 0xff);
776                     pic16_emitcode("mov","%s,a",
777                              aop->aopu.aop_ptr->name);
778
779                     if ( _G.accInUse )
780                         pic16_emitcode("pop","acc");
781             } else
782                 pic16_emitcode("mov","%s,#%s",
783                          aop->aopu.aop_ptr->name,
784                          sym->rname);
785             aop->paged = space->paged;
786         } else
787             aop->aopu.aop_stk = sym->stack;
788         return aop;
789 #endif
790
791     }
792 #endif
793
794 #if 0
795     if (sym->onStack && options.stack10bit)
796     {
797         /* It's on the 10 bit stack, which is located in
798          * far data space.
799          */
800          
801       //DEBUGpic16_emitcode(";","%d",__LINE__);
802
803         if ( _G.accInUse )
804                 pic16_emitcode("push","acc");
805
806         pic16_emitcode("mov","a,_bp");
807         pic16_emitcode("add","a,#0x%02x",
808                  ((sym->stack < 0) ?
809                    ((char)(sym->stack - _G.nRegsSaved )) :
810                    ((char)sym->stack)) & 0xff);
811         
812         genSetDPTR(1);
813         pic16_emitcode ("mov","dpx1,#0x40");
814         pic16_emitcode ("mov","dph1,#0x00");
815         pic16_emitcode ("mov","dpl1, a");
816         genSetDPTR(0);
817         
818         if ( _G.accInUse )
819             pic16_emitcode("pop","acc");
820             
821         sym->aop = aop = newAsmop(AOP_DPTR2);
822         aop->size = getSize(sym->type); 
823         return aop;
824     }
825 #endif
826
827 #if 1
828     /* special case for a function */
829     if (IS_FUNC(sym->type)) {   
830         sym->aop = aop = newAsmop(AOP_PCODE);
831         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
832         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
833         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
834         PCOI(aop->aopu.pcop)->index = 0;
835         aop->size = FPTRSIZE; 
836         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
837         return aop;
838     }
839 #endif
840
841
842
843     //DEBUGpic16_emitcode(";","%d",__LINE__);
844     /* if in bit space */
845     if (IN_BITSPACE(space)) {
846         sym->aop = aop = newAsmop (AOP_CRY);
847         aop->aopu.aop_dir = sym->rname ;
848         aop->size = getSize(sym->type);
849         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
850         return aop;
851     }
852     /* if it is in direct space */
853     if (IN_DIRSPACE(space)) {
854                 if(!strcmp(sym->rname, "_WREG")) {
855                         sym->aop = aop = newAsmop (AOP_ACC);
856                         aop->size = getSize(sym->type);         /* should always be 1 */
857                         assert(aop->size == 1);
858                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
859                         return (aop);
860                 } else {
861                         sym->aop = aop = newAsmop (AOP_DIR);
862                 aop->aopu.aop_dir = sym->rname ;
863             aop->size = getSize(sym->type);
864                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
865                         pic16_allocDirReg( IC_LEFT(ic) );
866                         return (aop);
867                 }
868         }
869
870     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
871         sym->aop = aop = newAsmop (AOP_DIR);
872         aop->aopu.aop_dir = sym->rname ;
873         aop->size = getSize(sym->type);
874         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
875         pic16_allocDirReg( IC_LEFT(ic) );
876         return aop;
877     }
878
879
880     /* only remaining is far space */
881     sym->aop = aop = newAsmop(AOP_PCODE);
882
883 /* change the next if to 1 to revert to good old immediate code */
884         if(IN_CODESPACE(space)) {
885                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
886                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
887                 PCOI(aop->aopu.pcop)->index = 0;
888         } else {
889                 /* try to allocate via direct register */
890                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
891 //              aop->size = getSize( sym->type );
892         }
893
894         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
895                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
896
897 #if 0
898         if(!pic16_allocDirReg (IC_LEFT(ic)))
899                 return NULL;
900 #endif
901
902         if(IN_DIRSPACE( space ))
903                 aop->size = PTRSIZE;
904         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
905                 aop->size = FPTRSIZE;
906         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
907         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
908         else if(sym->onStack) {
909                 aop->size = PTRSIZE;
910         } else {
911           if(SPEC_SCLS(sym->etype) == S_PDATA) {
912             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
913             aop->size = FPTRSIZE;
914           } else
915                 assert( 0 );
916         }
917
918     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
919
920     /* if it is in code space */
921     if (IN_CODESPACE(space))
922         aop->code = 1;
923
924     return aop;     
925 }
926
927 /*-----------------------------------------------------------------*/
928 /* aopForRemat - rematerialzes an object                           */
929 /*-----------------------------------------------------------------*/
930 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
931 {
932   symbol *sym = OP_SYMBOL(op);
933   operand *refop;
934   iCode *ic = NULL, *oldic;
935   asmop *aop = newAsmop(AOP_PCODE);
936   int val = 0;
937   int offset = 0;
938   int viaimmd=0;
939
940     FENTRY2;
941     
942         ic = sym->rematiCode;
943
944         if(IS_OP_POINTER(op)) {
945                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
946         }
947
948 //    if(!result)               /* fixme-vr */
949         for (;;) {
950                 oldic = ic;
951
952 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
953         
954                 if (ic->op == '+') {
955                         val += (int) operandLitValue(IC_RIGHT(ic));
956                 } else if (ic->op == '-') {
957                         val -= (int) operandLitValue(IC_RIGHT(ic));
958                 } else
959                         break;
960                 
961                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
962         }
963
964         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
965         refop = IC_LEFT(ic);
966
967         if(!op->isaddr)viaimmd++; else viaimmd=0;
968                 
969 /* set the following if to 1 to revert to good old immediate code */
970         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
971                 || viaimmd) {
972
973                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
974
975                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
976
977 #if 0
978                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
979 #else
980                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
981 #endif
982
983                 PCOI(aop->aopu.pcop)->index = val;
984                 
985                 aop->size = getSize( sym->type );
986         } else {
987                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
988
989                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
990                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
991
992                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
993         }
994
995
996         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
997                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
998 #if 0
999                 val, IS_PTR_CONST(operandType(op)));
1000 #else
1001                 val, IS_CODEPTR(operandType(op)));
1002 #endif
1003
1004 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1005
1006         pic16_allocDirReg (IC_LEFT(ic));
1007
1008         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1009                 aop->code = 1;
1010
1011   return aop;        
1012 }
1013
1014 #if 0
1015 static int aopIdx (asmop *aop, int offset)
1016 {
1017   if(!aop)
1018     return -1;
1019
1020   if(aop->type !=  AOP_REG)
1021     return -2;
1022         
1023   return aop->aopu.aop_reg[offset]->rIdx;
1024
1025 }
1026 #endif
1027
1028 /*-----------------------------------------------------------------*/
1029 /* regsInCommon - two operands have some registers in common       */
1030 /*-----------------------------------------------------------------*/
1031 static bool regsInCommon (operand *op1, operand *op2)
1032 {
1033     symbol *sym1, *sym2;
1034     int i;
1035
1036     /* if they have registers in common */
1037     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1038         return FALSE ;
1039
1040     sym1 = OP_SYMBOL(op1);
1041     sym2 = OP_SYMBOL(op2);
1042
1043     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1044         return FALSE ;
1045
1046     for (i = 0 ; i < sym1->nRegs ; i++) {
1047         int j;
1048         if (!sym1->regs[i])
1049             continue ;
1050
1051         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1052             if (!sym2->regs[j])
1053                 continue ;
1054
1055             if (sym2->regs[j] == sym1->regs[i])
1056                 return TRUE ;
1057         }
1058     }
1059
1060     return FALSE ;
1061 }
1062
1063 /*-----------------------------------------------------------------*/
1064 /* operandsEqu - equivalent                                        */
1065 /*-----------------------------------------------------------------*/
1066 static bool operandsEqu ( operand *op1, operand *op2)
1067 {
1068     symbol *sym1, *sym2;
1069
1070     /* if they not symbols */
1071     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1072         return FALSE;
1073
1074     sym1 = OP_SYMBOL(op1);
1075     sym2 = OP_SYMBOL(op2);
1076
1077     /* if both are itemps & one is spilt
1078        and the other is not then false */
1079     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1080         sym1->isspilt != sym2->isspilt )
1081         return FALSE ;
1082
1083     /* if they are the same */
1084     if (sym1 == sym2)
1085         return TRUE ;
1086
1087     if (sym1->rname[0] && sym2->rname[0]
1088         && strcmp (sym1->rname, sym2->rname) == 0)
1089         return TRUE;
1090
1091
1092     /* if left is a tmp & right is not */
1093     if (IS_ITEMP(op1)  && 
1094         !IS_ITEMP(op2) &&
1095         sym1->isspilt  &&
1096         (sym1->usl.spillLoc == sym2))
1097         return TRUE;
1098
1099     if (IS_ITEMP(op2)  && 
1100         !IS_ITEMP(op1) &&
1101         sym2->isspilt  &&
1102         sym1->level > 0 &&
1103         (sym2->usl.spillLoc == sym1))
1104         return TRUE ;
1105
1106     return FALSE ;
1107 }
1108
1109 /*-----------------------------------------------------------------*/
1110 /* pic16_sameRegs - two asmops have the same registers                   */
1111 /*-----------------------------------------------------------------*/
1112 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1113 {
1114     int i;
1115
1116     if (aop1 == aop2)
1117         return TRUE ;
1118
1119     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1120                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1121
1122     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1123
1124     if (aop1->type != AOP_REG ||
1125         aop2->type != AOP_REG )
1126         return FALSE ;
1127
1128     /* This is a bit too restrictive if one is a subset of the other...
1129     if (aop1->size != aop2->size )
1130         return FALSE ;
1131     */
1132
1133     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1134 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1135
1136 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1137         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1138             return FALSE ;
1139     }
1140
1141     return TRUE ;
1142 }
1143
1144 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1145 {
1146     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1147                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1148
1149     if(aop1 == aop2)return TRUE;
1150     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1151       
1152       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1153     
1154   return TRUE;
1155 }
1156
1157
1158 /*-----------------------------------------------------------------*/
1159 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1160 /*-----------------------------------------------------------------*/
1161 void pic16_aopOp (operand *op, iCode *ic, bool result)
1162 {
1163     asmop *aop;
1164     symbol *sym;
1165     int i;
1166
1167     if (!op)
1168         return ;
1169
1170     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1171
1172     /* if this a literal */
1173     if (IS_OP_LITERAL(op)) {
1174         op->aop = aop = newAsmop(AOP_LIT);
1175         aop->aopu.aop_lit = op->operand.valOperand;
1176         aop->size = getSize(operandType(op));
1177         return;
1178     }
1179
1180     {
1181       sym_link *type = operandType(op);
1182 #if 0
1183       if(IS_PTR_CONST(type))
1184 #else
1185       if(IS_CODEPTR(type))
1186 #endif
1187         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1188     }
1189
1190     /* if already has a asmop then continue */
1191     if (op->aop)
1192         return ;
1193
1194     /* if the underlying symbol has a aop */
1195     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1196       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1197         op->aop = OP_SYMBOL(op)->aop;
1198         return;
1199     }
1200
1201     /* if this is a true symbol */
1202     if (IS_TRUE_SYMOP(op)) {    
1203         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1204       op->aop = aopForSym(ic, op, result);
1205       return ;
1206     }
1207
1208     /* this is a temporary : this has
1209     only four choices :
1210     a) register
1211     b) spillocation
1212     c) rematerialize 
1213     d) conditional   
1214     e) can be a return use only */
1215
1216     sym = OP_SYMBOL(op);
1217
1218     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1219     /* if the type is a conditional */
1220     if (sym->regType == REG_CND) {
1221         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1222         aop->size = 0;
1223         return;
1224     }
1225
1226     /* if it is spilt then two situations
1227     a) is rematerialize 
1228     b) has a spill location */
1229     if (sym->isspilt || sym->nRegs == 0) {
1230
1231 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1232       DEBUGpic16_emitcode(";","%d",__LINE__);
1233         /* rematerialize it NOW */
1234         if (sym->remat) {
1235
1236             sym->aop = op->aop = aop = aopForRemat (op, result);
1237 //            aop->size = getSize(sym->type);
1238 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1239             return;
1240         }
1241
1242 #if 1
1243         if (sym->accuse) {
1244             int i;
1245             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1246             aop->size = getSize(sym->type);
1247             for ( i = 0 ; i < 1 ; i++ ) {
1248                 aop->aopu.aop_str[i] = accUse[i];
1249 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1250             }
1251             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1252             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1253             return;  
1254         }
1255 #endif
1256
1257 #if 1
1258         if (sym->ruonly) {
1259           /*
1260           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1261           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1262           //pic16_allocDirReg (IC_LEFT(ic));
1263           aop->size = getSize(sym->type);
1264           */
1265
1266           unsigned i;
1267
1268           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1269           aop->size = getSize(sym->type);
1270           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1271             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1272
1273           DEBUGpic16_emitcode(";","%d",__LINE__);
1274           return;
1275         }
1276 #endif
1277         /* else spill location  */
1278         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1279             /* force a new aop if sizes differ */
1280             sym->usl.spillLoc->aop = NULL;
1281         }
1282
1283 #if 0
1284         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1285                             __FUNCTION__,__LINE__,
1286                             sym->usl.spillLoc->rname,
1287                             sym->rname, sym->usl.spillLoc->offset);
1288 #endif
1289
1290         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1291         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1292         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1293           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1294                                                   getSize(sym->type), 
1295                                                   sym->usl.spillLoc->offset, op);
1296         } else {
1297           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1298           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1299           assert (getSize(sym->type) <= 1);
1300           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1301         }
1302         aop->size = getSize(sym->type);
1303
1304         return;
1305     }
1306
1307     {
1308       sym_link *type = operandType(op);
1309 #if 0
1310       if(IS_PTR_CONST(type)) 
1311 #else
1312       if(IS_CODEPTR(type)) 
1313 #endif
1314         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1315     }
1316
1317     /* must be in a register */
1318     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1319     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1320     aop->size = sym->nRegs;
1321     for ( i = 0 ; i < sym->nRegs ;i++)
1322         aop->aopu.aop_reg[i] = sym->regs[i];
1323 }
1324
1325 /*-----------------------------------------------------------------*/
1326 /* pic16_freeAsmop - free up the asmop given to an operand               */
1327 /*----------------------------------------------------------------*/
1328 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1329 {   
1330     asmop *aop ;
1331
1332     if (!op)
1333         aop = aaop;
1334     else 
1335         aop = op->aop;
1336
1337     if (!aop)
1338         return ;
1339
1340     if (aop->freed)
1341         goto dealloc; 
1342
1343     aop->freed = 1;
1344
1345     /* depending on the asmop type only three cases need work AOP_RO
1346        , AOP_R1 && AOP_STK */
1347 #if 1
1348     switch (aop->type) {
1349         case AOP_FSR0 :
1350             if (_G.fsr0Pushed ) {
1351                 if (pop) {
1352                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1353                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1354 //                    pic16_emitcode ("pop","ar0");
1355                     _G.fsr0Pushed--;
1356                 }
1357             }
1358             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1359             break;
1360
1361         case AOP_FSR2 :
1362             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1363             break;
1364
1365         case AOP_R0 :
1366             if (_G.r0Pushed ) {
1367                 if (pop) {
1368                     pic16_emitcode ("pop","ar0");     
1369                     _G.r0Pushed--;
1370                 }
1371             }
1372             bitVectUnSetBit(ic->rUsed,R0_IDX);
1373             break;
1374
1375         case AOP_R1 :
1376             if (_G.r1Pushed ) {
1377                 if (pop) {
1378                     pic16_emitcode ("pop","ar1");
1379                     _G.r1Pushed--;
1380                 }
1381             }
1382             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1383             break;
1384
1385         case AOP_STA:
1386           {
1387             int i;
1388
1389               /* we must store the result on stack */
1390               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1391                 // operands on stack are accessible via "FSR2 + index" with index
1392                 // starting at 2 for arguments and growing from 0 downwards for
1393                 // local variables (index == 0 is not assigned so we add one here)
1394                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1395                 if (soffs <= 0) {
1396                   assert (soffs < 0);
1397                   soffs++;
1398                 } // if
1399                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1400                 for(i=0;i<aop->size;i++) {
1401                   /* initialise for stack access via frame pointer */
1402                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1403                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1404                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1405                 }
1406         
1407                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1408               }
1409
1410               if(!_G.resDirect) {
1411                 for(i=0;i<aop->size;i++) {
1412                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1413
1414                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1415                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1416                 }
1417                   
1418               }
1419               _G.resDirect = 0;
1420           }
1421           break;
1422 #if 0
1423         case AOP_STK :
1424         {
1425             int sz = aop->size;    
1426             int stk = aop->aopu.aop_stk + aop->size;
1427             bitVectUnSetBit(ic->rUsed,R0_IDX);
1428             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1429
1430             getFreePtr(ic,&aop,FALSE);
1431             
1432             if (options.stack10bit)
1433             {
1434                 /* I'm not sure what to do here yet... */
1435                 /* #STUB */
1436                 fprintf(stderr, 
1437                         "*** Warning: probably generating bad code for "
1438                         "10 bit stack mode.\n");
1439             }
1440             
1441             if (stk) {
1442                 pic16_emitcode ("mov","a,_bp");
1443                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1444                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1445             } else {
1446                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1447             }
1448
1449             while (sz--) {
1450                 pic16_emitcode("pop","acc");
1451                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1452                 if (!sz) break;
1453                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1454             }
1455             op->aop = aop;
1456             pic16_freeAsmop(op,NULL,ic,TRUE);
1457             if (_G.r0Pushed) {
1458                 pic16_emitcode("pop","ar0");
1459                 _G.r0Pushed--;
1460             }
1461
1462             if (_G.r1Pushed) {
1463                 pic16_emitcode("pop","ar1");
1464                 _G.r1Pushed--;
1465             }       
1466         }
1467 #endif
1468
1469     }
1470 #endif
1471
1472 dealloc:
1473     /* all other cases just dealloc */
1474     if (op ) {
1475         op->aop = NULL;
1476         if (IS_SYMOP(op)) {
1477             OP_SYMBOL(op)->aop = NULL;    
1478             /* if the symbol has a spill */
1479             if (SPIL_LOC(op))
1480                 SPIL_LOC(op)->aop = NULL;
1481         }
1482     }
1483 }
1484
1485 /*-----------------------------------------------------------------*/
1486 /* pic16_aopGet - for fetching value of the aop                          */
1487 /*-----------------------------------------------------------------*/
1488 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1489 {
1490     char *s = buffer ;
1491     char *rs;
1492
1493     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1494
1495     /* offset is greater than size then zero */
1496     if (offset > (aop->size - 1) &&
1497         aop->type != AOP_LIT)
1498         return zero;
1499
1500     /* depending on type */
1501     switch (aop->type) {
1502
1503     case AOP_FSR0:
1504     case AOP_FSR2:
1505       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1506       rs = Safe_calloc(1, strlen(s)+1);
1507       strcpy(rs, s);
1508       return (rs);
1509       
1510 #if 0
1511       /* if we need to increment it */
1512       while (offset > aop->coff)
1513         {
1514           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1515           aop->coff++;
1516         }
1517
1518       while (offset < aop->coff)
1519         {
1520           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1521           aop->coff--;
1522         }
1523       aop->coff = offset;
1524       if (aop->paged)
1525         {
1526           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1527           return (dname ? "acc" : "a");
1528         }
1529       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1530       rs = Safe_calloc (1, strlen (s) + 1);
1531       strcpy (rs, s);
1532       return rs;
1533 #endif
1534
1535         
1536     case AOP_IMMD:
1537         if (bit16) 
1538             sprintf (s,"%s",aop->aopu.aop_immd);
1539         else
1540             if (offset) 
1541                 sprintf(s,"(%s >> %d)",
1542                         aop->aopu.aop_immd,
1543                         offset*8);
1544             else
1545                 sprintf(s,"%s",
1546                         aop->aopu.aop_immd);
1547         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1548         rs = Safe_calloc(1,strlen(s)+1);
1549         strcpy(rs,s);   
1550         return rs;
1551         
1552     case AOP_DIR:
1553       if (offset) {
1554         sprintf(s,"(%s + %d)",
1555                 aop->aopu.aop_dir,
1556                 offset);
1557         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1558       } else
1559             sprintf(s,"%s",aop->aopu.aop_dir);
1560         rs = Safe_calloc(1,strlen(s)+1);
1561         strcpy(rs,s);   
1562         return rs;
1563         
1564     case AOP_REG:
1565       return aop->aopu.aop_reg[offset]->name;
1566         
1567     case AOP_CRY:
1568       return aop->aopu.aop_dir;
1569         
1570     case AOP_ACC:
1571         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1572 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1573 //        assert( 0 );
1574 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1575         rs = Safe_strdup("WREG");
1576         return (rs);
1577
1578     case AOP_LIT:
1579         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1580         rs = Safe_calloc(1,strlen(s)+1);
1581         strcpy(rs,s);   
1582         return rs;
1583         
1584     case AOP_STR:
1585         aop->coff = offset ;
1586
1587 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1588 //          dname)
1589 //          return "acc";
1590         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1591           aop->type = AOP_ACC;
1592           return Safe_strdup("_WREG");
1593         }
1594         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1595         
1596         return aop->aopu.aop_str[offset];
1597         
1598     case AOP_PCODE:
1599       {
1600         pCodeOp *pcop = aop->aopu.pcop;
1601         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1602         if(pcop->name) {
1603           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1604           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1605           if (offset) {
1606             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1607           } else {
1608             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1609           }
1610         } else
1611           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1612
1613       }
1614       rs = Safe_calloc(1,strlen(s)+1);
1615       strcpy(rs,s);   
1616       return rs;
1617
1618 #if 0
1619     case AOP_PAGED:
1620       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1621       if (offset) {
1622         sprintf(s,"(%s + %d)",
1623                 aop->aopu.aop_dir,
1624                 offset);
1625       } else
1626             sprintf(s,"%s",aop->aopu.aop_dir);
1627       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1628       rs = Safe_calloc(1,strlen(s)+1);
1629       strcpy(rs,s);   
1630       return rs;
1631 #endif
1632
1633     case AOP_STA:
1634         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1635         return (rs);
1636         
1637     case AOP_STK:
1638 //        pCodeOp *pcop = aop->aop
1639         break;
1640
1641     }
1642
1643     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1644     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1645            "aopget got unsupported aop->type");
1646     exit(0);
1647 }
1648
1649
1650
1651 /* lock has the following meaning: When allocating temporary registers
1652  * for stack variables storage, the value of the temporary register is
1653  * saved on stack. Its value is restored at the end. This procedure is
1654  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1655  * a possibility that before a call to pic16_aopOp, a temporary register
1656  * is allocated for a while and it is freed after some time, this will
1657  * mess the stack and values will not be restored properly. So use lock=1
1658  * to allocate temporary registers used internally by the programmer, and
1659  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1660  * to inform the compiler developer about a possible bug. This is an internal
1661  * feature for developing the compiler -- VR */
1662  
1663 int _TempReg_lock = 0;
1664 /*-----------------------------------------------------------------*/
1665 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1666 /*-----------------------------------------------------------------*/
1667 pCodeOp *pic16_popGetTempReg(int lock)
1668 {
1669   pCodeOp *pcop=NULL;
1670   symbol *cfunc;
1671
1672 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1673     if(_TempReg_lock) {
1674 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1675     }
1676     
1677     _TempReg_lock += lock;
1678     
1679     cfunc = currFunc;
1680     currFunc = NULL;
1681
1682 #if 0
1683         {
1684           regs *rr;
1685           int i;
1686
1687                 /* this code might seem better but it does the *same* job with
1688                  * the old code, it all depends on ralloc.c to get a free/unused
1689                  * register */
1690          
1691                 i=0;
1692                 while(i < pic16_nRegs) {
1693                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1694                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1695                         if((!rr || (rr && rr->isFree))
1696                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1697                                 pcop = pic16_newpCodeOpReg( i );
1698                                 PCOR(pcop)->r->wasUsed = 1;
1699                                 PCOR(pcop)->r->isFree = 0;
1700                                 break;
1701                         }
1702                         i++;
1703                 }
1704
1705                 if(pcop) {
1706                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1707                 }
1708         }
1709 #else
1710     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1711     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1712       PCOR(pcop)->r->wasUsed=1;
1713       PCOR(pcop)->r->isFree=0;
1714
1715       /* push value on stack */
1716       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1717     }
1718 #endif
1719
1720     currFunc = cfunc;
1721
1722   return pcop;
1723 }
1724
1725 /*-----------------------------------------------------------------*/
1726 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1727 /*                           is not part of f, but don't save if   */
1728 /*                           inside v                              */
1729 /*-----------------------------------------------------------------*/
1730 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1731 {
1732   pCodeOp *pcop=NULL;
1733   symbol *cfunc;
1734   int i;
1735
1736 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1737
1738     if(_TempReg_lock) {
1739 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1740     }
1741
1742     _TempReg_lock += lock;
1743
1744     cfunc = currFunc;
1745     currFunc = NULL;
1746
1747     i = bitVectFirstBit(f);
1748     while(i < 128) {
1749
1750       /* bypass registers that are used by function */
1751       if(!bitVectBitValue(f, i)) {
1752       
1753         /* bypass registers that are already allocated for stack access */
1754         if(!bitVectBitValue(v, i))  {
1755         
1756 //          debugf("getting register rIdx = %d\n", i);
1757           /* ok, get the operand */
1758           pcop = pic16_newpCodeOpReg( i );
1759     
1760           /* should never by NULL */
1761           assert( pcop != NULL );
1762
1763           
1764           /* sanity check */
1765           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1766             int found=0;
1767             
1768               PCOR(pcop)->r->wasUsed=1;
1769               PCOR(pcop)->r->isFree=0;
1770
1771
1772               {
1773                 regs *sr;
1774               
1775                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1776
1777                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1778                       /* already used in previous steps, break */
1779                       found=1;          
1780                       break;
1781                     }
1782                   }
1783               }
1784
1785               /* caller takes care of the following */
1786 //              bitVectSetBit(v, i);
1787
1788               if(!found) {
1789                 /* push value on stack */
1790                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1791                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1792               }
1793           
1794             break;
1795           }
1796         }
1797       }
1798       i++;
1799     }
1800
1801     currFunc = cfunc;
1802
1803   return pcop;
1804 }
1805
1806
1807 /*-----------------------------------------------------------------*/
1808 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1809 /*-----------------------------------------------------------------*/
1810 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1811 {
1812   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1813
1814   _TempReg_lock -= lock;
1815
1816   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1817     PCOR(pcop)->r->isFree = 1;
1818
1819     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1820   }
1821 }
1822 /*-----------------------------------------------------------------*/
1823 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1824 /*-----------------------------------------------------------------*/
1825 pCodeOp *pic16_popGetLabel(int key)
1826 {
1827
1828   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1829
1830   if(key>max_key)
1831     max_key = key;
1832
1833   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1834 }
1835
1836 /*-----------------------------------------------------------------*/
1837 /* pic16_popCopyReg - copy a pcode operator                              */
1838 /*-----------------------------------------------------------------*/
1839 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1840 {
1841   pCodeOpReg *pcor;
1842
1843   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1844   memcpy (pcor, pc, sizeof (pCodeOpReg));
1845   pcor->r->wasUsed = 1;
1846   
1847   //pcor->pcop.type = pc->pcop.type;
1848   if(pc->pcop.name) {
1849     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1850       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1851   } else
1852     pcor->pcop.name = NULL;
1853
1854   //pcor->r = pc->r;
1855   //pcor->rIdx = pc->rIdx;
1856   //pcor->r->wasUsed=1;
1857   //pcor->instance = pc->instance;
1858
1859 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1860
1861   return PCOP(pcor);
1862 }
1863
1864 /*-----------------------------------------------------------------*/
1865 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1866 /*-----------------------------------------------------------------*/
1867 pCodeOp *pic16_popGetLit(int lit)
1868 {
1869   return pic16_newpCodeOpLit(lit);
1870 }
1871
1872 /*-----------------------------------------------------------------*/
1873 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1874 /*-----------------------------------------------------------------*/
1875 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1876 {
1877   return pic16_newpCodeOpLit2(lit, arg2);
1878 }
1879
1880
1881 /*-----------------------------------------------------------------*/
1882 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1883 /*-----------------------------------------------------------------*/
1884 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1885 {
1886   return pic16_newpCodeOpImmd(name, offset,index, 0);
1887 }
1888
1889
1890 /*-----------------------------------------------------------------*/
1891 /* pic16_popGet - asm operator to pcode operator conversion              */
1892 /*-----------------------------------------------------------------*/
1893 pCodeOp *pic16_popGetWithString(char *str)
1894 {
1895   pCodeOp *pcop;
1896
1897
1898   if(!str) {
1899     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1900     exit (1);
1901   }
1902
1903   pcop = pic16_newpCodeOp(str,PO_STR);
1904
1905   return pcop;
1906 }
1907
1908 /*-----------------------------------------------------------------*/
1909 /* pic16_popRegFromString -                                        */
1910 /*-----------------------------------------------------------------*/
1911 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1912 {
1913
1914   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1915   pcop->type = PO_DIR;
1916
1917   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1918   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1919
1920   if(!str)
1921     str = "BAD_STRING";
1922
1923   pcop->name = Safe_calloc(1,strlen(str)+1);
1924   strcpy(pcop->name,str);
1925
1926   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1927
1928   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1929 //  PCOR(pcop)->r->wasUsed = 1;
1930
1931   /* make sure that register doesn't exist,
1932    * and operand isn't NULL
1933    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1934   if((PCOR(pcop)->r == NULL) 
1935     && (op)
1936     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1937 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1938 //              __FUNCTION__, __LINE__, str, size, offset);
1939
1940     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1941     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1942
1943   }
1944   PCOR(pcop)->instance = offset;
1945
1946   return pcop;
1947 }
1948
1949 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1950 {
1951   pCodeOp *pcop;
1952
1953 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1954 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1955         
1956         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1957         PCOR(pcop)->rIdx = rIdx;
1958         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1959         if(!PCOR(pcop)->r)
1960                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1961                 
1962         PCOR(pcop)->r->isFree = 0;
1963         PCOR(pcop)->r->wasUsed = 1;
1964
1965         pcop->type = PCOR(pcop)->r->pc_type;
1966
1967   return pcop;
1968 }
1969
1970 /*---------------------------------------------------------------------------------*/
1971 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1972 /*                 VR 030601                                                       */
1973 /*---------------------------------------------------------------------------------*/
1974 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1975 {
1976   pCodeOpReg2 *pcop2;
1977   pCodeOp *temp;
1978   
1979         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1980
1981         /* comment the following check, so errors to throw up */
1982 //      if(!pcop2)return NULL;
1983
1984         temp = pic16_popGet(aop_dst, offset);
1985         pcop2->pcop2 = temp;
1986         
1987   return PCOP(pcop2);
1988 }
1989
1990
1991
1992 /*--------------------------------------------------------------------------------.-*/
1993 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1994 /*                  VR 030601 , adapted by Hans Dorn                                */
1995 /*--------------------------------------------------------------------------------.-*/
1996 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1997 {
1998   pCodeOpReg2 *pcop2;
1999  
2000         pcop2 = (pCodeOpReg2 *)src;
2001         pcop2->pcop2 = dst;
2002         
2003         return PCOP(pcop2);
2004 }
2005
2006
2007
2008 /*---------------------------------------------------------------------------------*/
2009 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2010 /*                     movff instruction                                           */
2011 /*---------------------------------------------------------------------------------*/
2012 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2013 {
2014   pCodeOpReg2 *pcop2;
2015
2016         if(!noalloc) {
2017                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
2018                 pcop2->pcop2 = pic16_popCopyReg(dst);
2019         } else {
2020                 /* the pCodeOp may be already allocated */
2021                 pcop2 = (pCodeOpReg2 *)(src);
2022                 pcop2->pcop2 = (pCodeOp *)(dst);
2023         }
2024
2025   return PCOP(pcop2);
2026 }
2027
2028
2029 /*-----------------------------------------------------------------*/
2030 /* pic16_popGet - asm operator to pcode operator conversion              */
2031 /*-----------------------------------------------------------------*/
2032 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2033 {
2034 //  char *s = buffer ;
2035 //  char *rs;
2036   pCodeOp *pcop;
2037
2038         FENTRY2;
2039                 /* offset is greater than
2040                  * size then zero */
2041
2042 //    if (offset > (aop->size - 1) &&
2043 //        aop->type != AOP_LIT)
2044 //      return NULL;  //zero;
2045
2046     /* depending on type */
2047     switch (aop->type) {
2048                 case AOP_R0:
2049                 case AOP_R1:
2050                 case AOP_DPTR:
2051                 case AOP_DPTR2:
2052                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2053                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2054                         assert( 0 );
2055                         return NULL;
2056
2057                 case AOP_FSR0:
2058                 case AOP_FSR2:
2059                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2060                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2061                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2062                         PCOR(pcop)->r->wasUsed = 1;
2063                         PCOR(pcop)->r->isFree = 0;
2064       
2065                         PCOR(pcop)->instance = offset;
2066                         pcop->type = PCOR(pcop)->r->pc_type;
2067                         return (pcop);
2068
2069                 case AOP_IMMD:
2070                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2071                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2072
2073                 case AOP_STA:
2074                         /* pCodeOp is already allocated from aopForSym */
2075                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2076                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2077                         return (pcop);
2078       
2079                 case AOP_ACC:
2080                         {
2081                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2082
2083                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2084
2085                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2086         
2087                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2088                                 PCOR(pcop)->rIdx = rIdx;
2089                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2090                                 PCOR(pcop)->r->wasUsed=1;
2091                                 PCOR(pcop)->r->isFree=0;
2092
2093                                 PCOR(pcop)->instance = offset;
2094                                 pcop->type = PCOR(pcop)->r->pc_type;
2095 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2096                                 return pcop;
2097
2098
2099 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2100 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2101
2102 //      assert( 0 );
2103                         }
2104         
2105     case AOP_DIR:
2106       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2107       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2108         
2109 #if 0
2110     case AOP_PAGED:
2111       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2112       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2113 #endif
2114
2115     case AOP_REG:
2116       {
2117         int rIdx;
2118         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2119         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2120
2121         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2122         
2123         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2124 //      pcop->type = PO_GPR_REGISTER;
2125         PCOR(pcop)->rIdx = rIdx;
2126         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2127         PCOR(pcop)->r->wasUsed=1;
2128         PCOR(pcop)->r->isFree=0;
2129
2130         PCOR(pcop)->instance = offset;
2131         pcop->type = PCOR(pcop)->r->pc_type;
2132         
2133         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2134 //      rs = aop->aopu.aop_reg[offset]->name;
2135 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2136         return pcop;
2137       }
2138
2139     case AOP_CRY:
2140         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2141
2142       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2143       PCOR(pcop)->instance = offset;
2144       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2145       //if(PCOR(pcop)->r == NULL)
2146       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2147       return pcop;
2148         
2149     case AOP_LIT:
2150         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2151       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2152
2153     case AOP_STR:
2154       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2155       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2156
2157       /*
2158       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2159       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2160       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2161       pcop->type = PCOR(pcop)->r->pc_type;
2162       pcop->name = PCOR(pcop)->r->name;
2163
2164       return pcop;
2165       */
2166
2167     case AOP_PCODE:
2168       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2169                           __LINE__, 
2170                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2171       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2172       switch( aop->aopu.pcop->type ) {
2173         case PO_DIR: PCOR(pcop)->instance += offset; break;
2174         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2175         case PO_WREG:
2176             assert (offset==0);
2177             break;
2178         default:
2179           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2180           assert( 0 );  /* should never reach here */;
2181       }
2182       return pcop;
2183     }
2184
2185     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2186            "pic16_popGet got unsupported aop->type");
2187     exit(0);
2188 }
2189 /*-----------------------------------------------------------------*/
2190 /* pic16_aopPut - puts a string for a aop                                */
2191 /*-----------------------------------------------------------------*/
2192 void pic16_aopPut (asmop *aop, char *s, int offset)
2193 {
2194     char *d = buffer ;
2195     symbol *lbl ;
2196
2197     return;
2198
2199     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2200
2201     if (aop->size && offset > ( aop->size - 1)) {
2202         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2203                "pic16_aopPut got offset > aop->size");
2204         exit(0);
2205     }
2206
2207     /* will assign value to value */
2208     /* depending on where it is ofcourse */
2209     switch (aop->type) {
2210     case AOP_DIR:
2211       if (offset) {
2212         sprintf(d,"(%s + %d)",
2213                 aop->aopu.aop_dir,offset);
2214         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2215
2216       } else
2217             sprintf(d,"%s",aop->aopu.aop_dir);
2218         
2219         if (strcmp(d,s)) {
2220           DEBUGpic16_emitcode(";","%d",__LINE__);
2221           if(strcmp(s,"W"))
2222             pic16_emitcode("movf","%s,w",s);
2223           pic16_emitcode("movwf","%s",d);
2224
2225           if(strcmp(s,"W")) {
2226             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2227             if(offset >= aop->size) {
2228               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2229               break;
2230             } else
2231               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2232           }
2233
2234           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2235
2236
2237         }
2238         break;
2239         
2240     case AOP_REG:
2241       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2242         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2243           /*
2244             if (*s == '@'           ||
2245                 strcmp(s,"r0") == 0 ||
2246                 strcmp(s,"r1") == 0 ||
2247                 strcmp(s,"r2") == 0 ||
2248                 strcmp(s,"r3") == 0 ||
2249                 strcmp(s,"r4") == 0 ||
2250                 strcmp(s,"r5") == 0 ||
2251                 strcmp(s,"r6") == 0 || 
2252                 strcmp(s,"r7") == 0 )
2253                 pic16_emitcode("mov","%s,%s  ; %d",
2254                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2255             else
2256           */
2257
2258           if(strcmp(s,"W")==0 )
2259             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2260
2261           pic16_emitcode("movwf","%s",
2262                    aop->aopu.aop_reg[offset]->name);
2263
2264           if(strcmp(s,zero)==0) {
2265             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2266
2267           } else if(strcmp(s,"W")==0) {
2268             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2269             pcop->type = PO_GPR_REGISTER;
2270
2271             PCOR(pcop)->rIdx = -1;
2272             PCOR(pcop)->r = NULL;
2273
2274             DEBUGpic16_emitcode(";","%d",__LINE__);
2275             pcop->name = Safe_strdup(s);
2276             pic16_emitpcode(POC_MOVFW,pcop);
2277             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2278           } else if(strcmp(s,one)==0) {
2279             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2280             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2281           } else {
2282             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2283           }
2284         }
2285         break;
2286         
2287     case AOP_DPTR:
2288     case AOP_DPTR2:
2289     
2290     if (aop->type == AOP_DPTR2)
2291     {
2292         genSetDPTR(1);
2293     }
2294     
2295         if (aop->code) {
2296             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2297                    "pic16_aopPut writting to code space");
2298             exit(0);
2299         }
2300         
2301         while (offset > aop->coff) {
2302             aop->coff++;
2303             pic16_emitcode ("inc","dptr");
2304         }
2305         
2306         while (offset < aop->coff) {
2307             aop->coff-- ;
2308             pic16_emitcode("lcall","__decdptr");
2309         }
2310         
2311         aop->coff = offset;
2312         
2313         /* if not in accumulater */
2314         MOVA(s);        
2315         
2316         pic16_emitcode ("movx","@dptr,a");
2317         
2318     if (aop->type == AOP_DPTR2)
2319     {
2320         genSetDPTR(0);
2321     }
2322         break;
2323         
2324     case AOP_R0:
2325     case AOP_R1:
2326         while (offset > aop->coff) {
2327             aop->coff++;
2328             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2329         }
2330         while (offset < aop->coff) {
2331             aop->coff-- ;
2332             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2333         }
2334         aop->coff = offset;
2335         
2336         if (aop->paged) {
2337             MOVA(s);           
2338             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2339             
2340         } else
2341             if (*s == '@') {
2342                 MOVA(s);
2343                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2344             } else
2345                 if (strcmp(s,"r0") == 0 ||
2346                     strcmp(s,"r1") == 0 ||
2347                     strcmp(s,"r2") == 0 ||
2348                     strcmp(s,"r3") == 0 ||
2349                     strcmp(s,"r4") == 0 ||
2350                     strcmp(s,"r5") == 0 ||
2351                     strcmp(s,"r6") == 0 || 
2352                     strcmp(s,"r7") == 0 ) {
2353                     char buffer[10];
2354                     sprintf(buffer,"a%s",s);
2355                     pic16_emitcode("mov","@%s,%s",
2356                              aop->aopu.aop_ptr->name,buffer);
2357                 } else
2358                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2359         
2360         break;
2361         
2362     case AOP_STK:
2363         if (strcmp(s,"a") == 0)
2364             pic16_emitcode("push","acc");
2365         else
2366             pic16_emitcode("push","%s",s);
2367         
2368         break;
2369         
2370     case AOP_CRY:
2371         /* if bit variable */
2372         if (!aop->aopu.aop_dir) {
2373             pic16_emitcode("clr","a");
2374             pic16_emitcode("rlc","a");
2375         } else {
2376             if (s == zero) 
2377                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2378             else
2379                 if (s == one)
2380                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2381                 else
2382                     if (!strcmp(s,"c"))
2383                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2384                     else {
2385                         lbl = newiTempLabel(NULL);
2386                         
2387                         if (strcmp(s,"a")) {
2388                             MOVA(s);
2389                         }
2390                         pic16_emitcode("clr","c");
2391                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2392                         pic16_emitcode("cpl","c");
2393                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2394                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2395                     }
2396         }
2397         break;
2398         
2399     case AOP_STR:
2400         aop->coff = offset;
2401         if (strcmp(aop->aopu.aop_str[offset],s))
2402             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2403         break;
2404         
2405     case AOP_ACC:
2406         aop->coff = offset;
2407         if (!offset && (strcmp(s,"acc") == 0))
2408             break;
2409         
2410         if (strcmp(aop->aopu.aop_str[offset],s))
2411             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2412         break;
2413
2414     default :
2415         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2416 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2417 //             "pic16_aopPut got unsupported aop->type");
2418 //      exit(0);    
2419     }    
2420
2421 }
2422
2423 /*-----------------------------------------------------------------*/
2424 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2425 /*-----------------------------------------------------------------*/
2426 void pic16_mov2w (asmop *aop, int offset)
2427 {
2428   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2429
2430   if(is_LitAOp(aop))
2431     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2432   else
2433     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2434 }
2435
2436 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2437 {
2438   if(is_LitAOp(src)) {
2439     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2440     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2441   } else {
2442     if(pic16_sameRegsOfs(src, dst, offset))return;
2443     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2444                       pic16_popGet(dst, offset)));
2445   }
2446 }
2447
2448 static void pic16_movLit2f(pCodeOp *pc, int lit)
2449 {
2450   if (0 == (lit & 0x00ff))
2451   {
2452     pic16_emitpcode (POC_CLRF, pc);
2453   } else if (0xff == (lit & 0x00ff))
2454   {
2455     pic16_emitpcode (POC_SETF, pc);
2456   } else {
2457     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2458     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2459   }
2460 }
2461
2462 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2463 {
2464   if(is_LitAOp(src)) {
2465     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2466     pic16_emitpcode(POC_MOVWF, dst);
2467   } else {
2468     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2469   }
2470 }
2471
2472 void pic16_testStackOverflow(void)
2473 {
2474 #define GSTACK_TEST_NAME        "_gstack_test"
2475
2476   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2477   
2478   {
2479     symbol *sym;
2480
2481       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2482       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2483 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2484       checkAddSym(&externs, sym);
2485   }
2486
2487 }
2488
2489 /* push pcop into stack */
2490 void pic16_pushpCodeOp(pCodeOp *pcop)
2491 {
2492 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2493   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2494   if(pic16_options.gstack)
2495     pic16_testStackOverflow();
2496     
2497 }
2498
2499 /* pop pcop from stack */
2500 void pic16_poppCodeOp(pCodeOp *pcop)
2501 {
2502   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2503   if(pic16_options.gstack)
2504     pic16_testStackOverflow();
2505 }
2506
2507
2508 /*-----------------------------------------------------------------*/
2509 /* pushw - pushes wreg to stack                                    */
2510 /*-----------------------------------------------------------------*/
2511 void pushw(void)
2512 {
2513   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2514   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2515   if(pic16_options.gstack)
2516     pic16_testStackOverflow();
2517 }
2518
2519                 
2520 /*-----------------------------------------------------------------*/
2521 /* pushaop - pushes aop to stack                                   */
2522 /*-----------------------------------------------------------------*/
2523 void pushaop(asmop *aop, int offset)
2524 {
2525   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2526
2527   if(_G.resDirect)return;
2528   
2529   if(is_LitAOp(aop)) {
2530     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2531     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2532   } else {
2533     pic16_emitpcode(POC_MOVFF,
2534       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2535   }
2536
2537   if(pic16_options.gstack)
2538     pic16_testStackOverflow();
2539 }
2540
2541 /*-----------------------------------------------------------------*/
2542 /* popaop - pops aop from stack                                    */
2543 /*-----------------------------------------------------------------*/
2544 void popaop(asmop *aop, int offset)
2545 {
2546   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2547   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2548   if(pic16_options.gstack)
2549     pic16_testStackOverflow();
2550 }
2551
2552 void popaopidx(asmop *aop, int offset, int index)
2553 {
2554   int ofs=1;
2555
2556     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2557
2558     if(STACK_MODEL_LARGE)ofs++;
2559
2560     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2561     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2562     if(pic16_options.gstack)
2563       pic16_testStackOverflow();
2564 }
2565
2566 #if !(USE_GENERIC_SIGNED_SHIFT)
2567 /*-----------------------------------------------------------------*/
2568 /* reAdjustPreg - points a register back to where it should        */
2569 /*-----------------------------------------------------------------*/
2570 static void reAdjustPreg (asmop *aop)
2571 {
2572     int size ;
2573
2574     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2575     aop->coff = 0;
2576     if ((size = aop->size) <= 1)
2577         return ;
2578     size-- ;
2579     switch (aop->type) {
2580         case AOP_R0 :
2581         case AOP_R1 :
2582             while (size--)
2583                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2584             break;          
2585         case AOP_DPTR :
2586         case AOP_DPTR2:
2587             if (aop->type == AOP_DPTR2)
2588             {
2589                 genSetDPTR(1);
2590             } 
2591             while (size--)
2592             {
2593                 pic16_emitcode("lcall","__decdptr");
2594             }
2595                 
2596             if (aop->type == AOP_DPTR2)
2597             {
2598                 genSetDPTR(0);
2599             }                
2600             break;  
2601
2602     }   
2603
2604 }
2605 #endif
2606
2607 #if 0
2608 /*-----------------------------------------------------------------*/
2609 /* opIsGptr: returns non-zero if the passed operand is             */   
2610 /* a generic pointer type.                                         */
2611 /*-----------------------------------------------------------------*/ 
2612 static int opIsGptr(operand *op)
2613 {
2614     sym_link *type = operandType(op);
2615     
2616     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2617     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2618     {
2619         return 1;
2620     }
2621     return 0;        
2622 }
2623 #endif
2624
2625 /*-----------------------------------------------------------------*/
2626 /* pic16_getDataSize - get the operand data size                         */
2627 /*-----------------------------------------------------------------*/
2628 int pic16_getDataSize(operand *op)
2629 {
2630     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2631
2632
2633     return AOP_SIZE(op);
2634
2635     // tsd- in the pic port, the genptr size is 1, so this code here
2636     // fails. ( in the 8051 port, the size was 4).
2637 #if 0
2638     int size;
2639     size = AOP_SIZE(op);
2640     if (size == GPTRSIZE)
2641     {
2642         sym_link *type = operandType(op);
2643         if (IS_GENPTR(type))
2644         {
2645             /* generic pointer; arithmetic operations
2646              * should ignore the high byte (pointer type).
2647              */
2648             size--;
2649     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2650         }
2651     }
2652     return size;
2653 #endif
2654 }
2655
2656 /*-----------------------------------------------------------------*/
2657 /* pic16_outAcc - output Acc                                             */
2658 /*-----------------------------------------------------------------*/
2659 void pic16_outAcc(operand *result)
2660 {
2661   int size,offset;
2662   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2663   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2664
2665
2666   size = pic16_getDataSize(result);
2667   if(size){
2668     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2669     size--;
2670     offset = 1;
2671     /* unsigned or positive */
2672     while(size--)
2673       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2674   }
2675
2676 }
2677
2678 /*-----------------------------------------------------------------*/
2679 /* pic16_outBitC - output a bit C                                  */
2680 /*                 Move to result the value of Carry flag -- VR    */
2681 /*-----------------------------------------------------------------*/
2682 void pic16_outBitC(operand *result)
2683 {
2684   int i;
2685
2686     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2687
2688     /* if the result is bit */
2689     if (AOP_TYPE(result) == AOP_CRY) {
2690         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2691         pic16_aopPut(AOP(result),"c",0);
2692     } else {
2693
2694         i = AOP_SIZE(result);
2695         while(i--) {
2696                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2697         }
2698         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2699     }
2700 }
2701
2702 /*-----------------------------------------------------------------*/
2703 /* pic16_outBitOp - output a bit from Op                           */
2704 /*                 Move to result the value of set/clr op -- VR    */
2705 /*-----------------------------------------------------------------*/
2706 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2707 {
2708   int i;
2709
2710     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2711
2712     /* if the result is bit */
2713     if (AOP_TYPE(result) == AOP_CRY) {
2714         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2715         pic16_aopPut(AOP(result),"c",0);
2716     } else {
2717
2718         i = AOP_SIZE(result);
2719         while(i--) {
2720                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2721         }
2722         pic16_emitpcode(POC_RRCF, pcop);          
2723         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2724     }
2725 }
2726
2727 /*-----------------------------------------------------------------*/
2728 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2729 /*-----------------------------------------------------------------*/
2730 void pic16_toBoolean(operand *oper)
2731 {
2732     int size = AOP_SIZE(oper) - 1;
2733     int offset = 1;
2734
2735     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2736
2737     if ( AOP_TYPE(oper) != AOP_ACC) {
2738       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2739     }
2740     while (size--) {
2741       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2742     }
2743 }
2744
2745 /*-----------------------------------------------------------------*/
2746 /* genUminusFloat - unary minus for floating points                */
2747 /*-----------------------------------------------------------------*/
2748 static void genUminusFloat(operand *op,operand *result)
2749 {
2750   int size ,offset =0 ;
2751   
2752     FENTRY;
2753     /* for this we just need to flip the 
2754     first it then copy the rest in place */
2755     size = AOP_SIZE(op);
2756     assert( size == AOP_SIZE(result) );
2757
2758     while(size--) {
2759       pic16_mov2f(AOP(result), AOP(op), offset);
2760       offset++;
2761     }
2762     
2763     /* toggle the MSB's highest bit */
2764     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2765 }
2766
2767 /*-----------------------------------------------------------------*/
2768 /* genUminus - unary minus code generation                         */
2769 /*-----------------------------------------------------------------*/
2770 static void genUminus (iCode *ic)
2771 {
2772   int size, i;
2773   sym_link *optype, *rtype;
2774   symbol *label;
2775   int needLabel=0;
2776
2777     FENTRY;     
2778     
2779     /* assign asmops */
2780     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2781     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2782
2783     /* if both in bit space then special case */
2784     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2785       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2786         
2787         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2788         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2789         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2790         goto release; 
2791     } 
2792
2793     optype = operandType(IC_LEFT(ic));
2794     rtype = operandType(IC_RESULT(ic));
2795
2796
2797     /* if float then do float stuff */
2798     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2799       if(IS_FIXED(optype))
2800         debugf("implement fixed16x16 type\n", 0);
2801         
2802         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2803         goto release;
2804     }
2805
2806     /* otherwise subtract from zero by taking the 2's complement */
2807     size = AOP_SIZE(IC_LEFT(ic));
2808     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2809     label = newiTempLabel ( NULL );
2810     
2811     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2812       for (i=size-1; i > 0; i--) {
2813         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2814       } // for
2815       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2816       for (i=1; i < size; i++) {
2817         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2818         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2819       } // for
2820     } else {
2821       for (i=size-1; i >= 0; i--) {
2822         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2823         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2824       } // for
2825       if (size > 1) {
2826         for (i=0; i < size-2; i++) {
2827           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2828           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2829         } // for
2830         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2831       } // if
2832       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2833     }
2834     if (needLabel)
2835       pic16_emitpLabel (label->key);
2836
2837 release:
2838     /* release the aops */
2839     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2840     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2841 }
2842
2843 #if 0
2844 /*-----------------------------------------------------------------*/
2845 /* saveRegisters - will look for a call and save the registers     */
2846 /*-----------------------------------------------------------------*/
2847 static void saveRegisters(iCode *lic) 
2848 {
2849     int i;
2850     iCode *ic;
2851     bitVect *rsave;
2852     sym_link *dtype;
2853
2854     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2855     /* look for call */
2856     for (ic = lic ; ic ; ic = ic->next) 
2857         if (ic->op == CALL || ic->op == PCALL)
2858             break;
2859
2860     if (!ic) {
2861         fprintf(stderr,"found parameter push with no function call\n");
2862         return ;
2863     }
2864
2865     /* if the registers have been saved already then
2866     do nothing */
2867     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2868         return ;
2869
2870     /* find the registers in use at this time 
2871     and push them away to safety */
2872     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2873                           ic->rUsed);
2874
2875     ic->regsSaved = 1;
2876     if (options.useXstack) {
2877         if (bitVectBitValue(rsave,R0_IDX))
2878             pic16_emitcode("mov","b,r0");
2879         pic16_emitcode("mov","r0,%s",spname);
2880         for (i = 0 ; i < pic16_nRegs ; i++) {
2881             if (bitVectBitValue(rsave,i)) {
2882                 if (i == R0_IDX)
2883                     pic16_emitcode("mov","a,b");
2884                 else
2885                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2886                 pic16_emitcode("movx","@r0,a");
2887                 pic16_emitcode("inc","r0");
2888             }
2889         }
2890         pic16_emitcode("mov","%s,r0",spname);
2891         if (bitVectBitValue(rsave,R0_IDX))
2892             pic16_emitcode("mov","r0,b");           
2893     }// else
2894     //for (i = 0 ; i < pic16_nRegs ; i++) {
2895     //    if (bitVectBitValue(rsave,i))
2896     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2897     //}
2898
2899     dtype = operandType(IC_LEFT(ic));
2900     if (currFunc && dtype && 
2901         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2902         IFFUNC_ISISR(currFunc->type) &&
2903         !ic->bankSaved) 
2904
2905         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2906
2907 }
2908 /*-----------------------------------------------------------------*/
2909 /* unsaveRegisters - pop the pushed registers                      */
2910 /*-----------------------------------------------------------------*/
2911 static void unsaveRegisters (iCode *ic)
2912 {
2913     int i;
2914     bitVect *rsave;
2915
2916     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2917     /* find the registers in use at this time 
2918     and push them away to safety */
2919     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2920                           ic->rUsed);
2921     
2922     if (options.useXstack) {
2923         pic16_emitcode("mov","r0,%s",spname);   
2924         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2925             if (bitVectBitValue(rsave,i)) {
2926                 pic16_emitcode("dec","r0");
2927                 pic16_emitcode("movx","a,@r0");
2928                 if (i == R0_IDX)
2929                     pic16_emitcode("mov","b,a");
2930                 else
2931                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2932             }       
2933
2934         }
2935         pic16_emitcode("mov","%s,r0",spname);
2936         if (bitVectBitValue(rsave,R0_IDX))
2937             pic16_emitcode("mov","r0,b");
2938     } //else
2939     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2940     //    if (bitVectBitValue(rsave,i))
2941     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2942     //}
2943
2944 }  
2945 #endif
2946
2947 #if 0  // patch 14
2948 /*-----------------------------------------------------------------*/
2949 /* pushSide -                                                      */
2950 /*-----------------------------------------------------------------*/
2951 static void pushSide(operand * oper, int size)
2952 {
2953         int offset = 0;
2954     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2955         while (size--) {
2956                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2957                 if (AOP_TYPE(oper) != AOP_REG &&
2958                     AOP_TYPE(oper) != AOP_DIR &&
2959                     strcmp(l,"a") ) {
2960                         pic16_emitcode("mov","a,%s",l);
2961                         pic16_emitcode("push","acc");
2962                 } else
2963                         pic16_emitcode("push","%s",l);
2964         }
2965 }
2966 #endif // patch 14
2967
2968 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2969 {
2970   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2971     pic16_emitpcode(POC_MOVFW, src);
2972     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2973   } else {
2974     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2975         src, pic16_popGet(AOP(op), offset)));
2976   }
2977 }
2978
2979
2980 /*-----------------------------------------------------------------*/
2981 /* assignResultValue - assign results to oper, rescall==1 is       */
2982 /*                     called from genCall() or genPcall()         */
2983 /*-----------------------------------------------------------------*/
2984 static void assignResultValue(operand * oper, int rescall)
2985 {
2986   int size = AOP_SIZE(oper);
2987   int offset=0;
2988   
2989     FENTRY2;
2990 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2991     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2992
2993     if(rescall) {
2994       /* assign result from a call/pcall function() */
2995                 
2996       /* function results are stored in a special order,
2997        * see top of file with Function return policy, or manual */
2998
2999       if(size <= 4) {
3000         /* 8-bits, result in WREG */
3001         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3002                         
3003         if(size>1) {
3004           /* 16-bits, result in PRODL:WREG */
3005           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3006         }
3007                         
3008         if(size>2) {
3009           /* 24-bits, result in PRODH:PRODL:WREG */
3010           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3011         }
3012                         
3013         if(size>3) {
3014           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3015           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3016         }
3017       
3018       } else {
3019         /* >32-bits, result on stack, and FSR0 points to beginning.
3020          * Fix stack when done */
3021         /* FIXME FIXME */
3022 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3023         while (size--) {
3024 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3025 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3026                 
3027           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3028           GpsuedoStkPtr++;
3029         }
3030                         
3031         /* fix stack */
3032         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3033         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3034         if(STACK_MODEL_LARGE) {
3035           emitSKPNC;
3036           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3037         }
3038       }                 
3039     } else {
3040       int areg = 0;             /* matching argument register */
3041       
3042 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3043       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3044
3045
3046       /* its called from genReceive (probably) -- VR */
3047       /* I hope this code will not be called from somewhere else in the future! 
3048        * We manually set the pseudo stack pointer in genReceive. - dw
3049        */
3050       if(!GpsuedoStkPtr && _G.useWreg) {
3051 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3052
3053         /* The last byte in the assignment is in W */
3054         if(areg <= GpsuedoStkPtr) {
3055           size--;
3056           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3057           offset++;
3058 //          debugf("receive from WREG\n", 0);
3059         }
3060         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3061       }
3062 //      GpsuedoStkPtr++;
3063       _G.stack_lat = AOP_SIZE(oper)-1;
3064
3065       while (size) {
3066         size--;
3067         GpsuedoStkPtr++;
3068         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3069 //        debugf("receive from STACK\n", 0);
3070         offset++;
3071       }
3072     }
3073 }
3074
3075
3076 /*-----------------------------------------------------------------*/
3077 /* genIpush - generate code for pushing this gets a little complex */
3078 /*-----------------------------------------------------------------*/
3079 static void genIpush (iCode *ic)
3080 {
3081 //  int size, offset=0;
3082
3083   FENTRY;
3084   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3085
3086   if(ic->parmPush) {
3087     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3088
3089     /* send to stack as normal */
3090     addSet(&_G.sendSet,ic);
3091 //    addSetHead(&_G.sendSet,ic);
3092     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3093   }
3094
3095         
3096 #if 0
3097     int size, offset = 0 ;
3098     char *l;
3099
3100
3101     /* if this is not a parm push : ie. it is spill push 
3102     and spill push is always done on the local stack */
3103     if (!ic->parmPush) {
3104
3105         /* and the item is spilt then do nothing */
3106         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3107             return ;
3108
3109         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3110         size = AOP_SIZE(IC_LEFT(ic));
3111         /* push it on the stack */
3112         while(size--) {
3113             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3114             if (*l == '#') {
3115                 MOVA(l);
3116                 l = "acc";
3117             }
3118             pic16_emitcode("push","%s",l);
3119         }
3120         return ;        
3121     }
3122
3123     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3124 #endif
3125 }
3126
3127 /*-----------------------------------------------------------------*/
3128 /* genIpop - recover the registers: can happen only for spilling   */
3129 /*-----------------------------------------------------------------*/
3130 static void genIpop (iCode *ic)
3131 {
3132   FENTRY;
3133   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3134 #if 0
3135     int size,offset ;
3136
3137
3138     /* if the temp was not pushed then */
3139     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3140         return ;
3141
3142     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3143     size = AOP_SIZE(IC_LEFT(ic));
3144     offset = (size-1);
3145     while (size--) 
3146         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3147                                    FALSE,TRUE));
3148
3149     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3150 #endif
3151 }
3152
3153 #if 0
3154 /*-----------------------------------------------------------------*/
3155 /* unsaverbank - restores the resgister bank from stack            */
3156 /*-----------------------------------------------------------------*/
3157 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3158 {
3159   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3160 #if 0
3161     int i;
3162     asmop *aop ;
3163     regs *r = NULL;
3164
3165     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3166     if (popPsw) {
3167         if (options.useXstack) {
3168             aop = newAsmop(0);
3169             r = getFreePtr(ic,&aop,FALSE);
3170             
3171             
3172             pic16_emitcode("mov","%s,_spx",r->name);
3173             pic16_emitcode("movx","a,@%s",r->name);
3174             pic16_emitcode("mov","psw,a");
3175             pic16_emitcode("dec","%s",r->name);
3176             
3177         }else
3178             pic16_emitcode ("pop","psw");
3179     }
3180
3181     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3182         if (options.useXstack) {       
3183             pic16_emitcode("movx","a,@%s",r->name);
3184             //pic16_emitcode("mov","(%s+%d),a",
3185             //       regspic16[i].base,8*bank+regspic16[i].offset);
3186             pic16_emitcode("dec","%s",r->name);
3187
3188         } else 
3189           pic16_emitcode("pop",""); //"(%s+%d)",
3190         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3191     }
3192
3193     if (options.useXstack) {
3194
3195         pic16_emitcode("mov","_spx,%s",r->name);
3196         pic16_freeAsmop(NULL,aop,ic,TRUE);
3197
3198     }
3199 #endif 
3200 }
3201
3202 /*-----------------------------------------------------------------*/
3203 /* saverbank - saves an entire register bank on the stack          */
3204 /*-----------------------------------------------------------------*/
3205 static void saverbank (int bank, iCode *ic, bool pushPsw)
3206 {
3207   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3208 #if 0
3209     int i;
3210     asmop *aop ;
3211     regs *r = NULL;
3212
3213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3214     if (options.useXstack) {
3215
3216         aop = newAsmop(0);
3217         r = getFreePtr(ic,&aop,FALSE);  
3218         pic16_emitcode("mov","%s,_spx",r->name);
3219
3220     }
3221
3222     for (i = 0 ; i < pic16_nRegs ;i++) {
3223         if (options.useXstack) {
3224             pic16_emitcode("inc","%s",r->name);
3225             //pic16_emitcode("mov","a,(%s+%d)",
3226             //         regspic16[i].base,8*bank+regspic16[i].offset);
3227             pic16_emitcode("movx","@%s,a",r->name);           
3228         } else 
3229           pic16_emitcode("push","");// "(%s+%d)",
3230                      //regspic16[i].base,8*bank+regspic16[i].offset);
3231     }
3232     
3233     if (pushPsw) {
3234         if (options.useXstack) {
3235             pic16_emitcode("mov","a,psw");
3236             pic16_emitcode("movx","@%s,a",r->name);     
3237             pic16_emitcode("inc","%s",r->name);
3238             pic16_emitcode("mov","_spx,%s",r->name);       
3239             pic16_freeAsmop (NULL,aop,ic,TRUE);
3240             
3241         } else
3242             pic16_emitcode("push","psw");
3243         
3244         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3245     }
3246     ic->bankSaved = 1;
3247 #endif
3248 }
3249 #endif  /* 0 */
3250
3251
3252 static int wparamCmp(void *p1, void *p2)
3253 {
3254   return (!strcmp((char *)p1, (char *)p2));
3255 }
3256
3257 int inWparamList(char *s)
3258 {
3259   return isinSetWith(wparamList, s, wparamCmp);
3260
3261
3262
3263 /*-----------------------------------------------------------------*/
3264 /* genCall - generates a call statement                            */
3265 /*-----------------------------------------------------------------*/
3266 static void genCall (iCode *ic)
3267 {
3268   sym_link *ftype;   
3269   int stackParms=0;
3270   int use_wreg=0;
3271   int inwparam=0;
3272   char *fname;
3273   
3274     FENTRY;
3275
3276     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3277     /* if caller saves & we have not saved then */
3278 //    if (!ic->regsSaved)
3279 //      saveRegisters(ic);
3280
3281         /* initialise stackParms for IPUSH pushes */
3282 //      stackParms = psuedoStkPtr;
3283 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3284     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3285     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3286
3287 #if 0
3288     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3289 #endif
3290
3291     /* if send set is not empty the assign */
3292     if (_G.sendSet) {
3293       iCode *sic;
3294       int psuedoStkPtr=-1; 
3295       int firstTimeThruLoop = 1;
3296
3297
3298         /* reverse sendSet if function is not reentrant */
3299         if(!IFFUNC_ISREENT(ftype))
3300           _G.sendSet = reverseSet(_G.sendSet);
3301
3302         /* First figure how many parameters are getting passed */
3303         stackParms = 0;
3304         use_wreg = 0;
3305         
3306         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3307           int size;
3308 //          int offset = 0;
3309
3310             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3311             size = AOP_SIZE(IC_LEFT(sic));
3312
3313             stackParms += size;
3314
3315             /* pass the last byte through WREG */
3316             if(inwparam) {
3317
3318               while (size--) {
3319                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3320                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3321                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3322
3323                 if(!firstTimeThruLoop) {
3324                   /* If this is not the first time we've been through the loop
3325                    * then we need to save the parameter in a temporary
3326                    * register. The last byte of the last parameter is
3327                    * passed in W. */
3328
3329                   pushw();
3330 //                  --psuedoStkPtr;             // sanity check
3331                   use_wreg = 1;
3332                 }
3333                 
3334                 firstTimeThruLoop=0;
3335
3336                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3337
3338 //                offset++;
3339               }
3340             } else {
3341               /* all arguments are passed via stack */
3342               use_wreg = 0;
3343
3344               while (size--) {
3345                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3346                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3347                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3348
3349 //                pushaop(AOP(IC_LEFT(sic)), size);
3350                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3351                                 
3352                 if(!_G.resDirect)
3353                   pushw();
3354               }
3355             }
3356
3357             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3358           }
3359
3360           if(inwparam) {
3361             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3362               pushw();  /* save last parameter to stack if functions has varargs */
3363               use_wreg = 0;
3364             } else
3365               use_wreg = 1;
3366           } else use_wreg = 0;
3367
3368           _G.stackRegSet = _G.sendSet;
3369           _G.sendSet = NULL;
3370     }
3371
3372     /* make the call */
3373     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3374
3375     GpsuedoStkPtr=0;
3376     
3377     /* if we need to assign a result value */
3378     if ((IS_ITEMP(IC_RESULT(ic))
3379           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3380               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3381         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3382
3383       _G.accInUse++;
3384       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3385       _G.accInUse--;
3386
3387       assignResultValue(IC_RESULT(ic), 1);
3388
3389       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3390                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3391                 
3392       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3393     }
3394
3395     if(!stackParms && ic->parmBytes) {
3396       stackParms = ic->parmBytes;
3397     }
3398       
3399     stackParms -= use_wreg;
3400     
3401     if(stackParms>0) {
3402       if(stackParms == 1) {
3403         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3404       } else {
3405         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3406         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3407       }
3408       if(STACK_MODEL_LARGE) {
3409         emitSKPNC;
3410         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3411       }
3412     }
3413
3414 #if 0
3415     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3416 #endif
3417
3418     /* adjust the stack for parameters if required */
3419 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3420
3421 #if 0
3422       /* if register bank was saved then pop them */
3423       if (ic->bankSaved)
3424         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3425
3426       /* if we hade saved some registers then unsave them */
3427       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3428         unsaveRegisters (ic);
3429 #endif
3430 }
3431
3432
3433
3434 /*-----------------------------------------------------------------*/
3435 /* genPcall - generates a call by pointer statement                */
3436 /*            new version, created from genCall - HJD              */
3437 /*-----------------------------------------------------------------*/
3438 static void genPcall (iCode *ic)
3439 {
3440   sym_link *fntype;
3441   int stackParms=0;
3442   symbol *retlbl = newiTempLabel(NULL);
3443   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3444   
3445     FENTRY;
3446
3447     fntype = operandType( IC_LEFT(ic) )->next;
3448
3449     /* if send set is not empty the assign */
3450     if (_G.sendSet) {
3451       iCode *sic;
3452       int psuedoStkPtr=-1; 
3453
3454       /* reverse sendSet if function is not reentrant */
3455       if(!IFFUNC_ISREENT(fntype))
3456         _G.sendSet = reverseSet(_G.sendSet);
3457
3458       stackParms = 0;
3459       
3460       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3461         int size;
3462
3463           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3464           size = AOP_SIZE(IC_LEFT(sic));
3465           stackParms += size;
3466
3467           /* all parameters are passed via stack, since WREG is clobbered
3468            * by the calling sequence */
3469           while (size--) {
3470             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3471             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3472             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3473
3474             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3475             pushw();
3476           }
3477
3478           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3479       }
3480
3481       _G.stackRegSet = _G.sendSet;
3482       _G.sendSet = NULL;
3483     }
3484
3485     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3486
3487     // push return address
3488     // push $ on return stack, then replace with retlbl
3489
3490     /* Thanks to Thorsten Klose for pointing out that the following
3491      * snippet should be interrupt safe */
3492     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3493     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3494
3495     pic16_emitpcodeNULLop(POC_PUSH);
3496
3497     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3498     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3499     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3500     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3501     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3502     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3503
3504
3505     /* restore interrupt control register */
3506     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3507     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3508
3509     /* make the call by writing the pointer into pc */
3510     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3511     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3512
3513     // note: MOVFF to PCL not allowed
3514     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3515     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3516
3517
3518     /* return address is here: (X) */
3519     pic16_emitpLabelFORCE(retlbl->key);
3520
3521     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3522
3523     GpsuedoStkPtr=0;
3524     /* if we need assign a result value */
3525     if ((IS_ITEMP(IC_RESULT(ic))
3526           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3527               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3528         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3529
3530       _G.accInUse++;
3531       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3532       _G.accInUse--;
3533
3534       assignResultValue(IC_RESULT(ic), 1);
3535
3536       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3537               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3538                 
3539       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3540     }
3541
3542 //    stackParms -= use_wreg;
3543     
3544     if(stackParms>0) {
3545       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3546       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3547       if(STACK_MODEL_LARGE) {
3548         emitSKPNC;
3549         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3550       }
3551     }
3552 }
3553
3554 /*-----------------------------------------------------------------*/
3555 /* resultRemat - result  is rematerializable                       */
3556 /*-----------------------------------------------------------------*/
3557 static int resultRemat (iCode *ic)
3558 {
3559   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3560   if (SKIP_IC(ic) || ic->op == IFX)
3561     return 0;
3562
3563   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3564     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3565     if (sym->remat && !POINTER_SET(ic)) 
3566       return 1;
3567   }
3568
3569   return 0;
3570 }
3571
3572 #if defined(__BORLANDC__) || defined(_MSC_VER)
3573 #define STRCASECMP stricmp
3574 #else
3575 #define STRCASECMP strcasecmp
3576 #endif
3577
3578 #if 0
3579 /*-----------------------------------------------------------------*/
3580 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3581 /*-----------------------------------------------------------------*/
3582 static bool inExcludeList(char *s)
3583 {
3584   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3585     int i =0;
3586     
3587     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3588     if (options.excludeRegs[i] &&
3589     STRCASECMP(options.excludeRegs[i],"none") == 0)
3590         return FALSE ;
3591
3592     for ( i = 0 ; options.excludeRegs[i]; i++) {
3593         if (options.excludeRegs[i] &&
3594         STRCASECMP(s,options.excludeRegs[i]) == 0)
3595             return TRUE;
3596     }
3597     return FALSE ;
3598 }
3599 #endif
3600
3601 /*-----------------------------------------------------------------*/
3602 /* genFunction - generated code for function entry                 */
3603 /*-----------------------------------------------------------------*/
3604 static void genFunction (iCode *ic)
3605 {
3606   symbol *sym;
3607   sym_link *ftype;
3608   
3609     FENTRY;
3610     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3611
3612     pic16_labelOffset += (max_key+4);
3613     max_key=0;
3614     GpsuedoStkPtr=0;
3615     _G.nRegsSaved = 0;
3616         
3617     ftype = operandType(IC_LEFT(ic));
3618     sym = OP_SYMBOL(IC_LEFT(ic));
3619
3620     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3621       /* create an absolute section at the interrupt vector:
3622        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3623       symbol *asym;
3624       char asymname[128];
3625       pBlock *apb;
3626
3627 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3628
3629         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3630           sprintf(asymname, "ivec_%s", sym->name);
3631         else
3632           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3633   
3634         /* when an interrupt is declared as naked, do not emit the special
3635          * wrapper segment at vector address. The user should take care for
3636          * this instead. -- VR */
3637
3638         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3639           asym = newSymbol(asymname, 0);
3640           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3641           pic16_addpBlock( apb );
3642
3643           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3644           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3645           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3646           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3647           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3648                 
3649           /* mark the end of this tiny function */
3650           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3651         } else {
3652           sprintf(asymname, "%s", sym->rname);
3653         }
3654
3655         {
3656           absSym *abSym;
3657
3658             abSym = Safe_calloc(1, sizeof(absSym));
3659             strcpy(abSym->name, asymname);
3660
3661             switch( FUNC_INTNO(sym->type) ) {
3662               case 0: abSym->address = 0x000000; break;
3663               case 1: abSym->address = 0x000008; break;
3664               case 2: abSym->address = 0x000018; break;
3665               
3666               default:
3667 //                fprintf(stderr, "no interrupt number is given\n");
3668                 abSym->address = -1; break;
3669             }
3670
3671             /* relocate interrupt vectors if needed */
3672             if(abSym->address != -1)
3673               abSym->address += pic16_options.ivt_loc;
3674
3675             addSet(&absSymSet, abSym);
3676         }
3677     }
3678
3679     /* create the function header */
3680     pic16_emitcode(";","-----------------------------------------");
3681     pic16_emitcode(";"," function %s",sym->name);
3682     pic16_emitcode(";","-----------------------------------------");
3683
3684     pic16_emitcode("","%s:",sym->rname);
3685     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3686
3687     {
3688       absSym *ab;
3689
3690         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3691           if(!strcmp(ab->name, sym->rname)) {
3692             pic16_pBlockConvert2Absolute(pb);
3693             break;
3694           }
3695         }
3696     }
3697
3698     if(IFFUNC_ISNAKED(ftype)) {
3699       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3700       return;
3701     }
3702         
3703     /* if critical function then turn interrupts off */
3704     if (IFFUNC_ISCRITICAL(ftype)) {
3705       //pic16_emitcode("clr","ea");
3706     }
3707
3708     currFunc = sym;             /* update the currFunc symbol */
3709     _G.fregsUsed = sym->regsUsed;
3710     _G.sregsAlloc = newBitVect(128);
3711     
3712
3713     /* if this is an interrupt service routine then
3714      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3715     if (IFFUNC_ISISR(sym->type)) {
3716         _G.usefastretfie = 1;   /* use shadow registers by default */
3717         
3718         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3719         if(!FUNC_ISSHADOWREGS(sym->type)) {
3720           /* do not save WREG,STATUS,BSR for high priority interrupts
3721            * because they are stored in the hardware shadow registers already */
3722           _G.usefastretfie = 0;
3723           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3724           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3725           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3726         }
3727
3728         /* these should really be optimized somehow, because not all
3729          * interrupt handlers modify them */
3730         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3731         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3732         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3733         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3734         
3735 //        pic16_pBlockConvert2ISR(pb);
3736     }
3737
3738     /* emit code to setup stack frame if user enabled,
3739      * and function is not main() */
3740     
3741 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3742     if(strcmp(sym->name, "main")) {
3743       if(0 
3744         || !options.ommitFramePtr 
3745 //        || sym->regsUsed
3746         || IFFUNC_ARGS(sym->type)
3747         || FUNC_HASSTACKPARM(sym->etype)
3748         ) {
3749         /* setup the stack frame */
3750         if(STACK_MODEL_LARGE)
3751           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3752         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3753
3754         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3755         if(STACK_MODEL_LARGE)
3756           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3757       }
3758     }
3759
3760     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3761           && sym->stack) {
3762
3763       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3764
3765       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3766       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3767       emitSKPC;
3768       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3769     }
3770           
3771     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3772       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3773         _G.useWreg = 0;
3774       else
3775         _G.useWreg = 1;
3776     } else
3777       _G.useWreg = 0;
3778
3779     /* if callee-save to be used for this function
3780      * then save the registers being used in this function */
3781 //    if (IFFUNC_CALLEESAVES(sym->type))
3782     if(strcmp(sym->name, "main")) {
3783       int i;
3784
3785         /* if any registers used */
3786         if (sym->regsUsed) {
3787                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3788
3789           if(!xinst) {
3790             /* save the registers used */
3791             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3792             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3793               if (bitVectBitValue(sym->regsUsed,i)) {
3794 #if 0
3795                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3796 #endif
3797                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3798                 _G.nRegsSaved++;
3799
3800                 if(!pic16_regWithIdx(i)->wasUsed) {
3801                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3802                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3803                   pic16_regWithIdx(i)->wasUsed = 1;
3804                 }
3805               }
3806             }
3807           } else {
3808             
3809             /* xinst */
3810             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3811             for(i=0;i<sym->regsUsed->size;i++) {
3812               if(bitVectBitValue(sym->regsUsed, i)) {
3813                 _G.nRegsSaved++;
3814               }
3815             }
3816                         
3817 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3818           }
3819
3820           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3821
3822         }
3823     }
3824         
3825     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3826 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3827 }
3828
3829 /*-----------------------------------------------------------------*/
3830 /* genEndFunction - generates epilogue for functions               */
3831 /*-----------------------------------------------------------------*/
3832 static void genEndFunction (iCode *ic)
3833 {
3834   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3835
3836     FENTRY;
3837
3838     if(IFFUNC_ISNAKED(sym->type)) {
3839       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3840       return;
3841     }
3842
3843     _G.stack_lat = 0;
3844
3845     /* add code for ISCRITICAL */
3846     if(IFFUNC_ISCRITICAL(sym->type)) {
3847       /* if critical function, turn on interrupts */
3848       
3849       /* TODO: add code here -- VR */
3850     }
3851     
3852 //    sym->regsUsed = _G.fregsUsed;
3853     
3854     /* now we need to restore the registers */
3855     /* if any registers used */
3856
3857     /* first restore registers that might be used for stack access */
3858     if(_G.sregsAllocSet) {
3859     regs *sr;
3860     
3861       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3862       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3863         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3864       }
3865     }
3866
3867     if (strcmp(sym->name, "main") && sym->regsUsed) {
3868       int i;
3869
3870         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3871         /* restore registers used */
3872         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3873         for ( i = sym->regsUsed->size; i >= 0; i--) {
3874           if (bitVectBitValue(sym->regsUsed,i)) {
3875             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3876             _G.nRegsSaved--;
3877           }
3878         }
3879         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3880     }
3881
3882       
3883
3884     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3885           && sym->stack) {
3886       if (sym->stack == 1) {
3887         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3888         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3889       } else {
3890         // we have to add more than one...
3891         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3892         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3893         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3894         emitSKPNC;
3895         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3896         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3897         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3898       }
3899     }
3900
3901     if(strcmp(sym->name, "main")) {
3902       if(0
3903         || !options.ommitFramePtr
3904 //        || sym->regsUsed
3905         || IFFUNC_ARGS(sym->type)
3906         || FUNC_HASSTACKPARM(sym->etype)
3907         ) {
3908         /* restore stack frame */
3909         if(STACK_MODEL_LARGE)
3910           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3911         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3912       }
3913     }
3914
3915     _G.useWreg = 0;
3916
3917     if (IFFUNC_ISISR(sym->type)) {
3918       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3919       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3920       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3921       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3922
3923       if(!FUNC_ISSHADOWREGS(sym->type)) {
3924         /* do not restore interrupt vector for WREG,STATUS,BSR
3925          * for high priority interrupt, see genFunction */
3926         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3927         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3928         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3929       }
3930 //      _G.interruptvector = 0;         /* sanity check */
3931
3932
3933       /* if debug then send end of function */
3934 /*      if (options.debug && currFunc)  */
3935       if (currFunc) {
3936         debugFile->writeEndFunction (currFunc, ic, 1);
3937       }
3938         
3939       if(_G.usefastretfie)
3940         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3941       else
3942         pic16_emitpcodeNULLop(POC_RETFIE);
3943
3944       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3945       
3946       _G.usefastretfie = 0;
3947       return;
3948     }
3949
3950     if (IFFUNC_ISCRITICAL(sym->type)) {
3951       pic16_emitcode("setb","ea");
3952     }
3953
3954     /* if debug then send end of function */
3955     if (currFunc) {
3956       debugFile->writeEndFunction (currFunc, ic, 1);
3957     }
3958
3959     /* insert code to restore stack frame, if user enabled it
3960      * and function is not main() */
3961          
3962
3963     pic16_emitpcodeNULLop(POC_RETURN);
3964
3965     /* Mark the end of a function */
3966     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3967 }
3968
3969
3970 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3971 {
3972   unsigned long lit=1;
3973   operand *op;
3974
3975     op = IC_LEFT(ic);
3976   
3977     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3978     if(AOP_TYPE(op) == AOP_LIT) {
3979       if(!IS_FLOAT(operandType( op ))) {
3980         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3981       } else {
3982         union {
3983           unsigned long lit_int;
3984           float lit_float;
3985         } info;
3986         
3987         /* take care if literal is a float */
3988         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3989         lit = info.lit_int;
3990       }
3991     }
3992
3993     if(is_LitOp(op)) {
3994       pic16_movLit2f(dest, lit);
3995     } else {
3996       if(dest->type == PO_WREG && (offset == 0)) {
3997         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3998       return;
3999     }
4000     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4001   }
4002 }
4003
4004 /*-----------------------------------------------------------------*/
4005 /* genRet - generate code for return statement                     */
4006 /*-----------------------------------------------------------------*/
4007 static void genRet (iCode *ic)
4008 {
4009   int size;
4010   operand *left;
4011
4012     FENTRY;
4013         /* if we have no return value then
4014          * just generate the "ret" */
4015         
4016         if (!IC_LEFT(ic)) 
4017                 goto jumpret;       
4018     
4019         /* we have something to return then
4020          * move the return value into place */
4021         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4022         size = AOP_SIZE(IC_LEFT(ic));
4023
4024         if(size <= 4) {
4025           if(size>3)
4026             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4027           
4028           if(size>2)
4029             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4030
4031           if(size>1)
4032             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4033           
4034           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4035
4036         } else {
4037                 /* >32-bits, setup stack and FSR0 */
4038                 while (size--) {
4039 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4040 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4041
4042                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4043
4044 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4045                         GpsuedoStkPtr++;
4046                 }
4047                         
4048                 /* setup FSR0 */
4049                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4050                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4051
4052                 if(STACK_MODEL_LARGE) {
4053                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4054                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4055                 } else {
4056                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4057                 }
4058         }
4059                                 
4060 #if 0
4061         /* old code, left here for reference -- VR */    
4062         while (size--) {
4063           char *l ;
4064
4065                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4066                         /* #NOCHANGE */
4067                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4068                         pic16_emitpcomment("push %s",l);
4069                         pushed++;
4070                 } else {
4071                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4072                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4073                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4074                         
4075                         if (strcmp(fReturn[offset],l)) {
4076                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4077                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4078                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4079                                 } else {
4080                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4081                                 }
4082                                 
4083                                 if(size) {
4084                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4085                                 }
4086                                 offset++;
4087                         }
4088                 }
4089         }    
4090
4091         if (pushed) {
4092                 while(pushed) {
4093                         pushed--;
4094                         if (strcmp(fReturn[pushed],"a"))
4095                                 pic16_emitcode("pop",fReturn[pushed]);
4096                         else
4097                                 pic16_emitcode("pop","acc");
4098                 }
4099         }
4100 #endif
4101
4102
4103         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4104     
4105 jumpret:
4106         /* generate a jump to the return label
4107          * if the next is not the return statement */
4108         if (!(ic->next && ic->next->op == LABEL
4109                 && IC_LABEL(ic->next) == returnLabel)) {
4110         
4111                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4112                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4113         }
4114 }
4115
4116 /*-----------------------------------------------------------------*/
4117 /* genLabel - generates a label                                    */
4118 /*-----------------------------------------------------------------*/
4119 static void genLabel (iCode *ic)
4120 {
4121   FENTRY;
4122
4123   /* special case never generate */
4124   if (IC_LABEL(ic) == entryLabel)
4125     return ;
4126
4127   pic16_emitpLabel(IC_LABEL(ic)->key);
4128 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4129 }
4130
4131 /*-----------------------------------------------------------------*/
4132 /* genGoto - generates a goto                                      */
4133 /*-----------------------------------------------------------------*/
4134 //tsd
4135 static void genGoto (iCode *ic)
4136 {
4137   FENTRY;
4138   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4139 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4140 }
4141
4142
4143 /*-----------------------------------------------------------------*/
4144 /* genMultbits :- multiplication of bits                           */
4145 /*-----------------------------------------------------------------*/
4146 static void genMultbits (operand *left, 
4147                          operand *right, 
4148                          operand *result)
4149 {
4150   FENTRY;
4151
4152   if(!pic16_sameRegs(AOP(result),AOP(right)))
4153     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4154
4155   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4156   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4157   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4158
4159 }
4160
4161
4162 /*-----------------------------------------------------------------*/
4163 /* genMultOneByte : 8 bit multiplication & division                */
4164 /*-----------------------------------------------------------------*/
4165 static void genMultOneByte (operand *left,
4166                             operand *right,
4167                             operand *result)
4168 {
4169
4170   FENTRY;
4171   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4172   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4173
4174   /* (if two literals, the value is computed before) */
4175   /* if one literal, literal on the right */
4176   if (AOP_TYPE(left) == AOP_LIT){
4177     operand *t = right;
4178     right = left;
4179     left = t;
4180   }
4181
4182         /* size is already checked in genMult == 1 */
4183 //      size = AOP_SIZE(result);
4184
4185         if (AOP_TYPE(right) == AOP_LIT){
4186                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4187                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4188                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4189                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4190         } else {
4191                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4192                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4193                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4194                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4195         }
4196         
4197         pic16_genMult8X8_8 (left, right,result);
4198 }
4199
4200 /*-----------------------------------------------------------------*/
4201 /* genMultOneWord : 16 bit multiplication                          */
4202 /*-----------------------------------------------------------------*/
4203 static void genMultOneWord (operand *left,
4204                             operand *right,
4205                             operand *result)
4206 {
4207   FENTRY;
4208   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4209   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4210
4211   /* (if two literals, the value is computed before)
4212    * if one literal, literal on the right */
4213   if (AOP_TYPE(left) == AOP_LIT){
4214     operand *t = right;
4215     right = left;
4216     left = t;
4217   }
4218
4219   /* size is checked already == 2 */
4220 //  size = AOP_SIZE(result);
4221
4222   if (AOP_TYPE(right) == AOP_LIT) {
4223     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4224       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4225       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4226       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4227   } else {
4228     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4229       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4230       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4231       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4232   }
4233         
4234   pic16_genMult16X16_16(left, right,result);
4235 }
4236
4237 /*-----------------------------------------------------------------*/
4238 /* genMultOneLong : 32 bit multiplication                          */
4239 /*-----------------------------------------------------------------*/
4240 static void genMultOneLong (operand *left,
4241                             operand *right,
4242                             operand *result)
4243 {
4244   FENTRY;
4245   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4246   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4247
4248   /* (if two literals, the value is computed before)
4249    * if one literal, literal on the right */
4250   if (AOP_TYPE(left) == AOP_LIT){
4251     operand *t = right;
4252     right = left;
4253     left = t;
4254   }
4255
4256   /* size is checked already == 4 */
4257 //  size = AOP_SIZE(result);
4258
4259   if (AOP_TYPE(right) == AOP_LIT) {
4260     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4261         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4262         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4263         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4264   } else {
4265     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4266         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4267         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4268         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4269   }
4270         
4271   pic16_genMult32X32_32(left, right,result);
4272 }
4273
4274
4275
4276 /*-----------------------------------------------------------------*/
4277 /* genMult - generates code for multiplication                     */
4278 /*-----------------------------------------------------------------*/
4279 static void genMult (iCode *ic)
4280 {
4281   operand *left = IC_LEFT(ic);
4282   operand *right = IC_RIGHT(ic);
4283   operand *result= IC_RESULT(ic);   
4284
4285     FENTRY;
4286         /* assign the amsops */
4287         pic16_aopOp (left,ic,FALSE);
4288         pic16_aopOp (right,ic,FALSE);
4289         pic16_aopOp (result,ic,TRUE);
4290
4291         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4292
4293         /* special cases first *
4294         * both are bits */
4295         if (AOP_TYPE(left) == AOP_CRY
4296                 && AOP_TYPE(right)== AOP_CRY) {
4297                 genMultbits(left,right,result);
4298           goto release ;
4299         }
4300
4301         /* if both are of size == 1 */
4302         if(AOP_SIZE(left) == 1
4303                 && AOP_SIZE(right) == 1) {
4304                 genMultOneByte(left,right,result);
4305           goto release ;
4306         }
4307
4308         /* if both are of size == 2 */
4309         if(AOP_SIZE(left) == 2
4310                 && AOP_SIZE(right) == 2) {
4311                 genMultOneWord(left, right, result);
4312           goto release;
4313         }
4314         
4315         /* if both are of size == 4 */
4316         if(AOP_SIZE(left) == 4
4317                 && AOP_SIZE(right) == 4) {
4318                 genMultOneLong(left, right, result);
4319           goto release;
4320         }
4321         
4322         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4323
4324
4325         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4326         /* should have been converted to function call */
4327         assert(0) ;
4328
4329 release :
4330         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4331         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4332         pic16_freeAsmop(result,NULL,ic,TRUE); 
4333 }
4334
4335 /*-----------------------------------------------------------------*/
4336 /* genDivbits :- division of bits                                  */
4337 /*-----------------------------------------------------------------*/
4338 static void genDivbits (operand *left, 
4339                         operand *right, 
4340                         operand *result)
4341 {
4342   char *l;
4343
4344     FENTRY;
4345     /* the result must be bit */    
4346     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4347     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4348
4349     MOVA(l);    
4350
4351     pic16_emitcode("div","ab");
4352     pic16_emitcode("rrc","a");
4353     pic16_aopPut(AOP(result),"c",0);
4354 }
4355
4356 /*-----------------------------------------------------------------*/
4357 /* genDivOneByte : 8 bit division                                  */
4358 /*-----------------------------------------------------------------*/
4359 static void genDivOneByte (operand *left,
4360                            operand *right,
4361                            operand *result)
4362 {
4363   sym_link *opetype = operandType(result);
4364   char *l ;
4365   symbol *lbl ;
4366   int size,offset;
4367
4368         /* result = divident / divisor
4369          * - divident may be a register or a literal,
4370          * - divisor may be a register or a literal,
4371          * so there are 3 cases (literal / literal is optimized
4372          * by the front-end) to handle.
4373          * In addition we must handle signed and unsigned, which
4374          * result in 6 final different cases -- VR */
4375
4376     FENTRY;
4377     
4378     size = AOP_SIZE(result) - 1;
4379     offset = 1;
4380     /* signed or unsigned */
4381     if (SPEC_USIGN(opetype)) {
4382       pCodeOp *pct1,    /* count */
4383                 *pct2,  /* reste */
4384                 *pct3;  /* temp */
4385       symbol *label1, *label2, *label3;;
4386
4387
4388         /* unsigned is easy */
4389
4390         pct1 = pic16_popGetTempReg(1);
4391         pct2 = pic16_popGetTempReg(1);
4392         pct3 = pic16_popGetTempReg(1);
4393         
4394         label1 = newiTempLabel(NULL);
4395         label2 = newiTempLabel(NULL);
4396         label3 = newiTempLabel(NULL);
4397
4398         /* the following algorithm is extracted from divuint.c */
4399
4400         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4401         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4402         
4403         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4404
4405         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4406         
4407         pic16_emitpLabel(label1->key);
4408         
4409         emitCLRC;
4410         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4411
4412
4413         emitCLRC;
4414         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4415         
4416
4417         emitSKPNC;
4418         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4419         
4420         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4421         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4422         
4423         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4424         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4425         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4426         
4427         pic16_emitpLabel( label3->key );
4428         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4429         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4430         
4431         
4432
4433         pic16_emitpLabel(label2->key);
4434         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4435         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4436         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4437         
4438         /* result is in wreg */
4439         if(AOP_TYPE(result) != AOP_ACC)
4440                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4441
4442         pic16_popReleaseTempReg( pct3, 1);
4443         pic16_popReleaseTempReg( pct2, 1);
4444         pic16_popReleaseTempReg( pct1, 1);
4445
4446         return ;
4447     }
4448
4449     /* signed is a little bit more difficult */
4450
4451     /* save the signs of the operands */
4452     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4453     MOVA(l);    
4454     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4455     pic16_emitcode("push","acc"); /* save it on the stack */
4456
4457     /* now sign adjust for both left & right */
4458     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4459     MOVA(l);       
4460     lbl = newiTempLabel(NULL);
4461     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4462     pic16_emitcode("cpl","a");   
4463     pic16_emitcode("inc","a");
4464     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4465     pic16_emitcode("mov","b,a");
4466
4467     /* sign adjust left side */
4468     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4469     MOVA(l);
4470
4471     lbl = newiTempLabel(NULL);
4472     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4473     pic16_emitcode("cpl","a");
4474     pic16_emitcode("inc","a");
4475     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4476
4477     /* now the division */
4478     pic16_emitcode("div","ab");
4479     /* we are interested in the lower order
4480     only */
4481     pic16_emitcode("mov","b,a");
4482     lbl = newiTempLabel(NULL);
4483     pic16_emitcode("pop","acc");   
4484     /* if there was an over flow we don't 
4485     adjust the sign of the result */
4486     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4487     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4488     CLRC;
4489     pic16_emitcode("clr","a");
4490     pic16_emitcode("subb","a,b");
4491     pic16_emitcode("mov","b,a");
4492     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4493
4494     /* now we are done */
4495     pic16_aopPut(AOP(result),"b",0);
4496     if(size > 0){
4497         pic16_emitcode("mov","c,b.7");
4498         pic16_emitcode("subb","a,acc");   
4499     }
4500     while (size--)
4501         pic16_aopPut(AOP(result),"a",offset++);
4502
4503 }
4504
4505 /*-----------------------------------------------------------------*/
4506 /* genDiv - generates code for division                            */
4507 /*-----------------------------------------------------------------*/
4508 static void genDiv (iCode *ic)
4509 {
4510     operand *left = IC_LEFT(ic);
4511     operand *right = IC_RIGHT(ic);
4512     operand *result= IC_RESULT(ic);   
4513
4514
4515         /* Division is a very lengthy algorithm, so it is better
4516          * to call support routines than inlining algorithm.
4517          * Division functions written here just in case someone
4518          * wants to inline and not use the support libraries -- VR */
4519
4520     FENTRY;
4521     
4522     /* assign the amsops */
4523     pic16_aopOp (left,ic,FALSE);
4524     pic16_aopOp (right,ic,FALSE);
4525     pic16_aopOp (result,ic,TRUE);
4526
4527     /* special cases first */
4528     /* both are bits */
4529     if (AOP_TYPE(left) == AOP_CRY &&
4530         AOP_TYPE(right)== AOP_CRY) {
4531         genDivbits(left,right,result);
4532         goto release ;
4533     }
4534
4535     /* if both are of size == 1 */
4536     if (AOP_SIZE(left) == 1 &&
4537         AOP_SIZE(right) == 1 ) {
4538         genDivOneByte(left,right,result);
4539         goto release ;
4540     }
4541
4542     /* should have been converted to function call */
4543     assert(0);
4544 release :
4545     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4546     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4547     pic16_freeAsmop(result,NULL,ic,TRUE); 
4548 }
4549
4550 /*-----------------------------------------------------------------*/
4551 /* genModbits :- modulus of bits                                   */
4552 /*-----------------------------------------------------------------*/
4553 static void genModbits (operand *left, 
4554                         operand *right, 
4555                         operand *result)
4556 {
4557   char *l;
4558
4559     FENTRY;  
4560     
4561     werror(W_POSSBUG2, __FILE__, __LINE__);
4562     /* the result must be bit */    
4563     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4564     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4565
4566     MOVA(l);       
4567
4568     pic16_emitcode("div","ab");
4569     pic16_emitcode("mov","a,b");
4570     pic16_emitcode("rrc","a");
4571     pic16_aopPut(AOP(result),"c",0);
4572 }
4573
4574 /*-----------------------------------------------------------------*/
4575 /* genModOneByte : 8 bit modulus                                   */
4576 /*-----------------------------------------------------------------*/
4577 static void genModOneByte (operand *left,
4578                            operand *right,
4579                            operand *result)
4580 {
4581   sym_link *opetype = operandType(result);
4582   char *l ;
4583   symbol *lbl ;
4584
4585     FENTRY;
4586     werror(W_POSSBUG2, __FILE__, __LINE__);
4587
4588     /* signed or unsigned */
4589     if (SPEC_USIGN(opetype)) {
4590         /* unsigned is easy */
4591         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4592         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4593         MOVA(l);    
4594         pic16_emitcode("div","ab");
4595         pic16_aopPut(AOP(result),"b",0);
4596         return ;
4597     }
4598
4599     /* signed is a little bit more difficult */
4600
4601     /* save the signs of the operands */
4602     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4603     MOVA(l);
4604
4605     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4606     pic16_emitcode("push","acc"); /* save it on the stack */
4607
4608     /* now sign adjust for both left & right */
4609     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4610     MOVA(l);
4611
4612     lbl = newiTempLabel(NULL);
4613     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4614     pic16_emitcode("cpl","a");   
4615     pic16_emitcode("inc","a");
4616     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4617     pic16_emitcode("mov","b,a"); 
4618
4619     /* sign adjust left side */
4620     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4621     MOVA(l);
4622
4623     lbl = newiTempLabel(NULL);
4624     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4625     pic16_emitcode("cpl","a");   
4626     pic16_emitcode("inc","a");
4627     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4628
4629     /* now the multiplication */
4630     pic16_emitcode("div","ab");
4631     /* we are interested in the lower order
4632     only */
4633     lbl = newiTempLabel(NULL);
4634     pic16_emitcode("pop","acc");   
4635     /* if there was an over flow we don't 
4636     adjust the sign of the result */
4637     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4638     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4639     CLRC ;
4640     pic16_emitcode("clr","a");
4641     pic16_emitcode("subb","a,b");
4642     pic16_emitcode("mov","b,a");
4643     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4644
4645     /* now we are done */
4646     pic16_aopPut(AOP(result),"b",0);
4647
4648 }
4649
4650 /*-----------------------------------------------------------------*/
4651 /* genMod - generates code for division                            */
4652 /*-----------------------------------------------------------------*/
4653 static void genMod (iCode *ic)
4654 {
4655   operand *left = IC_LEFT(ic);
4656   operand *right = IC_RIGHT(ic);
4657   operand *result= IC_RESULT(ic);  
4658
4659     FENTRY;
4660     
4661     /* assign the amsops */
4662     pic16_aopOp (left,ic,FALSE);
4663     pic16_aopOp (right,ic,FALSE);
4664     pic16_aopOp (result,ic,TRUE);
4665
4666     /* special cases first */
4667     /* both are bits */
4668     if (AOP_TYPE(left) == AOP_CRY &&
4669         AOP_TYPE(right)== AOP_CRY) {
4670         genModbits(left,right,result);
4671         goto release ;
4672     }
4673
4674     /* if both are of size == 1 */
4675     if (AOP_SIZE(left) == 1 &&
4676         AOP_SIZE(right) == 1 ) {
4677         genModOneByte(left,right,result);
4678         goto release ;
4679     }
4680
4681     /* should have been converted to function call */
4682     assert(0);
4683
4684 release :
4685     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4686     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4687     pic16_freeAsmop(result,NULL,ic,TRUE); 
4688 }
4689
4690 /*-----------------------------------------------------------------*/
4691 /* genIfxJump :- will create a jump depending on the ifx           */
4692 /*-----------------------------------------------------------------*/
4693 /*
4694   note: May need to add parameter to indicate when a variable is in bit space.
4695 */
4696 static void genIfxJump (iCode *ic, char *jval)
4697 {
4698   FENTRY;
4699   
4700     /* if true label then we jump if condition
4701     supplied is true */
4702     if ( IC_TRUE(ic) ) {
4703
4704         if(strcmp(jval,"a") == 0)
4705           emitSKPZ;
4706         else if (strcmp(jval,"c") == 0)
4707           emitSKPNC;
4708         else {
4709           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4710           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4711         }
4712
4713         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4714         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4715
4716     }
4717     else {
4718         /* false label is present */
4719         if(strcmp(jval,"a") == 0)
4720           emitSKPNZ;
4721         else if (strcmp(jval,"c") == 0)
4722           emitSKPC;
4723         else {
4724           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4725           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4726         }
4727
4728         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4729         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4730
4731     }
4732
4733
4734     /* mark the icode as generated */
4735     ic->generated = 1;
4736 }
4737
4738 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4739 {
4740   FENTRY;
4741   
4742     /* if true label then we jump if condition
4743     supplied is true */
4744     if ( IC_TRUE(ic) ) {
4745       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4746       pic16_emitpcode(POC_BTFSC, jop);
4747
4748       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4749       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4750
4751     } else {
4752       /* false label is present */
4753       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4754       pic16_emitpcode(POC_BTFSS, jop);
4755           
4756       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4757       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4758     }
4759
4760
4761     /* mark the icode as generated */
4762     ic->generated = 1;
4763 }
4764
4765 #if 0
4766 // not needed ATM
4767
4768 /*-----------------------------------------------------------------*/
4769 /* genSkip                                                         */
4770 /*-----------------------------------------------------------------*/
4771 static void genSkip(iCode *ifx,int status_bit)
4772 {
4773   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4774   if(!ifx)
4775     return;
4776
4777   if ( IC_TRUE(ifx) ) {
4778     switch(status_bit) {
4779     case 'z':
4780       emitSKPNZ;
4781       break;
4782
4783     case 'c':
4784       emitSKPNC;
4785       break;
4786
4787     case 'd':
4788       emitSKPDC;
4789       break;
4790
4791     }
4792
4793     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4794     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4795
4796   } else {
4797
4798     switch(status_bit) {
4799
4800     case 'z':
4801       emitSKPZ;
4802       break;
4803
4804     case 'c':
4805       emitSKPC;
4806       break;
4807
4808     case 'd':
4809       emitSKPDC;
4810       break;
4811     }
4812     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4813     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4814
4815   }
4816
4817 }
4818 #endif
4819
4820 /*-----------------------------------------------------------------*/
4821 /* genSkipc                                                        */
4822 /*-----------------------------------------------------------------*/
4823 static void genSkipc(resolvedIfx *rifx)
4824 {
4825   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4826   
4827   if(!rifx)
4828     return;
4829
4830   if(rifx->condition)
4831     emitSKPNC;
4832   else
4833     emitSKPC;
4834
4835   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4836   rifx->generated = 1;
4837 }
4838
4839 #if !(USE_SIMPLE_GENCMP)
4840 /*-----------------------------------------------------------------*/
4841 /* genSkipz2                                                       */
4842 /*-----------------------------------------------------------------*/
4843 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4844 {
4845   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4846   
4847   if(!rifx)
4848     return;
4849
4850   if( (rifx->condition ^ invert_condition) & 1)
4851     emitSKPZ;
4852   else
4853     emitSKPNZ;
4854
4855   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4856   rifx->generated = 1;
4857 }
4858 #endif
4859
4860 #if 0
4861 /*-----------------------------------------------------------------*/
4862 /* genSkipz                                                        */
4863 /*-----------------------------------------------------------------*/
4864 static void genSkipz(iCode *ifx, int condition)
4865 {
4866   if(!ifx)
4867     return;
4868
4869   if(condition)
4870     emitSKPNZ;
4871   else
4872     emitSKPZ;
4873
4874   if ( IC_TRUE(ifx) )
4875     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4876   else
4877     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4878
4879   if ( IC_TRUE(ifx) )
4880     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4881   else
4882     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4883
4884 }
4885 #endif
4886
4887 #if !(USE_SIMPLE_GENCMP)
4888 /*-----------------------------------------------------------------*/
4889 /* genSkipCond                                                     */
4890 /*-----------------------------------------------------------------*/
4891 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4892 {
4893   if(!rifx)
4894     return;
4895
4896   if(rifx->condition)
4897     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4898   else
4899     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4900
4901
4902   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4903   rifx->generated = 1;
4904 }
4905 #endif
4906
4907 #if 0
4908 /*-----------------------------------------------------------------*/
4909 /* genChkZeroes :- greater or less than comparison                 */
4910 /*     For each byte in a literal that is zero, inclusive or the   */
4911 /*     the corresponding byte in the operand with W                */
4912 /*     returns true if any of the bytes are zero                   */
4913 /*-----------------------------------------------------------------*/
4914 static int genChkZeroes(operand *op, int lit,  int size)
4915 {
4916
4917   int i;
4918   int flag =1;
4919
4920   while(size--) {
4921     i = (lit >> (size*8)) & 0xff;
4922
4923     if(i==0) {
4924       if(flag) 
4925         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4926       else
4927         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4928       flag = 0;
4929     }
4930   }
4931
4932   return (flag==0);
4933 }
4934 #endif
4935
4936
4937 /*-----------------------------------------------------------------*/
4938 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4939 /*                  aop (if it's NOT a literal) or from lit (if    */
4940 /*                  aop is a literal)                              */
4941 /*-----------------------------------------------------------------*/
4942 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4943   if (aop->type == AOP_LIT) {
4944     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4945   } else {
4946     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4947   }
4948 }
4949
4950 /*-----------------------------------------------------------------*/
4951 /* genCmp :- greater or less than comparison                       */
4952 /*-----------------------------------------------------------------*/
4953
4954 #if USE_SIMPLE_GENCMP           /* { */
4955
4956 /* genCmp performs a left < right comparison, stores
4957  * the outcome in result (if != NULL) and generates
4958  * control flow code for the ifx (if != NULL).
4959  *
4960  * This version leaves in sequences like
4961  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4962  * which should be optmized by the peephole
4963  * optimizer - RN 2005-01-01 */
4964 static void genCmp (operand *left,operand *right,
4965                     operand *result, iCode *ifx, int sign)
4966 {
4967   resolvedIfx rIfx;
4968   int size;
4969   int offs;
4970   symbol *templbl;
4971   operand *dummy;
4972   unsigned long lit;
4973   unsigned long mask;
4974   int performedLt;
4975
4976   FENTRY;
4977   
4978   assert (left && right);
4979   assert (AOP_SIZE(left) == AOP_SIZE(right));
4980
4981   size = AOP_SIZE(right) - 1;
4982   mask = (0x100UL << (size*8)) - 1;
4983   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4984   performedLt = 1;
4985   templbl = NULL;
4986   lit = 0;
4987   
4988   resolveIfx (&rIfx, ifx);
4989
4990   /* handle for special cases */
4991   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4992       return;
4993
4994   /**********************************************************************
4995    * handle bits - bit compares are promoted to int compares seemingly! *
4996    **********************************************************************/
4997 #if 0
4998   // THIS IS COMPLETELY UNTESTED!
4999   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5000     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5001     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5002     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5003
5004     emitSETC;
5005     // 1 < {0,1} is false --> clear C by skipping the next instruction
5006     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5007     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5008     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5009     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5010     emitCLRC; // only skipped for left=0 && right=1
5011
5012     goto correct_result_in_carry;
5013   } // if
5014 #endif
5015
5016   /*************************************************
5017    * make sure that left is register (or the like) *
5018    *************************************************/
5019   if (!isAOP_REGlike(left)) {
5020     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5021     assert (isAOP_LIT(left));
5022     assert (isAOP_REGlike(right));
5023     // swap left and right
5024     // left < right <==> right > left <==> (right >= left + 1)
5025     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5026
5027     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5028       // MAXVALUE < right? always false
5029       if (performedLt) emitCLRC; else emitSETC;
5030       goto correct_result_in_carry;
5031     } // if
5032
5033     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5034     // that's why we handled it above.
5035     lit++;
5036
5037     dummy = left;
5038     left = right;
5039     right = dummy;
5040
5041     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5042   } else if (isAOP_LIT(right)) {
5043     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5044   } // if
5045
5046   assert (isAOP_REGlike(left)); // left must be register or the like
5047   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5048
5049   /*************************************************
5050    * special cases go here                         *
5051    *************************************************/
5052
5053   if (isAOP_LIT(right)) {
5054     if (!sign) {
5055       // unsigned comparison to a literal
5056       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5057       if (lit == 0) {
5058         // unsigned left < 0? always false
5059         if (performedLt) emitCLRC; else emitSETC;
5060         goto correct_result_in_carry;
5061       }
5062     } else {
5063       // signed comparison to a literal
5064       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5065       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5066         // signed left < 0x80000000? always false
5067         if (performedLt) emitCLRC; else emitSETC;
5068         goto correct_result_in_carry;
5069       } else if (lit == 0) {
5070         // compare left < 0; set CARRY if SIGNBIT(left) is set
5071         if (performedLt) emitSETC; else emitCLRC;
5072         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5073         if (performedLt) emitCLRC; else emitSETC;
5074         goto correct_result_in_carry;
5075       }
5076     } // if (!sign)
5077   } // right is literal
5078
5079   /*************************************************
5080    * perform a general case comparison             *
5081    * make sure we get CARRY==1 <==> left >= right  *
5082    *************************************************/
5083   // compare most significant bytes
5084   //DEBUGpc ("comparing bytes at offset %d", size);
5085   if (!sign) {
5086     // unsigned comparison
5087     mov2w_regOrLit (AOP(right), lit, size);
5088     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5089   } else {
5090     // signed comparison
5091     // (add 2^n to both operands then perform an unsigned comparison)
5092     if (isAOP_LIT(right)) {
5093       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5094       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5095
5096       if (litbyte == 0x80) {
5097         // left >= 0x80 -- always true, but more bytes to come
5098         pic16_mov2w (AOP(left), size);
5099         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5100         emitSETC;
5101       } else {
5102         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5103         pic16_mov2w (AOP(left), size);
5104         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5105         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5106       } // if
5107     } else {
5108       /* using PRODL as a temporary register here */
5109       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5110       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5111       pic16_mov2w (AOP(left), size);
5112       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5113       pic16_emitpcode (POC_MOVWF, pctemp);
5114       pic16_mov2w (AOP(right), size);
5115       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5116       pic16_emitpcode (POC_SUBFW, pctemp);
5117       //pic16_popReleaseTempReg(pctemp, 1);
5118     }
5119   } // if (!sign)
5120
5121   // compare remaining bytes (treat as unsigned case from above)
5122   templbl = newiTempLabel ( NULL );
5123   offs = size;
5124   while (offs--) {
5125     //DEBUGpc ("comparing bytes at offset %d", offs);
5126     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5127     mov2w_regOrLit (AOP(right), lit, offs);
5128     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5129   } // while (offs)
5130   pic16_emitpLabel (templbl->key);
5131   goto result_in_carry;
5132
5133 result_in_carry:
5134   
5135   /****************************************************
5136    * now CARRY contains the result of the comparison: *
5137    * SUBWF sets CARRY iff                             *
5138    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5139    * (F=left, W=right)                                *
5140    ****************************************************/
5141
5142   if (performedLt) {
5143     if (result && AOP_TYPE(result) != AOP_CRY) {
5144       // value will be stored
5145       emitTOGC;
5146     } else {
5147       // value wil only be used in the following genSkipc()
5148       rIfx.condition ^= 1;
5149     }
5150   } // if
5151
5152 correct_result_in_carry:
5153
5154   // assign result to variable (if neccessary)
5155   if (result && AOP_TYPE(result) != AOP_CRY) {
5156     //DEBUGpc ("assign result");
5157     size = AOP_SIZE(result);
5158     while (size--) {
5159       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5160     } // while
5161     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5162   } // if (result)
5163
5164   // perform conditional jump
5165   if (ifx) {
5166     //DEBUGpc ("generate control flow");
5167     genSkipc (&rIfx);
5168     ifx->generated = 1;
5169   } // if
5170 }
5171
5172 #elif 1         /* } */
5173                 /* { */
5174       /* original code */
5175 static void genCmp (operand *left,operand *right,
5176                     operand *result, iCode *ifx, int sign)
5177 {
5178   int size; //, offset = 0 ;
5179   unsigned long lit = 0L,i = 0;
5180   resolvedIfx rFalseIfx;
5181   //  resolvedIfx rTrueIfx;
5182   symbol *truelbl;
5183   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5184 /*
5185   if(ifx) {
5186     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5187     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5188   }
5189 */
5190
5191   FENTRY;
5192   
5193   resolveIfx(&rFalseIfx,ifx);
5194   truelbl  = newiTempLabel(NULL);
5195   size = max(AOP_SIZE(left),AOP_SIZE(right));
5196
5197   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5198
5199 #define _swapp
5200
5201   /* if literal is on the right then swap with left */
5202   if ((AOP_TYPE(right) == AOP_LIT)) {
5203     operand *tmp = right ;
5204     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5205     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5206 #ifdef _swapp
5207
5208     lit = (lit - 1) & mask;
5209     right = left;
5210     left = tmp;
5211     rFalseIfx.condition ^= 1;
5212 #endif
5213
5214   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5215     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5216   }
5217
5218
5219   //if(IC_TRUE(ifx) == NULL)
5220   /* if left & right are bit variables */
5221   if (AOP_TYPE(left) == AOP_CRY &&
5222       AOP_TYPE(right) == AOP_CRY ) {
5223     assert (0 && "bit variables used in genCmp");
5224     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5225     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5226   } else {
5227     /* subtract right from left if at the
5228        end the carry flag is set then we know that
5229        left is greater than right */
5230
5231     symbol *lbl  = newiTempLabel(NULL);
5232
5233 #if 0
5234         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5235                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5236 #endif
5237
5238 #ifndef _swapp
5239     if(AOP_TYPE(right) == AOP_LIT) {
5240
5241       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5242
5243       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5244
5245       /* special cases */
5246
5247       if(lit == 0) {
5248
5249         if(sign != 0) 
5250           genSkipCond(&rFalseIfx,left,size-1,7);
5251         else 
5252           /* no need to compare to 0...*/
5253           /* NOTE: this is a de-generate compare that most certainly 
5254            *       creates some dead code. */
5255           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5256
5257         if(ifx) ifx->generated = 1;
5258         return;
5259
5260       }
5261       size--;
5262
5263       if(size == 0) {
5264         //i = (lit >> (size*8)) & 0xff;
5265         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5266         
5267         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5268
5269         i = ((0-lit) & 0xff);
5270         if(sign) {
5271           if( i == 0x81) { 
5272             /* lit is 0x7f, all signed chars are less than
5273              * this except for 0x7f itself */
5274             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5275             genSkipz2(&rFalseIfx,0);
5276           } else {
5277             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5278             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5279             genSkipc(&rFalseIfx);
5280           }
5281
5282         } else {
5283           if(lit == 1) {
5284             genSkipz2(&rFalseIfx,1);
5285           } else {
5286             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5287             genSkipc(&rFalseIfx);
5288           }
5289         }
5290
5291         if(ifx) ifx->generated = 1;
5292         return;
5293       }
5294
5295       /* chars are out of the way. now do ints and longs */
5296
5297
5298       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5299         
5300       /* special cases */
5301
5302       if(sign) {
5303
5304         if(lit == 0) {
5305           genSkipCond(&rFalseIfx,left,size,7);
5306           if(ifx) ifx->generated = 1;
5307           return;
5308         }
5309
5310         if(lit <0x100) {
5311           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5312
5313           //rFalseIfx.condition ^= 1;
5314           //genSkipCond(&rFalseIfx,left,size,7);
5315           //rFalseIfx.condition ^= 1;
5316
5317           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5318           if(rFalseIfx.condition)
5319             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5320           else
5321             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5322
5323           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5324           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5325           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5326
5327           while(size > 1)
5328             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5329
5330           if(rFalseIfx.condition) {
5331             emitSKPZ;
5332             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5333
5334           } else {
5335             emitSKPNZ;
5336           }
5337
5338           genSkipc(&rFalseIfx);
5339           pic16_emitpLabel(truelbl->key);
5340           if(ifx) ifx->generated = 1;
5341           return;
5342
5343         }
5344
5345         if(size == 1) {
5346
5347           if( (lit & 0xff) == 0) {
5348             /* lower byte is zero */
5349             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5350             i = ((lit >> 8) & 0xff) ^0x80;
5351             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5352             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5353             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5354             genSkipc(&rFalseIfx);
5355
5356
5357             if(ifx) ifx->generated = 1;
5358             return;
5359
5360           }
5361         } else {
5362           /* Special cases for signed longs */
5363           if( (lit & 0xffffff) == 0) {
5364             /* lower byte is zero */
5365             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5366             i = ((lit >> 8*3) & 0xff) ^0x80;
5367             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5368             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5369             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5370             genSkipc(&rFalseIfx);
5371
5372
5373             if(ifx) ifx->generated = 1;
5374             return;
5375
5376           }
5377
5378         }
5379
5380
5381         if(lit & (0x80 << (size*8))) {
5382           /* lit is negative */
5383           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5384
5385           //genSkipCond(&rFalseIfx,left,size,7);
5386
5387           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5388
5389           if(rFalseIfx.condition)
5390             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5391           else
5392             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5393
5394
5395         } else {
5396           /* lit is positive */
5397           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5398           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5399           if(rFalseIfx.condition)
5400             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5401           else
5402             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5403
5404         }
5405
5406         /*
5407           This works, but is only good for ints.
5408           It also requires a "known zero" register.
5409           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5410           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5411           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5412           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5413           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5414           genSkipc(&rFalseIfx);
5415
5416           pic16_emitpLabel(truelbl->key);
5417           if(ifx) ifx->generated = 1;
5418           return;
5419         **/
5420           
5421         /* There are no more special cases, so perform a general compare */
5422   
5423         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5424         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5425
5426         while(size--) {
5427
5428           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5429           emitSKPNZ;
5430           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5431         }
5432         //rFalseIfx.condition ^= 1;
5433         genSkipc(&rFalseIfx);
5434
5435         pic16_emitpLabel(truelbl->key);
5436
5437         if(ifx) ifx->generated = 1;
5438         return;
5439
5440
5441       }
5442
5443
5444       /* sign is out of the way. So now do an unsigned compare */
5445       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5446
5447
5448       /* General case - compare to an unsigned literal on the right.*/
5449
5450       i = (lit >> (size*8)) & 0xff;
5451       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5452       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5453       while(size--) {
5454         i = (lit >> (size*8)) & 0xff;
5455
5456         if(i) {
5457           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5458           emitSKPNZ;
5459           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5460         } else {
5461           /* this byte of the lit is zero, 
5462            *if it's not the last then OR in the variable */
5463           if(size)
5464             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5465         }
5466       }
5467
5468
5469       pic16_emitpLabel(lbl->key);
5470 //      pic16_emitpLabel(truelbl->key);
5471       //if(emitFinalCheck)
5472       genSkipc(&rFalseIfx);
5473       if(sign)
5474         pic16_emitpLabel(truelbl->key);
5475
5476       if(ifx) ifx->generated = 1;
5477       return;
5478
5479
5480     }
5481 #endif  // _swapp
5482
5483     if(AOP_TYPE(left) == AOP_LIT) {
5484       //symbol *lbl = newiTempLabel(NULL);
5485
5486       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5487
5488
5489       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5490
5491       /* Special cases */
5492       if((lit == 0) && (sign == 0)){
5493
5494         size--;
5495         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5496         while(size) 
5497           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5498
5499         genSkipz2(&rFalseIfx,0);
5500         if(ifx) ifx->generated = 1;
5501         return;
5502       }
5503
5504       if(size==1) {
5505         /* Special cases */
5506         lit &= 0xff;
5507         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5508           /* degenerate compare can never be true */
5509           if(rFalseIfx.condition == 0)
5510             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5511
5512           if(ifx) ifx->generated = 1;
5513           return;
5514         }
5515
5516         if(sign) {
5517           /* signed comparisons to a literal byte */
5518
5519           int lp1 = (lit+1) & 0xff;
5520
5521           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5522           switch (lp1) {
5523           case 0:
5524             rFalseIfx.condition ^= 1;
5525             genSkipCond(&rFalseIfx,right,0,7);
5526             break;
5527           case 0x7f:
5528             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5529             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5530             genSkipz2(&rFalseIfx,1);
5531             break;
5532           default:
5533             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5534             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5535             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5536             rFalseIfx.condition ^= 1;
5537             genSkipc(&rFalseIfx);
5538             break;
5539           }
5540         } else {
5541           /* unsigned comparisons to a literal byte */
5542
5543           switch(lit & 0xff ) {
5544           case 0:
5545             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5546             genSkipz2(&rFalseIfx,0);
5547             break;
5548           case 0x7f:
5549             rFalseIfx.condition ^= 1;
5550             genSkipCond(&rFalseIfx,right,0,7);
5551             break;
5552
5553           default:
5554             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5555             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5556             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5557             rFalseIfx.condition ^= 1;
5558             if (AOP_TYPE(result) == AOP_CRY)
5559               genSkipc(&rFalseIfx);
5560             else {
5561               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5562               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5563             }         
5564             break;
5565           }
5566         }
5567
5568         if(ifx) ifx->generated = 1;
5569         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5570                 goto check_carry;
5571         return;
5572
5573       } else {
5574
5575         /* Size is greater than 1 */
5576
5577         if(sign) {
5578           int lp1 = lit+1;
5579
5580           size--;
5581
5582           if(lp1 == 0) {
5583             /* this means lit = 0xffffffff, or -1 */
5584
5585
5586             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5587             rFalseIfx.condition ^= 1;
5588             genSkipCond(&rFalseIfx,right,size,7);
5589             if(ifx) ifx->generated = 1;
5590
5591             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5592               goto check_carry;
5593
5594             return;
5595           }
5596
5597           if(lit == 0) {
5598             int s = size;
5599
5600             if(rFalseIfx.condition) {
5601               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5602               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5603             }
5604
5605             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5606             while(size--)
5607               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5608
5609
5610             emitSKPZ;
5611             if(rFalseIfx.condition) {
5612               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5613               pic16_emitpLabel(truelbl->key);
5614             }else {
5615               rFalseIfx.condition ^= 1;
5616               genSkipCond(&rFalseIfx,right,s,7);
5617             }
5618
5619             if(ifx) ifx->generated = 1;
5620
5621             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5622               goto check_carry;
5623
5624             return;
5625           }
5626
5627           if((size == 1) &&  (0 == (lp1&0xff))) {
5628             /* lower byte of signed word is zero */
5629             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5630             i = ((lp1 >> 8) & 0xff) ^0x80;
5631             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5632             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5633             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5634
5635             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5636               emitTOGC;
5637               if(ifx) ifx->generated = 1;
5638               goto check_carry;
5639             } else {
5640               rFalseIfx.condition ^= 1;
5641               genSkipc(&rFalseIfx);
5642               if(ifx) ifx->generated = 1;
5643             }
5644
5645             return;
5646           }
5647
5648           if(lit & (0x80 << (size*8))) {
5649             /* Lit is less than zero */
5650             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5651             //rFalseIfx.condition ^= 1;
5652             //genSkipCond(&rFalseIfx,left,size,7);
5653             //rFalseIfx.condition ^= 1;
5654             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5655             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5656
5657             if(rFalseIfx.condition)
5658               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5659             else
5660               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5661
5662
5663           } else {
5664             /* Lit is greater than or equal to zero */
5665             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5666             //rFalseIfx.condition ^= 1;
5667             //genSkipCond(&rFalseIfx,right,size,7);
5668             //rFalseIfx.condition ^= 1;
5669
5670             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5671             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5672
5673             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5674             if(rFalseIfx.condition)
5675               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5676             else
5677               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5678
5679           }
5680
5681           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5682           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5683
5684           while(size--) {
5685
5686             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5687             emitSKPNZ;
5688             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5689           }
5690           rFalseIfx.condition ^= 1;
5691           //rFalseIfx.condition = 1;
5692           genSkipc(&rFalseIfx);
5693
5694           pic16_emitpLabel(truelbl->key);
5695
5696           if(ifx) ifx->generated = 1;
5697
5698
5699           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5700             goto check_carry;
5701
5702           return;
5703           // end of if (sign)
5704         } else {
5705
5706           /* compare word or long to an unsigned literal on the right.*/
5707
5708
5709           size--;
5710           if(lit < 0xff) {
5711             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5712             switch (lit) {
5713             case 0:
5714               break; /* handled above */
5715 /*
5716             case 0xff:
5717               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5718               while(size--)
5719                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5720               genSkipz2(&rFalseIfx,0);
5721               break;
5722 */
5723             default:
5724               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5725               while(--size)
5726                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5727
5728               emitSKPZ;
5729               if(rFalseIfx.condition)
5730                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5731               else
5732                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5733
5734
5735               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5736               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5737
5738               rFalseIfx.condition ^= 1;
5739               genSkipc(&rFalseIfx);
5740             }
5741
5742             pic16_emitpLabel(truelbl->key);
5743
5744             if(ifx) ifx->generated = 1;
5745
5746             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5747               goto check_carry;
5748
5749             return;
5750           }
5751
5752
5753           lit++;
5754           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5755           i = (lit >> (size*8)) & 0xff;
5756
5757           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5758           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5759
5760           while(size--) {
5761             i = (lit >> (size*8)) & 0xff;
5762
5763             if(i) {
5764               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5765               emitSKPNZ;
5766               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5767             } else {
5768               /* this byte of the lit is zero, 
5769                * if it's not the last then OR in the variable */
5770               if(size)
5771                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5772             }
5773           }
5774
5775
5776           pic16_emitpLabel(lbl->key);
5777
5778           rFalseIfx.condition ^= 1;
5779
5780           genSkipc(&rFalseIfx);
5781         }
5782
5783         if(sign)
5784           pic16_emitpLabel(truelbl->key);
5785         if(ifx) ifx->generated = 1;
5786
5787             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5788               goto check_carry;
5789
5790         return;
5791       }
5792     }
5793     /* Compare two variables */
5794
5795     DEBUGpic16_emitcode(";sign","%d",sign);
5796
5797     size--;
5798     if(sign) {
5799       /* Sigh. thus sucks... */
5800       if(size) {
5801         pCodeOp *pctemp;
5802         
5803         pctemp = pic16_popGetTempReg(1);
5804         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5805         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5806         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5807         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5808         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5809         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5810         pic16_popReleaseTempReg(pctemp, 1);
5811       } else {
5812         /* Signed char comparison */
5813         /* Special thanks to Nikolai Golovchenko for this snippet */
5814         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5815         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5816         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5817         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5818         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5819         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5820
5821         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5822         genSkipc(&rFalseIfx);
5823           
5824         if(ifx) ifx->generated = 1;
5825
5826             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5827               goto check_carry;
5828
5829         return;
5830       }
5831
5832     } else {
5833
5834       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5835       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5836     }
5837
5838
5839     /* The rest of the bytes of a multi-byte compare */
5840     while (size) {
5841
5842       emitSKPZ;
5843       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5844       size--;
5845
5846       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5847       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5848
5849
5850     }
5851
5852     pic16_emitpLabel(lbl->key);
5853
5854     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5855     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5856         (AOP_TYPE(result) == AOP_REG)) {
5857       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5858       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5859     } else {
5860       genSkipc(&rFalseIfx);
5861     }         
5862     //genSkipc(&rFalseIfx);
5863     if(ifx) ifx->generated = 1;
5864
5865
5866             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5867               goto check_carry;
5868
5869     return;
5870
5871   }
5872
5873 check_carry:
5874   if ((AOP_TYPE(result) != AOP_CRY) 
5875         && AOP_SIZE(result)) {
5876     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5877
5878     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5879
5880     pic16_outBitC(result);
5881   } else {
5882     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5883     /* if the result is used in the next
5884        ifx conditional branch then generate
5885        code a little differently */
5886     if (ifx )
5887       genIfxJump (ifx,"c");
5888     else
5889       pic16_outBitC(result);
5890     /* leave the result in acc */
5891   }
5892
5893 }
5894
5895 #elif 0 /* VR version of genCmp() */    /* } else { */
5896
5897 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5898 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5899         operand *result, int offset, int invert_op)
5900 {
5901   /* add code here */
5902   
5903   /* check condition, > or < ?? */
5904   if(rIfx->condition != 0)invert_op ^= 1;
5905   
5906   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5907
5908   if(!ifx)invert_op ^= 1;
5909
5910   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5911       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5912   
5913   /* do selection */
5914   if(!invert_op)return POC_CPFSGT;
5915   else return POC_CPFSLT;
5916 }
5917
5918 static int compareAopfirstpass=1;
5919
5920 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5921             operand *oper, int offset, operand *result,
5922             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5923             symbol *tlbl)
5924 {
5925   int op;
5926   symbol *truelbl;
5927
5928   /* invert if there is a result to be loaded, in order to fit,
5929    * SETC/CLRC sequence */
5930   if(AOP_SIZE(result))invert_op ^= 1;
5931
5932 //  if(sign && !offset)invert_op ^= 1;
5933   
5934 //  if(sign)invert_op ^= 1;
5935   
5936   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5937
5938   if(AOP_SIZE(result) && compareAopfirstpass) {
5939     if(!ifx) {
5940       if(pcop2)
5941         pic16_emitpcode(POC_SETF, pcop2);
5942       else
5943         emitSETC;
5944     } else {
5945       if(pcop2)
5946         pic16_emitpcode(POC_CLRF, pcop2);
5947       else
5948         emitCLRC;
5949     }
5950   }
5951
5952   compareAopfirstpass = 0;
5953
5954       /* there is a bug when comparing operands with size > 1,
5955        * because higher bytes can be equal and test should be performed
5956        * to the next lower byte, current algorithm, considers operands
5957        * inequal in these cases! -- VR 20041107 */
5958
5959     
5960   if(pcop)
5961     pic16_emitpcode(op, pcop);
5962   else
5963     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5964
5965
5966   if((!sign || !offset) && AOP_SIZE(result)) {
5967     if(!ifx) {
5968       if(pcop2)
5969         pic16_emitpcode(POC_CLRF, pcop2);
5970         else
5971         emitCLRC;
5972     } else {
5973       if(pcop2)
5974         pic16_emitpcode(POC_SETF, pcop2);
5975       else
5976         emitSETC;
5977     }
5978     
5979     /* don't emit final branch (offset == 0) */
5980     if(offset) {
5981
5982       if(pcop2)
5983         pic16_emitpcode(POC_RRCF, pcop2);
5984
5985       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5986     }
5987   } else {
5988     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5989       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5990             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5991
5992       truelbl = newiTempLabel( NULL );
5993       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5994       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5995         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5996       else
5997         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5998       pic16_emitpLabel(truelbl->key);
5999     } else {
6000       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6001     }
6002   }
6003 }
6004
6005 static void genCmp (operand *left, operand *right,
6006                     operand *result, iCode *ifx, int sign)
6007 {
6008   int size, cmpop=1;
6009   long lit = 0L;
6010   resolvedIfx rFalseIfx;
6011   symbol *falselbl, *tlbl;
6012
6013     FENTRY;
6014     
6015     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6016
6017     resolveIfx(&rFalseIfx, ifx);
6018     size = max(AOP_SIZE(left), AOP_SIZE(right));
6019     
6020     /* if left & right are bit variables */
6021     if(AOP_TYPE(left) == AOP_CRY
6022       && AOP_TYPE(right) == AOP_CRY ) {
6023
6024         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6025         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6026         
6027         werror(W_POSSBUG2, __FILE__, __LINE__);
6028         exit(-1);
6029     }
6030     
6031     /* if literal is on the right then swap with left */
6032     if((AOP_TYPE(right) == AOP_LIT)) {
6033       operand *tmp = right ;
6034 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6035
6036         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6037
6038 //      lit = (lit - 1) & mask;
6039         right = left;
6040         left = tmp;
6041         rFalseIfx.condition ^= 1;               /* reverse compare */
6042     } else
6043     if ((AOP_TYPE(left) == AOP_LIT)) {
6044       /* float compares are handled by support functions */
6045       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6046     }
6047
6048     /* actual comparing algorithm */
6049 //    size = AOP_SIZE( right );
6050
6051     falselbl = newiTempLabel( NULL );
6052     if(AOP_TYPE(left) == AOP_LIT) {
6053       /* compare to literal */
6054       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6055       
6056       if(sign) {
6057         pCodeOp *pct, *pct2;
6058         symbol *tlbl1;
6059
6060         /* signed compare */
6061         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6062
6063         /* using PRODL:PRODH as a temporary register here */
6064         pct = pic16_popCopyReg(&pic16_pc_prodl);
6065         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6066         tlbl = newiTempLabel( NULL );
6067         
6068         /* first compare signs:
6069          *  a. if both are positive, compare just like unsigned
6070          *  b. if both are negative, invert cmpop, compare just like unsigned
6071          *  c. if different signs, determine the result directly */
6072
6073         size--;
6074
6075 #if 1
6076         /* { */
6077         tlbl1 = newiTempLabel( NULL );
6078 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6079
6080         if(lit > 0) {
6081
6082           /* literal is zero or positive:
6083            *  a. if carry is zero, too, continue compare,
6084            *  b. if carry is set, then continue depending on cmpop ^ condition:
6085            *    1. '<' return false (literal < variable),
6086            *    2. '>' return true (literal > variable) */
6087 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6088           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6089           
6090           
6091           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6092           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6093         } else 
6094         if(lit < 0) {
6095           
6096           /* literal is negative:
6097            *  a. if carry is set, too, continue compare,
6098            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6099            *    1. '<' return true (literal < variable),
6100            *    2. '>' return false (literal > variable) */
6101 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6102           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6103           
6104           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6105           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6106         }
6107 #if 1
6108         else {
6109           /* lit == 0 */
6110           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6111           
6112           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6113           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6114         }
6115 #endif
6116         
6117         
6118         pic16_emitpLabel( tlbl1->key );
6119 #endif  /* } */
6120
6121         compareAopfirstpass=1;
6122 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6123 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6124 //        pic16_emitpcode(POC_MOVWF, pct);
6125
6126 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6127         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6128 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6129         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6130
6131         /* generic case */        
6132           while( size-- ) {
6133 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6134 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6135 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6136 //            pic16_emitpcode(POC_MOVWF, pct);
6137
6138 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6139             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6140             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6141 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6142 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6143           }
6144         
6145         if(ifx)ifx->generated = 1;
6146
6147         if(AOP_SIZE(result)) {
6148           pic16_emitpLabel(tlbl->key);
6149           pic16_emitpLabel(falselbl->key);
6150           pic16_outBitOp( result, pct2 );
6151         } else {
6152           pic16_emitpLabel(tlbl->key);
6153         }
6154       } else {
6155
6156         /* unsigned compare */      
6157         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6158     
6159         compareAopfirstpass=1;
6160         while(size--) {
6161           
6162           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6163           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6164
6165         }
6166         if(ifx)ifx->generated = 1;
6167
6168         if(AOP_SIZE(result)) {
6169           pic16_emitpLabel(falselbl->key);
6170           pic16_outBitC( result );
6171         }
6172
6173       }
6174     } else {
6175       /* compare registers */
6176       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6177
6178
6179       if(sign) {
6180         pCodeOp *pct, *pct2;
6181         
6182         /* signed compare */
6183         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6184
6185         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6186         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6187         tlbl = newiTempLabel( NULL );
6188         
6189         compareAopfirstpass=1;
6190
6191         size--;
6192         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6193 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6194         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6195         pic16_emitpcode(POC_MOVWF, pct);
6196
6197         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6198 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6199         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6200
6201         /* WREG already holds left + 0x80 */
6202         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6203         
6204         while( size-- ) {
6205           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6206 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6207           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6208           pic16_emitpcode(POC_MOVWF, pct);
6209                 
6210           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6211 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6212           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6213
6214           /* WREG already holds left + 0x80 */
6215           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6216 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6217         }
6218         
6219         if(ifx)ifx->generated = 1;
6220
6221         if(AOP_SIZE(result)) {
6222           pic16_emitpLabel(tlbl->key);
6223           pic16_emitpLabel(falselbl->key);
6224           pic16_outBitOp( result, pct2 );
6225         } else {
6226           pic16_emitpLabel(tlbl->key);
6227         }
6228
6229       } else {
6230         /* unsigned compare */      
6231         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6232
6233         compareAopfirstpass=1;
6234         while(size--) {
6235           
6236           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6237           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6238
6239         }
6240
6241         if(ifx)ifx->generated = 1;
6242         if(AOP_SIZE(result)) {
6243
6244           pic16_emitpLabel(falselbl->key);
6245           pic16_outBitC( result );
6246         }
6247
6248       }
6249     }
6250 }
6251
6252 #endif  /* } */
6253
6254
6255
6256 /*-----------------------------------------------------------------*/
6257 /* genCmpGt :- greater than comparison                             */
6258 /*-----------------------------------------------------------------*/
6259 static void genCmpGt (iCode *ic, iCode *ifx)
6260 {
6261   operand *left, *right, *result;
6262   sym_link *letype , *retype;
6263   int sign ;
6264
6265     FENTRY;
6266     
6267     left = IC_LEFT(ic);
6268     right= IC_RIGHT(ic);
6269     result = IC_RESULT(ic);
6270
6271     letype = getSpec(operandType(left));
6272     retype =getSpec(operandType(right));
6273     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6274     /* assign the amsops */
6275     pic16_aopOp (left,ic,FALSE);
6276     pic16_aopOp (right,ic,FALSE);
6277     pic16_aopOp (result,ic,TRUE);
6278
6279     genCmp(right, left, result, ifx, sign);
6280
6281     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6282     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6283     pic16_freeAsmop(result,NULL,ic,TRUE); 
6284 }
6285
6286 /*-----------------------------------------------------------------*/
6287 /* genCmpLt - less than comparisons                                */
6288 /*-----------------------------------------------------------------*/
6289 static void genCmpLt (iCode *ic, iCode *ifx)
6290 {
6291   operand *left, *right, *result;
6292   sym_link *letype , *retype;
6293   int sign ;
6294
6295     FENTRY;
6296
6297     left = IC_LEFT(ic);
6298     right= IC_RIGHT(ic);
6299     result = IC_RESULT(ic);
6300
6301     letype = getSpec(operandType(left));
6302     retype =getSpec(operandType(right));
6303     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6304
6305     /* assign the amsops */
6306     pic16_aopOp (left,ic,FALSE);
6307     pic16_aopOp (right,ic,FALSE);
6308     pic16_aopOp (result,ic,TRUE);
6309
6310     genCmp(left, right, result, ifx, sign);
6311
6312     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6313     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6314     pic16_freeAsmop(result,NULL,ic,TRUE); 
6315 }
6316
6317 #if 0
6318 // not needed ATM
6319 // FIXME reenable literal optimisation when the pic16 port is stable
6320
6321 /*-----------------------------------------------------------------*/
6322 /* genc16bit2lit - compare a 16 bit value to a literal             */
6323 /*-----------------------------------------------------------------*/
6324 static void genc16bit2lit(operand *op, int lit, int offset)
6325 {
6326   int i;
6327
6328   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6329   if( (lit&0xff) == 0) 
6330     i=1;
6331   else
6332     i=0;
6333
6334   switch( BYTEofLONG(lit,i)) { 
6335   case 0:
6336     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6337     break;
6338   case 1:
6339     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6340     break;
6341   case 0xff:
6342     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6343     break;
6344   default:
6345     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6346     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6347   }
6348
6349   i ^= 1;
6350
6351   switch( BYTEofLONG(lit,i)) { 
6352   case 0:
6353     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6354     break;
6355   case 1:
6356     emitSKPNZ;
6357     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6358     break;
6359   case 0xff:
6360     emitSKPNZ;
6361     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6362     break;
6363   default:
6364     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6365     emitSKPNZ;
6366     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6367
6368   }
6369
6370 }
6371 #endif
6372
6373 #if 0
6374 // not needed ATM
6375 /*-----------------------------------------------------------------*/
6376 /* gencjneshort - compare and jump if not equal                    */
6377 /*-----------------------------------------------------------------*/
6378 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6379 {
6380   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6381   int offset = 0;
6382   int res_offset = 0;  /* the result may be a different size then left or right */
6383   int res_size = AOP_SIZE(result);
6384   resolvedIfx rIfx;
6385   symbol *lbl, *lbl_done;
6386
6387   unsigned long lit = 0L;
6388   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6389
6390   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6391   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6392   if(result)
6393     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6394   resolveIfx(&rIfx,ifx);
6395   lbl =  newiTempLabel(NULL);
6396   lbl_done =  newiTempLabel(NULL);
6397
6398
6399   /* if the left side is a literal or 
6400      if the right is in a pointer register and left 
6401      is not */
6402   if ((AOP_TYPE(left) == AOP_LIT) || 
6403       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6404     operand *t = right;
6405     right = left;
6406     left = t;
6407   }
6408   if(AOP_TYPE(right) == AOP_LIT)
6409     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6410
6411   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6412     preserve_result = 1;
6413
6414   if(result && !preserve_result)
6415     {
6416       int i;
6417       for(i = 0; i < AOP_SIZE(result); i++)
6418         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6419     }
6420
6421
6422   /* if the right side is a literal then anything goes */
6423   if (AOP_TYPE(right) == AOP_LIT &&
6424       AOP_TYPE(left) != AOP_DIR ) {
6425     switch(size) {
6426     case 2:
6427       genc16bit2lit(left, lit, 0);
6428       emitSKPZ;
6429       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6430       break;
6431     default:
6432       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6433       while (size--) {
6434         if(lit & 0xff) {
6435           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6436           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6437         } else {
6438           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6439         }
6440
6441         emitSKPZ;
6442         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6443         offset++;
6444         if(res_offset < res_size-1)
6445           res_offset++;
6446         lit >>= 8;
6447       }
6448       break;
6449     }
6450   }
6451
6452   /* if the right side is in a register or in direct space or
6453      if the left is a pointer register & right is not */    
6454   else if (AOP_TYPE(right) == AOP_REG ||
6455            AOP_TYPE(right) == AOP_DIR || 
6456            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6457            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6458     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6459     int lbl_key = lbl->key;
6460
6461     if(result) {
6462       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6463       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6464     }else {
6465       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6466       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6467               __FUNCTION__,__LINE__);
6468       return;
6469     }
6470    
6471 /*     switch(size) { */
6472 /*     case 2: */
6473 /*       genc16bit2lit(left, lit, 0); */
6474 /*       emitSKPNZ; */
6475 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6476 /*       break; */
6477 /*     default: */
6478     while (size--) {
6479       int emit_skip=1;
6480       if((AOP_TYPE(left) == AOP_DIR) && 
6481          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6482
6483         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6484         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6485
6486       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6487             
6488         switch (lit & 0xff) {
6489         case 0:
6490           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6491           break;
6492         case 1:
6493           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6494           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6495           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6496           emit_skip=0;
6497           break;
6498         case 0xff:
6499           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6500           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6501           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6502           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6503           emit_skip=0;
6504           break;
6505         default:
6506           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6507           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6508         }
6509         lit >>= 8;
6510
6511       } else {
6512         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6513       }
6514       if(emit_skip) {
6515         if(AOP_TYPE(result) == AOP_CRY) {
6516           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6517           if(rIfx.condition)
6518             emitSKPNZ;
6519           else
6520             emitSKPZ;
6521           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6522         } else {
6523           /* fix me. probably need to check result size too */
6524           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6525           if(rIfx.condition)
6526             emitSKPZ;
6527           else
6528             emitSKPNZ;
6529           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6530           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6531         }
6532         if(ifx)
6533           ifx->generated=1;
6534       }
6535       emit_skip++;
6536       offset++;
6537       if(res_offset < res_size-1)
6538         res_offset++;
6539     }
6540 /*       break; */
6541 /*     } */
6542   } else if(AOP_TYPE(right) == AOP_REG &&
6543             AOP_TYPE(left) != AOP_DIR){
6544
6545     while(size--) {
6546       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6547       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6548       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6549       if(rIfx.condition)
6550         emitSKPNZ;
6551       else
6552         emitSKPZ;
6553       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6554       offset++;
6555       if(res_offset < res_size-1)
6556         res_offset++;
6557     }
6558       
6559   }else{
6560     /* right is a pointer reg need both a & b */
6561     while(size--) {
6562       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6563       if(strcmp(l,"b"))
6564         pic16_emitcode("mov","b,%s",l);
6565       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6566       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6567       offset++;
6568     }
6569   }
6570
6571   if(result && preserve_result)
6572     {
6573       int i;
6574       for(i = 0; i < AOP_SIZE(result); i++)
6575         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6576     }
6577
6578   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6579
6580   if(result && preserve_result)
6581     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6582
6583   if(!rIfx.condition)
6584     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6585
6586   pic16_emitpLabel(lbl->key);
6587
6588   if(result && preserve_result)
6589     {
6590       int i;
6591       for(i = 0; i < AOP_SIZE(result); i++)
6592         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6593
6594       pic16_emitpLabel(lbl_done->key);
6595    }
6596
6597   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6598
6599   if(ifx)
6600     ifx->generated = 1;
6601 }
6602 #endif
6603
6604 #if 0
6605 /*-----------------------------------------------------------------*/
6606 /* gencjne - compare and jump if not equal                         */
6607 /*-----------------------------------------------------------------*/
6608 static void gencjne(operand *left, operand *right, iCode *ifx)
6609 {
6610     symbol *tlbl  = newiTempLabel(NULL);
6611
6612     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6613     gencjneshort(left, right, lbl);
6614
6615     pic16_emitcode("mov","a,%s",one);
6616     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6617     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6618     pic16_emitcode("clr","a");
6619     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6620
6621     pic16_emitpLabel(lbl->key);
6622     pic16_emitpLabel(tlbl->key);
6623
6624 }
6625 #endif
6626
6627
6628 /*-----------------------------------------------------------------*/
6629 /* is_LitOp - check if operand has to be treated as literal        */
6630 /*-----------------------------------------------------------------*/
6631 static bool is_LitOp(operand *op)
6632 {
6633   return ((AOP_TYPE(op) == AOP_LIT)
6634       || ( (AOP_TYPE(op) == AOP_PCODE)
6635           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6636               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6637 }
6638
6639 /*-----------------------------------------------------------------*/
6640 /* is_LitAOp - check if operand has to be treated as literal        */
6641 /*-----------------------------------------------------------------*/
6642 static bool is_LitAOp(asmop *aop)
6643 {
6644   return ((aop->type == AOP_LIT)
6645       || ( (aop->type == AOP_PCODE)
6646           && ( (aop->aopu.pcop->type == PO_LITERAL)
6647               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6648 }
6649
6650
6651
6652 /*-----------------------------------------------------------------*/
6653 /* genCmpEq - generates code for equal to                          */
6654 /*-----------------------------------------------------------------*/
6655 static void genCmpEq (iCode *ic, iCode *ifx)
6656 {
6657   operand *left, *right, *result;
6658   symbol *falselbl = newiTempLabel(NULL);
6659   symbol *donelbl = newiTempLabel(NULL);
6660
6661   int preserve_result = 0;
6662   int generate_result = 0;
6663   int i=0;
6664   unsigned long lit = -1;
6665
6666   FENTRY;
6667   
6668   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6669   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6670   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6671  
6672   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6673
6674   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6675     {
6676       werror(W_POSSBUG2, __FILE__, __LINE__);
6677       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6678       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6679       goto release;
6680     }
6681
6682   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6683     {
6684       operand *tmp = right ;
6685       right = left;
6686       left = tmp;
6687     }
6688
6689   if (AOP_TYPE(right) == AOP_LIT) {
6690     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6691   }
6692
6693   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6694     preserve_result = 1;
6695
6696   if(result && AOP_SIZE(result))
6697     generate_result = 1;
6698
6699   if(generate_result && !preserve_result)
6700     {
6701       for(i = 0; i < AOP_SIZE(result); i++)
6702         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6703     }
6704
6705   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6706   for(i=0; i < AOP_SIZE(left); i++)
6707     {
6708       if(AOP_TYPE(left) != AOP_ACC)
6709         {
6710           if(is_LitOp(left))
6711             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6712           else
6713             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6714         }
6715       if(is_LitOp(right)) {
6716         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6717           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6718         }
6719       } else
6720         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6721
6722       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6723     }
6724
6725   // result == true
6726
6727   if(generate_result && preserve_result)
6728     {
6729       for(i = 0; i < AOP_SIZE(result); i++)
6730         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6731     }
6732
6733   if(generate_result)
6734     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6735
6736   if(generate_result && preserve_result)
6737     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6738
6739   if(ifx && IC_TRUE(ifx))
6740     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6741
6742   if(ifx && IC_FALSE(ifx))
6743     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6744
6745   pic16_emitpLabel(falselbl->key);
6746
6747   // result == false
6748
6749   if(ifx && IC_FALSE(ifx))
6750     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6751
6752   if(generate_result && preserve_result)
6753     {
6754       for(i = 0; i < AOP_SIZE(result); i++)
6755         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6756     }
6757
6758   pic16_emitpLabel(donelbl->key);
6759
6760   if(ifx)
6761     ifx->generated = 1;
6762
6763 release:
6764   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6765   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6766   pic16_freeAsmop(result,NULL,ic,TRUE);
6767
6768 }
6769
6770
6771 #if 0
6772 // old version kept for reference
6773
6774 /*-----------------------------------------------------------------*/
6775 /* genCmpEq - generates code for equal to                          */
6776 /*-----------------------------------------------------------------*/
6777 static void genCmpEq (iCode *ic, iCode *ifx)
6778 {
6779     operand *left, *right, *result;
6780     unsigned long lit = 0L;
6781     int size,offset=0;
6782     symbol *falselbl  = newiTempLabel(NULL);
6783
6784
6785     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6786
6787     if(ifx)
6788       DEBUGpic16_emitcode ("; ifx is non-null","");
6789     else
6790       DEBUGpic16_emitcode ("; ifx is null","");
6791
6792     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6793     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6794     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6795
6796     size = max(AOP_SIZE(left),AOP_SIZE(right));
6797
6798     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6799
6800     /* if literal, literal on the right or 
6801     if the right is in a pointer register and left 
6802     is not */
6803     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6804         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6805       operand *tmp = right ;
6806       right = left;
6807       left = tmp;
6808     }
6809
6810
6811     if(ifx && !AOP_SIZE(result)){
6812         symbol *tlbl;
6813         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6814         /* if they are both bit variables */
6815         if (AOP_TYPE(left) == AOP_CRY &&
6816             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6817                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6818             if(AOP_TYPE(right) == AOP_LIT){
6819                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6820                 if(lit == 0L){
6821                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6822                     pic16_emitcode("cpl","c");
6823                 } else if(lit == 1L) {
6824                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6825                 } else {
6826                     pic16_emitcode("clr","c");
6827                 }
6828                 /* AOP_TYPE(right) == AOP_CRY */
6829             } else {
6830                 symbol *lbl = newiTempLabel(NULL);
6831                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6832                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6833                 pic16_emitcode("cpl","c");
6834                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6835             }
6836             /* if true label then we jump if condition
6837             supplied is true */
6838             tlbl = newiTempLabel(NULL);
6839             if ( IC_TRUE(ifx) ) {
6840                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6841                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6842             } else {
6843                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6844                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6845             }
6846             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6847
6848                 {
6849                 /* left and right are both bit variables, result is carry */
6850                         resolvedIfx rIfx;
6851               
6852                         resolveIfx(&rIfx,ifx);
6853
6854                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6855                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6856                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6857                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6858                         genSkipz2(&rIfx,0);
6859                 }
6860         } else {
6861
6862                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6863
6864                         /* They're not both bit variables. Is the right a literal? */
6865                         if(AOP_TYPE(right) == AOP_LIT) {
6866                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6867             
6868                         switch(size) {
6869
6870                                 case 1:
6871                                         switch(lit & 0xff) {
6872                                                 case 1:
6873                                                                 if ( IC_TRUE(ifx) ) {
6874                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6875                                                                         emitSKPNZ;
6876                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6877                                                                 } else {
6878                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6879                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6880                                                                 }
6881                                                                 break;
6882                                                 case 0xff:
6883                                                                 if ( IC_TRUE(ifx) ) {
6884                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6885                                                                         emitSKPNZ;
6886                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6887                                                                 } else {
6888                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6889                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6890                                                                 }
6891                                                                 break;
6892                                                 default:
6893                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6894                                                                 if(lit)
6895                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6896                                                                 genSkip(ifx,'z');
6897                                         } // switch lit
6898
6899
6900                                         /* end of size == 1 */
6901                                         break;
6902               
6903                                 case 2:
6904                                         genc16bit2lit(left,lit,offset);
6905                                         genSkip(ifx,'z');
6906                                         break;
6907                                         /* end of size == 2 */
6908
6909                                 default:
6910                                         /* size is 4 */
6911                                         if(lit==0) {
6912                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6913                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6914                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6915                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6916                                                 genSkip(ifx,'z');
6917                                         } else {
6918                                                 /* search for patterns that can be optimized */
6919
6920                                                 genc16bit2lit(left,lit,0);
6921                                                 lit >>= 16;
6922                                                 if(lit) {
6923                                                                 if(IC_TRUE(ifx))
6924                                                                 emitSKPZ; // if hi word unequal
6925                                                                 else
6926                                                                 emitSKPNZ; // if hi word equal
6927                                                                 // fail early
6928                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6929                                                         genc16bit2lit(left,lit,2);
6930                                                         genSkip(ifx,'z');
6931                                                 } else {
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                                                 }
6936                                         }
6937                                                 pic16_emitpLabel(falselbl->key);
6938                                                 break;
6939
6940                         } // switch size
6941           
6942                         ifx->generated = 1;
6943                         goto release ;
6944             
6945
6946           } else if(AOP_TYPE(right) == AOP_CRY ) {
6947             /* we know the left is not a bit, but that the right is */
6948             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6949             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6950                       pic16_popGet(AOP(right),offset));
6951             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6952
6953             /* if the two are equal, then W will be 0 and the Z bit is set
6954              * we could test Z now, or go ahead and check the high order bytes if
6955              * the variable we're comparing is larger than a byte. */
6956
6957             while(--size)
6958               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6959
6960             if ( IC_TRUE(ifx) ) {
6961               emitSKPNZ;
6962               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6963               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6964             } else {
6965               emitSKPZ;
6966               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6967               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6968             }
6969
6970           } else {
6971             /* They're both variables that are larger than bits */
6972             int s = size;
6973
6974             tlbl = newiTempLabel(NULL);
6975
6976             while(size--) {
6977               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6978               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6979
6980               if ( IC_TRUE(ifx) ) {
6981                 if(size) {
6982                   emitSKPZ;
6983                 
6984                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6985
6986                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6987                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6988                 } else {
6989                   emitSKPNZ;
6990
6991                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6992
6993
6994                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6995                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6996                 }
6997               } else {
6998                 emitSKPZ;
6999
7000                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7001
7002                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7003                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7004               }
7005               offset++;
7006             }
7007             if(s>1 && IC_TRUE(ifx)) {
7008               pic16_emitpLabel(tlbl->key);
7009               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7010             }
7011           }
7012         }
7013         /* mark the icode as generated */
7014         ifx->generated = 1;
7015         goto release ;
7016     }
7017
7018     /* if they are both bit variables */
7019     if (AOP_TYPE(left) == AOP_CRY &&
7020         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7021         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7022         if(AOP_TYPE(right) == AOP_LIT){
7023             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7024             if(lit == 0L){
7025                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7026                 pic16_emitcode("cpl","c");
7027             } else if(lit == 1L) {
7028                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7029             } else {
7030                 pic16_emitcode("clr","c");
7031             }
7032             /* AOP_TYPE(right) == AOP_CRY */
7033         } else {
7034             symbol *lbl = newiTempLabel(NULL);
7035             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7036             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7037             pic16_emitcode("cpl","c");
7038             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7039         }
7040         /* c = 1 if egal */
7041         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7042             pic16_outBitC(result);
7043             goto release ;
7044         }
7045         if (ifx) {
7046             genIfxJump (ifx,"c");
7047             goto release ;
7048         }
7049         /* if the result is used in an arithmetic operation
7050         then put the result in place */
7051         pic16_outBitC(result);
7052     } else {
7053       
7054       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7055       gencjne(left,right,result,ifx);
7056 /*
7057       if(ifx) 
7058         gencjne(left,right,newiTempLabel(NULL));
7059       else {
7060         if(IC_TRUE(ifx)->key)
7061           gencjne(left,right,IC_TRUE(ifx)->key);
7062         else
7063           gencjne(left,right,IC_FALSE(ifx)->key);
7064         ifx->generated = 1;
7065         goto release ;
7066       }
7067       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7068         pic16_aopPut(AOP(result),"a",0);
7069         goto release ;
7070       }
7071
7072       if (ifx) {
7073         genIfxJump (ifx,"a");
7074         goto release ;
7075       }
7076 */
7077       /* if the result is used in an arithmetic operation
7078          then put the result in place */
7079 /*
7080       if (AOP_TYPE(result) != AOP_CRY) 
7081         pic16_outAcc(result);
7082 */
7083       /* leave the result in acc */
7084     }
7085
7086 release:
7087     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7088     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7089     pic16_freeAsmop(result,NULL,ic,TRUE);
7090 }
7091 #endif
7092
7093 /*-----------------------------------------------------------------*/
7094 /* ifxForOp - returns the icode containing the ifx for operand     */
7095 /*-----------------------------------------------------------------*/
7096 static iCode *ifxForOp ( operand *op, iCode *ic )
7097 {
7098   FENTRY2;
7099
7100     /* if true symbol then needs to be assigned */
7101     if (IS_TRUE_SYMOP(op))
7102         return NULL ;
7103
7104     /* if this has register type condition and
7105     the next instruction is ifx with the same operand
7106     and live to of the operand is upto the ifx only then */
7107     if (ic->next
7108         && ic->next->op == IFX
7109         && IC_COND(ic->next)->key == op->key
7110         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7111         ) {
7112                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7113           return ic->next;
7114     }
7115
7116     /*
7117     if (ic->next &&
7118         ic->next->op == IFX &&
7119         IC_COND(ic->next)->key == op->key) {
7120       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7121       return ic->next;
7122     }
7123     */
7124
7125     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7126     if (ic->next &&
7127         ic->next->op == IFX)
7128       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7129
7130     if (ic->next &&
7131         ic->next->op == IFX &&
7132         IC_COND(ic->next)->key == op->key) {
7133       DEBUGpic16_emitcode ("; "," key is okay");
7134       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7135                            OP_SYMBOL(op)->liveTo,
7136                            ic->next->seq);
7137     }
7138
7139 #if 0
7140     /* the code below is completely untested
7141      * it just allows ulong2fs.c compile -- VR */
7142          
7143     ic = ic->next;
7144     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7145                                         __FILE__, __FUNCTION__, __LINE__);
7146         
7147     /* if this has register type condition and
7148     the next instruction is ifx with the same operand
7149     and live to of the operand is upto the ifx only then */
7150     if (ic->next &&
7151         ic->next->op == IFX &&
7152         IC_COND(ic->next)->key == op->key &&
7153         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7154         return ic->next;
7155
7156     if (ic->next &&
7157         ic->next->op == IFX &&
7158         IC_COND(ic->next)->key == op->key) {
7159       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7160       return ic->next;
7161     }
7162
7163     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7164                                         __FILE__, __FUNCTION__, __LINE__);
7165
7166 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7167 #endif
7168
7169     return NULL;
7170 }
7171 /*-----------------------------------------------------------------*/
7172 /* genAndOp - for && operation                                     */
7173 /*-----------------------------------------------------------------*/
7174 static void genAndOp (iCode *ic)
7175 {
7176   operand *left,*right, *result;
7177 /*     symbol *tlbl; */
7178
7179     FENTRY;
7180
7181     /* note here that && operations that are in an
7182     if statement are taken away by backPatchLabels
7183     only those used in arthmetic operations remain */
7184     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7185     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7186     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7187
7188     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7189
7190     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7191     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7192     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7193
7194     /* if both are bit variables */
7195 /*     if (AOP_TYPE(left) == AOP_CRY && */
7196 /*         AOP_TYPE(right) == AOP_CRY ) { */
7197 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7198 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7199 /*         pic16_outBitC(result); */
7200 /*     } else { */
7201 /*         tlbl = newiTempLabel(NULL); */
7202 /*         pic16_toBoolean(left);     */
7203 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7204 /*         pic16_toBoolean(right); */
7205 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7206 /*         pic16_outBitAcc(result); */
7207 /*     } */
7208
7209     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7210     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7211     pic16_freeAsmop(result,NULL,ic,TRUE);
7212 }
7213
7214
7215 /*-----------------------------------------------------------------*/
7216 /* genOrOp - for || operation                                      */
7217 /*-----------------------------------------------------------------*/
7218 /*
7219   tsd pic port -
7220   modified this code, but it doesn't appear to ever get called
7221 */
7222
7223 static void genOrOp (iCode *ic)
7224 {
7225   operand *left,*right, *result;
7226   symbol *tlbl;
7227
7228     FENTRY;  
7229
7230   /* note here that || operations that are in an
7231     if statement are taken away by backPatchLabels
7232     only those used in arthmetic operations remain */
7233     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7234     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7235     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7236
7237     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7238
7239     /* if both are bit variables */
7240     if (AOP_TYPE(left) == AOP_CRY &&
7241         AOP_TYPE(right) == AOP_CRY ) {
7242       pic16_emitcode("clrc","");
7243       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7244                AOP(left)->aopu.aop_dir,
7245                AOP(left)->aopu.aop_dir);
7246       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7247                AOP(right)->aopu.aop_dir,
7248                AOP(right)->aopu.aop_dir);
7249       pic16_emitcode("setc","");
7250
7251     } else {
7252         tlbl = newiTempLabel(NULL);
7253         pic16_toBoolean(left);
7254         emitSKPZ;
7255         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7256         pic16_toBoolean(right);
7257         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7258
7259         pic16_outBitAcc(result);
7260     }
7261
7262     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7263     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7264     pic16_freeAsmop(result,NULL,ic,TRUE);            
7265 }
7266
7267 /*-----------------------------------------------------------------*/
7268 /* isLiteralBit - test if lit == 2^n                               */
7269 /*-----------------------------------------------------------------*/
7270 static int isLiteralBit(unsigned long lit)
7271 {
7272     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7273     0x100L,0x200L,0x400L,0x800L,
7274     0x1000L,0x2000L,0x4000L,0x8000L,
7275     0x10000L,0x20000L,0x40000L,0x80000L,
7276     0x100000L,0x200000L,0x400000L,0x800000L,
7277     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7278     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7279     int idx;
7280     
7281     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7282     for(idx = 0; idx < 32; idx++)
7283         if(lit == pw[idx])
7284             return idx+1;
7285     return 0;
7286 }
7287
7288 /*-----------------------------------------------------------------*/
7289 /* continueIfTrue -                                                */
7290 /*-----------------------------------------------------------------*/
7291 static void continueIfTrue (iCode *ic)
7292 {
7293   FENTRY;
7294   if(IC_TRUE(ic))
7295     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7296   ic->generated = 1;
7297 }
7298
7299 /*-----------------------------------------------------------------*/
7300 /* jmpIfTrue -                                                     */
7301 /*-----------------------------------------------------------------*/
7302 static void jumpIfTrue (iCode *ic)
7303 {
7304   FENTRY;
7305   if(!IC_TRUE(ic))
7306     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7307   ic->generated = 1;
7308 }
7309
7310 /*-----------------------------------------------------------------*/
7311 /* jmpTrueOrFalse -                                                */
7312 /*-----------------------------------------------------------------*/
7313 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7314 {
7315   // ugly but optimized by peephole
7316   FENTRY;
7317   if(IC_TRUE(ic)){
7318     symbol *nlbl = newiTempLabel(NULL);
7319       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7320       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7321       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7322       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7323   } else {
7324     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7325     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7326   }
7327   ic->generated = 1;
7328 }
7329
7330 /*-----------------------------------------------------------------*/
7331 /* genAnd  - code for and                                          */
7332 /*-----------------------------------------------------------------*/
7333 static void genAnd (iCode *ic, iCode *ifx)
7334 {
7335   operand *left, *right, *result;
7336   int size, offset=0;  
7337   unsigned long lit = 0L;
7338   int bytelit = 0;
7339   resolvedIfx rIfx;
7340
7341     FENTRY;
7342     
7343   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7344   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7345   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7346
7347   resolveIfx(&rIfx,ifx);
7348
7349   /* if left is a literal & right is not then exchange them */
7350   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7351       AOP_NEEDSACC(left)) {
7352     operand *tmp = right ;
7353     right = left;
7354     left = tmp;
7355   }
7356
7357   /* if result = right then exchange them */
7358   if(pic16_sameRegs(AOP(result),AOP(right))){
7359     operand *tmp = right ;
7360     right = left;
7361     left = tmp;
7362   }
7363
7364   /* if right is bit then exchange them */
7365   if (AOP_TYPE(right) == AOP_CRY &&
7366       AOP_TYPE(left) != AOP_CRY){
7367     operand *tmp = right ;
7368     right = left;
7369     left = tmp;
7370   }
7371   if(AOP_TYPE(right) == AOP_LIT)
7372     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7373
7374   size = AOP_SIZE(result);
7375
7376   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7377
7378   // if(bit & yy)
7379   // result = bit & yy;
7380   if (AOP_TYPE(left) == AOP_CRY){
7381     // c = bit & literal;
7382     if(AOP_TYPE(right) == AOP_LIT){
7383       if(lit & 1) {
7384         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7385           // no change
7386           goto release;
7387         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7388       } else {
7389         // bit(result) = 0;
7390         if(size && (AOP_TYPE(result) == AOP_CRY)){
7391           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7392           goto release;
7393         }
7394         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7395           jumpIfTrue(ifx);
7396           goto release;
7397         }
7398         pic16_emitcode("clr","c");
7399       }
7400     } else {
7401       if (AOP_TYPE(right) == AOP_CRY){
7402         // c = bit & bit;
7403         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7404         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7405       } else {
7406         // c = bit & val;
7407         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7408         // c = lsb
7409         pic16_emitcode("rrc","a");
7410         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7411       }
7412     }
7413     // bit = c
7414     // val = c
7415     if(size)
7416       pic16_outBitC(result);
7417     // if(bit & ...)
7418     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7419       genIfxJump(ifx, "c");           
7420     goto release ;
7421   }
7422
7423   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7424   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7425   if((AOP_TYPE(right) == AOP_LIT) &&
7426      (AOP_TYPE(result) == AOP_CRY) &&
7427      (AOP_TYPE(left) != AOP_CRY)){
7428     int posbit = isLiteralBit(lit);
7429     /* left &  2^n */
7430     if(posbit){
7431       posbit--;
7432       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7433       // bit = left & 2^n
7434       if(size)
7435         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7436       // if(left &  2^n)
7437       else{
7438         if(ifx){
7439 /*
7440           if(IC_TRUE(ifx)) {
7441             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7442             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7443           } else {
7444             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7445             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7446           }
7447 */
7448         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7449         size = AOP_SIZE(left);
7450
7451         {
7452           int bp = posbit, ofs=0;
7453           
7454             while(bp > 7) {
7455               bp -= 8;
7456               ofs++;
7457             }
7458
7459           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7460                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7461
7462         }
7463 /*
7464           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7465                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7466 */
7467           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7468           
7469           ifx->generated = 1;
7470         }
7471         goto release;
7472       }
7473     } else {
7474       symbol *tlbl = newiTempLabel(NULL);
7475       int sizel = AOP_SIZE(left);
7476
7477       if(size)
7478         emitSETC;
7479
7480       while(sizel--) {
7481         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7482
7483           /* patch provided by Aaron Colwell */
7484           if((posbit = isLiteralBit(bytelit)) != 0) {
7485               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7486                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7487                                                 (posbit-1),0, PO_GPR_REGISTER));
7488
7489               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7490 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7491           } else {
7492               if (bytelit == 0xff) {
7493                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7494                    * a peephole could optimize it out -- VR */
7495                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7496               } else {
7497                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7498                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7499               }
7500
7501               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7502                             pic16_popGetLabel(tlbl->key));
7503           }
7504         
7505 #if 0
7506           /* old code, left here for reference -- VR 09/2004 */
7507           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7508           // byte ==  2^n ?
7509           if((posbit = isLiteralBit(bytelit)) != 0)
7510             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7511           else{
7512             if(bytelit != 0x0FFL)
7513               pic16_emitcode("anl","a,%s",
7514                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7515             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7516           }
7517 #endif
7518         }
7519         offset++;
7520       }
7521       // bit = left & literal
7522       if(size) {
7523         emitCLRC;
7524         pic16_emitpLabel(tlbl->key);
7525       }
7526       // if(left & literal)
7527       else {
7528         if(ifx) {
7529           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7530           ifx->generated = 1;
7531         }
7532         pic16_emitpLabel(tlbl->key);
7533         goto release;
7534       }
7535     }
7536
7537     pic16_outBitC(result);
7538     goto release ;
7539   }
7540
7541   /* if left is same as result */
7542   if(pic16_sameRegs(AOP(result),AOP(left))){
7543     int know_W = -1;
7544     for(;size--; offset++,lit>>=8) {
7545       if(AOP_TYPE(right) == AOP_LIT){
7546         switch(lit & 0xff) {
7547         case 0x00:
7548           /*  and'ing with 0 has clears the result */
7549 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7550           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7551           break;
7552         case 0xff:
7553           /* and'ing with 0xff is a nop when the result and left are the same */
7554           break;
7555
7556         default:
7557           {
7558             int p = pic16_my_powof2( (~lit) & 0xff );
7559             if(p>=0) {
7560               /* only one bit is set in the literal, so use a bcf instruction */
7561 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7562               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7563
7564             } else {
7565               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7566               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7567               if(know_W != (lit&0xff))
7568                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7569               know_W = lit &0xff;
7570               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7571             }
7572           }    
7573         }
7574       } else {
7575         if (AOP_TYPE(left) == AOP_ACC) {
7576           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7577         } else {                    
7578           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7579           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7580
7581         }
7582       }
7583     }
7584
7585   } else {
7586     // left & result in different registers
7587     if(AOP_TYPE(result) == AOP_CRY){
7588       // result = bit
7589       // if(size), result in bit
7590       // if(!size && ifx), conditional oper: if(left & right)
7591       symbol *tlbl = newiTempLabel(NULL);
7592       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7593       if(size)
7594         pic16_emitcode("setb","c");
7595       while(sizer--){
7596         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7597         pic16_emitcode("anl","a,%s",
7598                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7599         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7600         offset++;
7601       }
7602       if(size){
7603         CLRC;
7604         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7605         pic16_outBitC(result);
7606       } else if(ifx)
7607         jmpTrueOrFalse(ifx, tlbl);
7608     } else {
7609       for(;(size--);offset++) {
7610         // normal case
7611         // result = left & right
7612         if(AOP_TYPE(right) == AOP_LIT){
7613           int t = (lit >> (offset*8)) & 0x0FFL;
7614           switch(t) { 
7615           case 0x00:
7616             pic16_emitcode("clrf","%s",
7617                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7618             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7619             break;
7620           case 0xff:
7621             pic16_emitcode("movf","%s,w",
7622                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7623             pic16_emitcode("movwf","%s",
7624                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7625             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7626             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7627             break;
7628           default:
7629             pic16_emitcode("movlw","0x%x",t);
7630             pic16_emitcode("andwf","%s,w",
7631                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7632             pic16_emitcode("movwf","%s",
7633                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7634               
7635             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7636             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7637             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7638           }
7639           continue;
7640         }
7641
7642         if (AOP_TYPE(left) == AOP_ACC) {
7643           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7644           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7645         } else {
7646           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7647           pic16_emitcode("andwf","%s,w",
7648                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7649           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7650           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7651         }
7652         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7653         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7654       }
7655     }
7656   }
7657
7658   release :
7659     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7660   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7661   pic16_freeAsmop(result,NULL,ic,TRUE);     
7662 }
7663
7664 /*-----------------------------------------------------------------*/
7665 /* genOr  - code for or                                            */
7666 /*-----------------------------------------------------------------*/
7667 static void genOr (iCode *ic, iCode *ifx)
7668 {
7669     operand *left, *right, *result;
7670     int size, offset=0;
7671     unsigned long lit = 0L;
7672
7673     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7674
7675     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7676     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7677     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7678
7679     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7680
7681     /* if left is a literal & right is not then exchange them */
7682     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7683         AOP_NEEDSACC(left)) {
7684         operand *tmp = right ;
7685         right = left;
7686         left = tmp;
7687     }
7688
7689     /* if result = right then exchange them */
7690     if(pic16_sameRegs(AOP(result),AOP(right))){
7691         operand *tmp = right ;
7692         right = left;
7693         left = tmp;
7694     }
7695
7696     /* if right is bit then exchange them */
7697     if (AOP_TYPE(right) == AOP_CRY &&
7698         AOP_TYPE(left) != AOP_CRY){
7699         operand *tmp = right ;
7700         right = left;
7701         left = tmp;
7702     }
7703
7704     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7705
7706     if(AOP_TYPE(right) == AOP_LIT)
7707         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7708
7709     size = AOP_SIZE(result);
7710
7711     // if(bit | yy)
7712     // xx = bit | yy;
7713     if (AOP_TYPE(left) == AOP_CRY){
7714         if(AOP_TYPE(right) == AOP_LIT){
7715             // c = bit & literal;
7716             if(lit){
7717                 // lit != 0 => result = 1
7718                 if(AOP_TYPE(result) == AOP_CRY){
7719                   if(size)
7720                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7721                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7722                   //     AOP(result)->aopu.aop_dir,
7723                   //     AOP(result)->aopu.aop_dir);
7724                     else if(ifx)
7725                         continueIfTrue(ifx);
7726                     goto release;
7727                 }
7728             } else {
7729                 // lit == 0 => result = left
7730                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7731                     goto release;
7732                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7733             }
7734         } else {
7735             if (AOP_TYPE(right) == AOP_CRY){
7736               if(pic16_sameRegs(AOP(result),AOP(left))){
7737                 // c = bit | bit;
7738                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7739                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7740                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7741
7742                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7743                          AOP(result)->aopu.aop_dir,
7744                          AOP(result)->aopu.aop_dir);
7745                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7746                          AOP(right)->aopu.aop_dir,
7747                          AOP(right)->aopu.aop_dir);
7748                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7749                          AOP(result)->aopu.aop_dir,
7750                          AOP(result)->aopu.aop_dir);
7751               } else {
7752                 if( AOP_TYPE(result) == AOP_ACC) {
7753                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7754                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7755                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7756                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7757
7758                 } else {
7759
7760                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7761                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7762                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7763                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7764
7765                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7766                                  AOP(result)->aopu.aop_dir,
7767                                  AOP(result)->aopu.aop_dir);
7768                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7769                                  AOP(right)->aopu.aop_dir,
7770                                  AOP(right)->aopu.aop_dir);
7771                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7772                                  AOP(left)->aopu.aop_dir,
7773                                  AOP(left)->aopu.aop_dir);
7774                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7775                                  AOP(result)->aopu.aop_dir,
7776                                  AOP(result)->aopu.aop_dir);
7777                 }
7778               }
7779             } else {
7780                 // c = bit | val;
7781                 symbol *tlbl = newiTempLabel(NULL);
7782                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7783
7784
7785                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7786                 if( AOP_TYPE(right) == AOP_ACC) {
7787                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7788                   emitSKPNZ;
7789                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7790                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7791                 }
7792
7793
7794
7795                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7796                     pic16_emitcode(";XXX setb","c");
7797                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7798                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7799                 pic16_toBoolean(right);
7800                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7801                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7802                     jmpTrueOrFalse(ifx, tlbl);
7803                     goto release;
7804                 } else {
7805                     CLRC;
7806                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7807                 }
7808             }
7809         }
7810         // bit = c
7811         // val = c
7812         if(size)
7813             pic16_outBitC(result);
7814         // if(bit | ...)
7815         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7816             genIfxJump(ifx, "c");           
7817         goto release ;
7818     }
7819
7820     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7821     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7822     if((AOP_TYPE(right) == AOP_LIT) &&
7823        (AOP_TYPE(result) == AOP_CRY) &&
7824        (AOP_TYPE(left) != AOP_CRY)){
7825         if(lit){
7826           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7827             // result = 1
7828             if(size)
7829                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7830             else 
7831                 continueIfTrue(ifx);
7832             goto release;
7833         } else {
7834           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7835             // lit = 0, result = boolean(left)
7836             if(size)
7837                 pic16_emitcode(";XXX setb","c");
7838             pic16_toBoolean(right);
7839             if(size){
7840                 symbol *tlbl = newiTempLabel(NULL);
7841                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7842                 CLRC;
7843                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7844             } else {
7845                 genIfxJump (ifx,"a");
7846                 goto release;
7847             }
7848         }
7849         pic16_outBitC(result);
7850         goto release ;
7851     }
7852
7853     /* if left is same as result */
7854     if(pic16_sameRegs(AOP(result),AOP(left))){
7855       int know_W = -1;
7856       for(;size--; offset++,lit>>=8) {
7857         if(AOP_TYPE(right) == AOP_LIT){
7858           if((lit & 0xff) == 0)
7859             /*  or'ing with 0 has no effect */
7860             continue;
7861           else {
7862             int p = pic16_my_powof2(lit & 0xff);
7863             if(p>=0) {
7864               /* only one bit is set in the literal, so use a bsf instruction */
7865               pic16_emitpcode(POC_BSF,
7866                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7867             } else {
7868               if(know_W != (lit & 0xff))
7869                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7870               know_W = lit & 0xff;
7871               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7872             }
7873                     
7874           }
7875         } else {
7876           if (AOP_TYPE(left) == AOP_ACC) {
7877             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7878 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7879           } else {                  
7880             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7881             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7882
7883 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7884 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7885
7886           }
7887         }
7888       }
7889     } else {
7890         // left & result in different registers
7891         if(AOP_TYPE(result) == AOP_CRY){
7892             // result = bit
7893             // if(size), result in bit
7894             // if(!size && ifx), conditional oper: if(left | right)
7895             symbol *tlbl = newiTempLabel(NULL);
7896             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7897             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7898
7899
7900             if(size)
7901                 pic16_emitcode(";XXX setb","c");
7902             while(sizer--){
7903                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7904                 pic16_emitcode(";XXX orl","a,%s",
7905                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7906                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7907                 offset++;
7908             }
7909             if(size){
7910                 CLRC;
7911                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7912                 pic16_outBitC(result);
7913             } else if(ifx)
7914                 jmpTrueOrFalse(ifx, tlbl);
7915         } else for(;(size--);offset++){
7916           // normal case
7917           // result = left & right
7918           if(AOP_TYPE(right) == AOP_LIT){
7919             int t = (lit >> (offset*8)) & 0x0FFL;
7920             switch(t) { 
7921             case 0x00:
7922               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7923               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7924
7925 //            pic16_emitcode("movf","%s,w",
7926 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7927 //            pic16_emitcode("movwf","%s",
7928 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7929               break;
7930             default:
7931               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7932               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7933               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7934
7935 //            pic16_emitcode("movlw","0x%x",t);
7936 //            pic16_emitcode("iorwf","%s,w",
7937 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7938 //            pic16_emitcode("movwf","%s",
7939 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7940               
7941             }
7942             continue;
7943           }
7944
7945           // faster than result <- left, anl result,right
7946           // and better if result is SFR
7947           if (AOP_TYPE(left) == AOP_ACC) {
7948             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7949 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7950           } else {
7951             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7952             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7953
7954 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7955 //          pic16_emitcode("iorwf","%s,w",
7956 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7957           }
7958           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7959 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7960         }
7961     }
7962
7963 release :
7964     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7965     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7966     pic16_freeAsmop(result,NULL,ic,TRUE);     
7967 }
7968
7969 /*-----------------------------------------------------------------*/
7970 /* genXor - code for xclusive or                                   */
7971 /*-----------------------------------------------------------------*/
7972 static void genXor (iCode *ic, iCode *ifx)
7973 {
7974   operand *left, *right, *result;
7975   int size, offset=0;
7976   unsigned long lit = 0L;
7977
7978   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7979
7980   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7981   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7982   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7983
7984   /* if left is a literal & right is not ||
7985      if left needs acc & right does not */
7986   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7987       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7988     operand *tmp = right ;
7989     right = left;
7990     left = tmp;
7991   }
7992
7993   /* if result = right then exchange them */
7994   if(pic16_sameRegs(AOP(result),AOP(right))){
7995     operand *tmp = right ;
7996     right = left;
7997     left = tmp;
7998   }
7999
8000   /* if right is bit then exchange them */
8001   if (AOP_TYPE(right) == AOP_CRY &&
8002       AOP_TYPE(left) != AOP_CRY){
8003     operand *tmp = right ;
8004     right = left;
8005     left = tmp;
8006   }
8007   if(AOP_TYPE(right) == AOP_LIT)
8008     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8009
8010   size = AOP_SIZE(result);
8011
8012   // if(bit ^ yy)
8013   // xx = bit ^ yy;
8014   if (AOP_TYPE(left) == AOP_CRY){
8015     if(AOP_TYPE(right) == AOP_LIT){
8016       // c = bit & literal;
8017       if(lit>>1){
8018         // lit>>1  != 0 => result = 1
8019         if(AOP_TYPE(result) == AOP_CRY){
8020           if(size)
8021             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8022             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8023           else if(ifx)
8024             continueIfTrue(ifx);
8025           goto release;
8026         }
8027         pic16_emitcode("setb","c");
8028       } else{
8029         // lit == (0 or 1)
8030         if(lit == 0){
8031           // lit == 0, result = left
8032           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8033             goto release;
8034           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8035         } else{
8036           // lit == 1, result = not(left)
8037           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8038             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8039             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8040             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8041             goto release;
8042           } else {
8043             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8044             pic16_emitcode("cpl","c");
8045           }
8046         }
8047       }
8048
8049     } else {
8050       // right != literal
8051       symbol *tlbl = newiTempLabel(NULL);
8052       if (AOP_TYPE(right) == AOP_CRY){
8053         // c = bit ^ bit;
8054         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8055       }
8056       else{
8057         int sizer = AOP_SIZE(right);
8058         // c = bit ^ val
8059         // if val>>1 != 0, result = 1
8060         pic16_emitcode("setb","c");
8061         while(sizer){
8062           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8063           if(sizer == 1)
8064             // test the msb of the lsb
8065             pic16_emitcode("anl","a,#0xfe");
8066           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8067           sizer--;
8068         }
8069         // val = (0,1)
8070         pic16_emitcode("rrc","a");
8071       }
8072       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8073       pic16_emitcode("cpl","c");
8074       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8075     }
8076     // bit = c
8077     // val = c
8078     if(size)
8079       pic16_outBitC(result);
8080     // if(bit | ...)
8081     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8082       genIfxJump(ifx, "c");           
8083     goto release ;
8084   }
8085
8086   if(pic16_sameRegs(AOP(result),AOP(left))){
8087     /* if left is same as result */
8088     for(;size--; offset++) {
8089       if(AOP_TYPE(right) == AOP_LIT){
8090         int t  = (lit >> (offset*8)) & 0x0FFL;
8091         if(t == 0x00L)
8092           continue;
8093         else
8094           if (IS_AOP_PREG(left)) {
8095             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8096             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8097             pic16_aopPut(AOP(result),"a",offset);
8098           } else {
8099             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8100             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8101             pic16_emitcode("xrl","%s,%s",
8102                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8103                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8104           }
8105       } else {
8106         if (AOP_TYPE(left) == AOP_ACC)
8107           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8108         else {
8109           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8110           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8111 /*
8112           if (IS_AOP_PREG(left)) {
8113             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8114             pic16_aopPut(AOP(result),"a",offset);
8115           } else
8116             pic16_emitcode("xrl","%s,a",
8117                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8118 */
8119         }
8120       }
8121     }
8122   } else {
8123     // left & result in different registers
8124     if(AOP_TYPE(result) == AOP_CRY){
8125       // result = bit
8126       // if(size), result in bit
8127       // if(!size && ifx), conditional oper: if(left ^ right)
8128       symbol *tlbl = newiTempLabel(NULL);
8129       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8130       if(size)
8131         pic16_emitcode("setb","c");
8132       while(sizer--){
8133         if((AOP_TYPE(right) == AOP_LIT) &&
8134            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8135           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8136         } else {
8137           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8138           pic16_emitcode("xrl","a,%s",
8139                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8140         }
8141         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8142         offset++;
8143       }
8144       if(size){
8145         CLRC;
8146         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8147         pic16_outBitC(result);
8148       } else if(ifx)
8149         jmpTrueOrFalse(ifx, tlbl);
8150     } else for(;(size--);offset++){
8151       // normal case
8152       // result = left & right
8153       if(AOP_TYPE(right) == AOP_LIT){
8154         int t = (lit >> (offset*8)) & 0x0FFL;
8155         switch(t) { 
8156         case 0x00:
8157           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8158           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8159           pic16_emitcode("movf","%s,w",
8160                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8161           pic16_emitcode("movwf","%s",
8162                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8163           break;
8164         case 0xff:
8165           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8166           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8167           pic16_emitcode("comf","%s,w",
8168                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8169           pic16_emitcode("movwf","%s",
8170                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8171           break;
8172         default:
8173           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8174           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8175           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8176           pic16_emitcode("movlw","0x%x",t);
8177           pic16_emitcode("xorwf","%s,w",
8178                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179           pic16_emitcode("movwf","%s",
8180                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8181
8182         }
8183         continue;
8184       }
8185
8186       // faster than result <- left, anl result,right
8187       // and better if result is SFR
8188       if (AOP_TYPE(left) == AOP_ACC) {
8189         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8190         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8191       } else {
8192         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8193         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8194         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8195         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8196       }
8197       if ( AOP_TYPE(result) != AOP_ACC){
8198         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8199         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8200       }
8201     }
8202   }
8203
8204   release :
8205     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8206   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8207   pic16_freeAsmop(result,NULL,ic,TRUE);     
8208 }
8209
8210 /*-----------------------------------------------------------------*/
8211 /* genInline - write the inline code out                           */
8212 /*-----------------------------------------------------------------*/
8213 static void genInline (iCode *ic)
8214 {
8215   char *buffer, *bp, *bp1;
8216     
8217         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8218
8219         _G.inLine += (!options.asmpeep);
8220
8221         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8222         strcpy(buffer,IC_INLINE(ic));
8223         
8224         while((bp1=strstr(bp, "\\n"))) {
8225           *bp1++ = '\n';
8226           *bp1++ = ' ';
8227           bp = bp1;
8228         }
8229         bp = bp1 = buffer;
8230
8231 #if 0
8232   /* This is an experimental code for #pragma inline
8233      and is temporarily disabled for 2.5.0 release */
8234         if(asmInlineMap)
8235         {
8236           symbol *sym;
8237           char *s;
8238           char *cbuf;
8239           int cblen;
8240
8241             cbuf = Safe_strdup(buffer);
8242             cblen = strlen(buffer)+1;
8243             memset(cbuf, 0, cblen);
8244
8245             bp = buffer;
8246             bp1 = cbuf;
8247             while(*bp) {
8248               if(*bp != '%')*bp1++ = *bp++;
8249               else {
8250                 int i;
8251
8252                   bp++;
8253                   i = *bp - '0';
8254                   if(i>elementsInSet(asmInlineMap))break;
8255                   
8256                   bp++;
8257                   s = indexSet(asmInlineMap, i);
8258                   DEBUGpc("searching symbol s = `%s'", s);
8259                   sym = findSym(SymbolTab, NULL, s);
8260
8261                   if(sym->reqv) {
8262                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8263                   } else {
8264                     strcat(bp1, sym->rname);
8265                   }
8266                   
8267                   while(*bp1)bp1++;
8268               }
8269               
8270               if(strlen(bp1) > cblen - 16) {
8271                 int i = strlen(cbuf);
8272                 cblen += 50;
8273                 cbuf = realloc(cbuf, cblen);
8274                 memset(cbuf+i, 0, 50);
8275                 bp1 = cbuf + i;
8276               }
8277             }
8278             
8279             free(buffer);
8280             buffer = Safe_strdup( cbuf );
8281             free(cbuf);
8282             
8283             bp = bp1 = buffer;
8284         }
8285 #endif  /* 0 */
8286
8287         /* emit each line as a code */
8288         while (*bp) {
8289                 if (*bp == '\n') {
8290                         *bp++ = '\0';
8291
8292                         if(*bp1)
8293                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8294                         bp1 = bp;
8295                 } else {
8296                         if (*bp == ':') {
8297                                 bp++;
8298                                 *bp = '\0';
8299                                 bp++;
8300
8301                                 /* print label, use this special format with NULL directive
8302                                  * to denote that the argument should not be indented with tab */
8303                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8304                                 bp1 = bp;
8305                         } if (*bp == ';') {
8306                                 /* advance to end of line (prevent splitting of comments at ':' */
8307                                 while (*bp && *bp != '\n') {
8308                                         bp++;
8309                                 } // while
8310                         } else
8311                                 bp++;
8312                 }
8313         }
8314
8315         if ((bp1 != bp) && *bp1)
8316                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8317
8318
8319     Safe_free(buffer);
8320
8321     _G.inLine -= (!options.asmpeep);
8322 }
8323
8324 /*-----------------------------------------------------------------*/
8325 /* genRRC - rotate right with carry                                */
8326 /*-----------------------------------------------------------------*/
8327 static void genRRC (iCode *ic)
8328 {
8329   operand *left , *result ;
8330   int size, offset = 0, same;
8331
8332   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8333
8334   /* rotate right with carry */
8335   left = IC_LEFT(ic);
8336   result=IC_RESULT(ic);
8337   pic16_aopOp (left,ic,FALSE);
8338   pic16_aopOp (result,ic,TRUE);
8339
8340   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8341
8342   same = pic16_sameRegs(AOP(result),AOP(left));
8343
8344   size = AOP_SIZE(result);    
8345
8346   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8347
8348   /* get the lsb and put it into the carry */
8349   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8350
8351   offset = 0 ;
8352
8353   while(size--) {
8354
8355     if(same) {
8356       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8357     } else {
8358       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8359       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8360     }
8361
8362     offset++;
8363   }
8364
8365   pic16_freeAsmop(left,NULL,ic,TRUE);
8366   pic16_freeAsmop(result,NULL,ic,TRUE);
8367 }
8368
8369 /*-----------------------------------------------------------------*/
8370 /* genRLC - generate code for rotate left with carry               */
8371 /*-----------------------------------------------------------------*/
8372 static void genRLC (iCode *ic)
8373 {    
8374   operand *left , *result ;
8375   int size, offset = 0;
8376   int same;
8377
8378   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8379   /* rotate right with carry */
8380   left = IC_LEFT(ic);
8381   result=IC_RESULT(ic);
8382   pic16_aopOp (left,ic,FALSE);
8383   pic16_aopOp (result,ic,TRUE);
8384
8385   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8386
8387   same = pic16_sameRegs(AOP(result),AOP(left));
8388
8389   /* move it to the result */
8390   size = AOP_SIZE(result);    
8391
8392   /* get the msb and put it into the carry */
8393   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8394
8395   offset = 0 ;
8396
8397   while(size--) {
8398
8399     if(same) {
8400       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8401     } else {
8402       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8403       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8404     }
8405
8406     offset++;
8407   }
8408
8409
8410   pic16_freeAsmop(left,NULL,ic,TRUE);
8411   pic16_freeAsmop(result,NULL,ic,TRUE);
8412 }
8413
8414
8415 /* gpasm can get the highest order bit with HIGH/UPPER
8416  * so the following probably is not needed -- VR */
8417  
8418 /*-----------------------------------------------------------------*/
8419 /* genGetHbit - generates code get highest order bit               */
8420 /*-----------------------------------------------------------------*/
8421 static void genGetHbit (iCode *ic)
8422 {
8423     operand *left, *result;
8424     left = IC_LEFT(ic);
8425     result=IC_RESULT(ic);
8426     pic16_aopOp (left,ic,FALSE);
8427     pic16_aopOp (result,ic,FALSE);
8428
8429     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8430     /* get the highest order byte into a */
8431     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8432     if(AOP_TYPE(result) == AOP_CRY){
8433         pic16_emitcode("rlc","a");
8434         pic16_outBitC(result);
8435     }
8436     else{
8437         pic16_emitcode("rl","a");
8438         pic16_emitcode("anl","a,#0x01");
8439         pic16_outAcc(result);
8440     }
8441
8442
8443     pic16_freeAsmop(left,NULL,ic,TRUE);
8444     pic16_freeAsmop(result,NULL,ic,TRUE);
8445 }
8446
8447 #if 0
8448 /*-----------------------------------------------------------------*/
8449 /* AccRol - rotate left accumulator by known count                 */
8450 /*-----------------------------------------------------------------*/
8451 static void AccRol (int shCount)
8452 {
8453     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8454     shCount &= 0x0007;              // shCount : 0..7
8455     switch(shCount){
8456         case 0 :
8457             break;
8458         case 1 :
8459             pic16_emitcode("rl","a");
8460             break;
8461         case 2 :
8462             pic16_emitcode("rl","a");
8463             pic16_emitcode("rl","a");
8464             break;
8465         case 3 :
8466             pic16_emitcode("swap","a");
8467             pic16_emitcode("rr","a");
8468             break;
8469         case 4 :
8470             pic16_emitcode("swap","a");
8471             break;
8472         case 5 :
8473             pic16_emitcode("swap","a");
8474             pic16_emitcode("rl","a");
8475             break;
8476         case 6 :
8477             pic16_emitcode("rr","a");
8478             pic16_emitcode("rr","a");
8479             break;
8480         case 7 :
8481             pic16_emitcode("rr","a");
8482             break;
8483     }
8484 }
8485 #endif
8486
8487 /*-----------------------------------------------------------------*/
8488 /* AccLsh - left shift accumulator by known count                  */
8489 /*-----------------------------------------------------------------*/
8490 static void AccLsh (int shCount, int doMask)
8491 {
8492         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8493         switch(shCount){
8494                 case 0 :
8495                         return;
8496                         break;
8497                 case 1 :
8498                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8499                         break;
8500                 case 2 :
8501                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8502                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8503                         break;
8504                 case 3 :
8505                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8506                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8507                         break;
8508                 case 4 :
8509                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8510                         break;
8511                 case 5 :
8512                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8513                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8514                         break;
8515                 case 6 :
8516                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8517                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8518                         break;
8519                 case 7 :
8520                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8521                         break;
8522         }
8523         if (doMask) {
8524                 /* no masking is required in genPackBits */
8525                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8526         }
8527 }
8528
8529 /*-----------------------------------------------------------------*/
8530 /* AccRsh - right shift accumulator by known count                 */
8531 /*-----------------------------------------------------------------*/
8532 static void AccRsh (int shCount, int andmask)
8533 {
8534         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8535         switch(shCount){
8536                 case 0 :
8537                         return; break;
8538                 case 1 :
8539                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8540                         break;
8541                 case 2 :
8542                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8543                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8544                         break;
8545                 case 3 :
8546                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8547                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8548                         break;
8549                 case 4 :
8550                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8551                         break;
8552                 case 5 :
8553                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8554                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8555                         break;
8556                 case 6 :
8557                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8558                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8559                         break;
8560                 case 7 :
8561                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8562                         break;
8563         }
8564         
8565         if(andmask)
8566                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8567         else
8568                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8569 }
8570
8571 #if 0
8572 /*-----------------------------------------------------------------*/
8573 /* AccSRsh - signed right shift accumulator by known count                 */
8574 /*-----------------------------------------------------------------*/
8575 static void AccSRsh (int shCount)
8576 {
8577     symbol *tlbl ;
8578     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8579     if(shCount != 0){
8580         if(shCount == 1){
8581             pic16_emitcode("mov","c,acc.7");
8582             pic16_emitcode("rrc","a");
8583         } else if(shCount == 2){
8584             pic16_emitcode("mov","c,acc.7");
8585             pic16_emitcode("rrc","a");
8586             pic16_emitcode("mov","c,acc.7");
8587             pic16_emitcode("rrc","a");
8588         } else {
8589             tlbl = newiTempLabel(NULL);
8590             /* rotate right accumulator */
8591             AccRol(8 - shCount);
8592             /* and kill the higher order bits */
8593             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8594             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8595             pic16_emitcode("orl","a,#0x%02x",
8596                      (unsigned char)~SRMask[shCount]);
8597             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8598         }
8599     }
8600 }
8601 #endif
8602
8603 /*-----------------------------------------------------------------*/
8604 /* shiftR1Left2Result - shift right one byte from left to result   */
8605 /*-----------------------------------------------------------------*/
8606 static void shiftR1Left2ResultSigned (operand *left, int offl,
8607                                 operand *result, int offr,
8608                                 int shCount)
8609 {
8610   int same;
8611
8612   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8613
8614   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8615
8616   switch(shCount) {
8617   case 1:
8618     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8619     if(same) 
8620       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8621     else {
8622       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8623       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8624     }
8625
8626     break;
8627   case 2:
8628
8629     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8630     if(same) 
8631       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8632     else {
8633       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8634       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8635     }
8636     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8637     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8638
8639     break;
8640
8641   case 3:
8642     if(same)
8643       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8644     else {
8645       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8646       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8647     }
8648
8649     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8650     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8651     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8652
8653     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8654     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8655
8656     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8657     break;
8658
8659   case 4:
8660     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8661     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8662     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8663     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8664     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8665     break;
8666   case 5:
8667     if(same) {
8668       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8669     } else {
8670       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8671       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8672     }
8673     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8674     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8675     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8676     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8677     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8678     break;
8679
8680   case 6:
8681     if(same) {
8682       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8683       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8684       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8685       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8686       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8687       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8688     } else {
8689       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8690       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8691       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8692       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8693       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8694     }
8695     break;
8696
8697   case 7:
8698     if(same) {
8699       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8700       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8701       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8702       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8703     } else {
8704       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8705       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8706       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8707     }
8708
8709   default:
8710     break;
8711   }
8712 }
8713
8714 /*-----------------------------------------------------------------*/
8715 /* shiftR1Left2Result - shift right one byte from left to result   */
8716 /*-----------------------------------------------------------------*/
8717 static void shiftR1Left2Result (operand *left, int offl,
8718                                 operand *result, int offr,
8719                                 int shCount, int sign)
8720 {
8721   int same;
8722
8723   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8724
8725   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8726
8727   /* Copy the msb into the carry if signed. */
8728   if(sign) {
8729     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8730     return;
8731   }
8732
8733
8734
8735   switch(shCount) {
8736   case 1:
8737     emitCLRC;
8738     if(same) 
8739       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8740     else {
8741       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8742       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8743     }
8744     break;
8745   case 2:
8746     emitCLRC;
8747     if(same) {
8748       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8749     } else {
8750       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8751       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8752     }
8753     emitCLRC;
8754     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8755
8756     break;
8757   case 3:
8758     if(same)
8759       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8760     else {
8761       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8762       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8763     }
8764
8765     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8766     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8767     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8768     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8769     break;
8770       
8771   case 4:
8772     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8773     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8774     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8775     break;
8776
8777   case 5:
8778     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8779     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8780     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8781     //emitCLRC;
8782     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8783
8784     break;
8785   case 6:
8786
8787     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8788     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8789     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8790     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8791     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8792     break;
8793
8794   case 7:
8795
8796     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8797     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8798     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8799
8800     break;
8801
8802   default:
8803     break;
8804   }
8805 }
8806
8807 /*-----------------------------------------------------------------*/
8808 /* shiftL1Left2Result - shift left one byte from left to result    */
8809 /*-----------------------------------------------------------------*/
8810 static void shiftL1Left2Result (operand *left, int offl,
8811                                 operand *result, int offr, int shCount)
8812 {
8813   int same;
8814
8815   //    char *l;
8816   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8817
8818   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8819   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8820     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8821     //    MOVA(l);
8822     /* shift left accumulator */
8823     //AccLsh(shCount, 1); // don't comment out just yet...
8824   //    pic16_aopPut(AOP(result),"a",offr);
8825
8826   switch(shCount) {
8827   case 1:
8828     /* Shift left 1 bit position */
8829     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8830     if(same) {
8831       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8832     } else {
8833       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8834       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8835     }
8836     break;
8837   case 2:
8838     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8839     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8840     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8841     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8842     break;
8843   case 3:
8844     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8845     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8846     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8847     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8848     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8849     break;
8850   case 4:
8851     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8852     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8853     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8854     break;
8855   case 5:
8856     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8857     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8858     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8859     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8860     break;
8861   case 6:
8862     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8863     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
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 7:
8869     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8870     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8871     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8872     break;
8873
8874   default:
8875     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8876   }
8877
8878 }
8879
8880 /*-----------------------------------------------------------------*/
8881 /* movLeft2Result - move byte from left to result                  */
8882 /*-----------------------------------------------------------------*/
8883 static void movLeft2Result (operand *left, int offl,
8884                             operand *result, int offr)
8885 {
8886   char *l;
8887   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8888   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8889     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8890
8891     if (*l == '@' && (IS_AOP_PREG(result))) {
8892       pic16_emitcode("mov","a,%s",l);
8893       pic16_aopPut(AOP(result),"a",offr);
8894     } else {
8895       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8896       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8897     }
8898   }
8899 }
8900
8901 /*-----------------------------------------------------------------*/
8902 /* shiftL2Left2Result - shift left two bytes from left to result   */
8903 /*-----------------------------------------------------------------*/
8904 static void shiftL2Left2Result (operand *left, int offl,
8905                                 operand *result, int offr, int shCount)
8906 {
8907   int same = pic16_sameRegs(AOP(result), AOP(left));
8908   int i;
8909
8910   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8911
8912   if (same && (offl != offr)) { // shift bytes
8913     if (offr > offl) {
8914        for(i=1;i>-1;i--) {
8915          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8916          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8917        }
8918     } else { // just treat as different later on
8919                 same = 0;
8920     }
8921   }
8922
8923   if(same) {
8924     switch(shCount) {
8925     case 0:
8926       break;
8927     case 1:
8928     case 2:
8929     case 3:
8930
8931       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8932       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8933       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8934
8935       while(--shCount) {
8936                 emitCLRC;
8937                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8938                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8939       }
8940
8941       break;
8942     case 4:
8943     case 5:
8944       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8945       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8946       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8947       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8948       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8949       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8950       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8951       if(shCount >=5) {
8952                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8953                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8954       }
8955       break;
8956     case 6:
8957       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8958       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8959       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8960       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8961       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8962       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8963       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8964       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8965       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8966       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8967       break;
8968     case 7:
8969       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8970       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8971       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8972       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8973       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8974     }
8975
8976   } else {
8977     switch(shCount) {
8978     case 0:
8979       break;
8980     case 1:
8981     case 2:
8982     case 3:
8983       /* note, use a mov/add for the shift since the mov has a
8984          chance of getting optimized out */
8985       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8986       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8987       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8988       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8989       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8990
8991       while(--shCount) {
8992                 emitCLRC;
8993                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8994                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8995       }
8996       break;
8997
8998     case 4:
8999     case 5:
9000       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9001       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9002       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9003       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9004       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9005       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9006       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9007       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9008
9009
9010       if(shCount == 5) {
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     case 6:
9016       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9017       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9018       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9019       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9020
9021       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9022       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9023       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9024       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9025       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9026       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9027       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9028       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9029       break;
9030     case 7:
9031       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9032       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9033       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9034       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9035       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9036     }
9037   }
9038
9039 }
9040 /*-----------------------------------------------------------------*/
9041 /* shiftR2Left2Result - shift right two bytes from left to result  */
9042 /*-----------------------------------------------------------------*/
9043 static void shiftR2Left2Result (operand *left, int offl,
9044                                 operand *result, int offr,
9045                                 int shCount, int sign)
9046 {
9047   int same = pic16_sameRegs(AOP(result), AOP(left));
9048   int i;
9049   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9050
9051   if (same && (offl != offr)) { // shift right bytes
9052     if (offr < offl) {
9053        for(i=0;i<2;i++) {
9054          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9055          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9056        }
9057     } else { // just treat as different later on
9058                 same = 0;
9059     }
9060   }
9061
9062   switch(shCount) {
9063   case 0:
9064     break;
9065   case 1:
9066   case 2:
9067   case 3:
9068     if(sign)
9069       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9070     else
9071       emitCLRC;
9072
9073     if(same) {
9074       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9075       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9076     } else {
9077       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9078       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9079       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9080       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9081     }
9082
9083     while(--shCount) {
9084       if(sign)
9085                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9086       else
9087                 emitCLRC;
9088       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9089       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9090     }
9091     break;
9092   case 4:
9093   case 5:
9094     if(same) {
9095
9096       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9097       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9098       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9099
9100       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9101       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9102       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9103       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9104     } else {
9105       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9106       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9107       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9108
9109       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9110       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9111       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9112       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9113       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9114     }
9115
9116     if(shCount >=5) {
9117       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9118       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9119     }
9120
9121     if(sign) {
9122       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9123       pic16_emitpcode(POC_BTFSC, 
9124                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9125       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9126     }
9127
9128     break;
9129
9130   case 6:
9131     if(same) {
9132
9133       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9134       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9135
9136       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9137       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9138       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9139       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9140       if(sign) {
9141         pic16_emitpcode(POC_BTFSC, 
9142                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9143         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9144       }
9145       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9146       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9147       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9148       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9149     } else {
9150       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9151       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9152       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9153       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9154       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9155       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9156       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9157       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9158       if(sign) {
9159         pic16_emitpcode(POC_BTFSC, 
9160                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9161         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9162       }
9163       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9164       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9165
9166         
9167     }
9168
9169     break;
9170   case 7:
9171     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9172     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9173     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9174     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9175     if(sign) {
9176       emitSKPNC;
9177       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9178     } else 
9179       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9180   }
9181 }
9182
9183
9184 /*-----------------------------------------------------------------*/
9185 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9186 /*-----------------------------------------------------------------*/
9187 static void shiftLLeftOrResult (operand *left, int offl,
9188                                 operand *result, int offr, int shCount)
9189 {
9190     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9191
9192     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9193     /* shift left accumulator */
9194     AccLsh(shCount, 1);
9195     /* or with result */
9196     /* back to result */
9197     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9198 }
9199
9200 /*-----------------------------------------------------------------*/
9201 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9202 /*-----------------------------------------------------------------*/
9203 static void shiftRLeftOrResult (operand *left, int offl,
9204                                 operand *result, int offr, int shCount)
9205 {
9206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9207     
9208     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9209     /* shift right accumulator */
9210     AccRsh(shCount, 1);
9211     /* or with result */
9212     /* back to result */
9213     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9214 }
9215
9216 /*-----------------------------------------------------------------*/
9217 /* genlshOne - left shift a one byte quantity by known count       */
9218 /*-----------------------------------------------------------------*/
9219 static void genlshOne (operand *result, operand *left, int shCount)
9220 {       
9221     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9222     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9223 }
9224
9225 /*-----------------------------------------------------------------*/
9226 /* genlshTwo - left shift two bytes by known amount != 0           */
9227 /*-----------------------------------------------------------------*/
9228 static void genlshTwo (operand *result,operand *left, int shCount)
9229 {
9230     int size;
9231     
9232     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9233     size = pic16_getDataSize(result);
9234
9235     /* if shCount >= 8 */
9236     if (shCount >= 8) {
9237         shCount -= 8 ;
9238
9239         if (size > 1){
9240             if (shCount)
9241                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9242             else 
9243                 movLeft2Result(left, LSB, result, MSB16);
9244         }
9245         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9246     }
9247
9248     /*  1 <= shCount <= 7 */
9249     else {  
9250         if(size == 1)
9251             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9252         else 
9253             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9254     }
9255 }
9256
9257 /*-----------------------------------------------------------------*/
9258 /* shiftLLong - shift left one long from left to result            */
9259 /* offr = LSB or MSB16                                             */
9260 /*-----------------------------------------------------------------*/
9261 static void shiftLLong (operand *left, operand *result, int offr )
9262 {
9263     int size = AOP_SIZE(result);
9264     int same = pic16_sameRegs(AOP(left),AOP(result));
9265         int i;
9266
9267     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9268
9269         if (same && (offr == MSB16)) { //shift one byte
9270                 for(i=size-1;i>=MSB16;i--) {
9271                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9272                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9273                 }
9274         } else {
9275                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9276         }
9277         
9278     if (size > LSB+offr ){
9279                 if (same) {
9280                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9281                 } else {
9282                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9283                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9284                 }
9285          }
9286
9287     if(size > MSB16+offr){
9288                 if (same) {
9289                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9290                 } else {
9291                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9292                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9293                 }
9294     }
9295
9296     if(size > MSB24+offr){
9297                 if (same) {
9298                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9299                 } else {
9300                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9301                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9302                 }
9303     }
9304
9305     if(size > MSB32+offr){
9306                 if (same) {
9307                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9308                 } else {
9309                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9310                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9311                 }
9312     }
9313     if(offr != LSB)
9314                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9315
9316 }
9317
9318 /*-----------------------------------------------------------------*/
9319 /* genlshFour - shift four byte by a known amount != 0             */
9320 /*-----------------------------------------------------------------*/
9321 static void genlshFour (operand *result, operand *left, int shCount)
9322 {
9323     int size;
9324
9325     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9326     size = AOP_SIZE(result);
9327
9328     /* if shifting more that 3 bytes */
9329     if (shCount >= 24 ) {
9330         shCount -= 24;
9331         if (shCount)
9332             /* lowest order of left goes to the highest
9333             order of the destination */
9334             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9335         else
9336             movLeft2Result(left, LSB, result, MSB32);
9337
9338                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9339                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9340                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9341
9342         return;
9343     }
9344
9345     /* more than two bytes */
9346     else if ( shCount >= 16 ) {
9347         /* lower order two bytes goes to higher order two bytes */
9348         shCount -= 16;
9349         /* if some more remaining */
9350         if (shCount)
9351             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9352         else {
9353             movLeft2Result(left, MSB16, result, MSB32);
9354             movLeft2Result(left, LSB, result, MSB24);
9355         }
9356                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9357                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9358         return;
9359     }    
9360
9361     /* if more than 1 byte */
9362     else if ( shCount >= 8 ) {
9363         /* lower order three bytes goes to higher order  three bytes */
9364         shCount -= 8;
9365         if(size == 2){
9366             if(shCount)
9367                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9368             else
9369                 movLeft2Result(left, LSB, result, MSB16);
9370         }
9371         else{   /* size = 4 */
9372             if(shCount == 0){
9373                 movLeft2Result(left, MSB24, result, MSB32);
9374                 movLeft2Result(left, MSB16, result, MSB24);
9375                 movLeft2Result(left, LSB, result, MSB16);
9376                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9377             }
9378             else if(shCount == 1)
9379                 shiftLLong(left, result, MSB16);
9380             else{
9381                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9382                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9383                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9384                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9385             }
9386         }
9387     }
9388
9389     /* 1 <= shCount <= 7 */
9390     else if(shCount <= 3)
9391     { 
9392         shiftLLong(left, result, LSB);
9393         while(--shCount >= 1)
9394             shiftLLong(result, result, LSB);
9395     }
9396     /* 3 <= shCount <= 7, optimize */
9397     else{
9398         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9399         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9400         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9401     }
9402 }
9403
9404 /*-----------------------------------------------------------------*/
9405 /* genLeftShiftLiteral - left shifting by known count              */
9406 /*-----------------------------------------------------------------*/
9407 void pic16_genLeftShiftLiteral (operand *left,
9408                                  operand *right,
9409                                  operand *result,
9410                                  iCode *ic)
9411 {    
9412     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9413     int size;
9414
9415     FENTRY;
9416     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9417     pic16_freeAsmop(right,NULL,ic,TRUE);
9418
9419     pic16_aopOp(left,ic,FALSE);
9420     pic16_aopOp(result,ic,TRUE);
9421
9422     size = getSize(operandType(result));
9423
9424 #if VIEW_SIZE
9425     pic16_emitcode("; shift left ","result %d, left %d",size,
9426              AOP_SIZE(left));
9427 #endif
9428
9429     /* I suppose that the left size >= result size */
9430     if(shCount == 0){
9431         while(size--){
9432             movLeft2Result(left, size, result, size);
9433         }
9434     }
9435
9436     else if(shCount >= (size * 8))
9437         while(size--)
9438             pic16_aopPut(AOP(result),zero,size);
9439     else{
9440         switch (size) {
9441             case 1:
9442                 genlshOne (result,left,shCount);
9443                 break;
9444
9445             case 2:
9446             case 3:
9447                 genlshTwo (result,left,shCount);
9448                 break;
9449
9450             case 4:
9451                 genlshFour (result,left,shCount);
9452                 break;
9453         }
9454     }
9455     pic16_freeAsmop(left,NULL,ic,TRUE);
9456     pic16_freeAsmop(result,NULL,ic,TRUE);
9457 }
9458
9459 /*-----------------------------------------------------------------*
9460  * genMultiAsm - repeat assembly instruction for size of register.
9461  * if endian == 1, then the high byte (i.e base address + size of 
9462  * register) is used first else the low byte is used first;
9463  *-----------------------------------------------------------------*/
9464 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9465 {
9466
9467   int offset = 0;
9468
9469   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9470
9471   if(!reg)
9472     return;
9473
9474   if(!endian) {
9475     endian = 1;
9476   } else {
9477     endian = -1;
9478     offset = size-1;
9479   }
9480
9481   while(size--) {
9482     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9483     offset += endian;
9484   }
9485
9486 }
9487
9488 #if !(USE_GENERIC_SIGNED_SHIFT)
9489 /*-----------------------------------------------------------------*/
9490 /* genLeftShift - generates code for left shifting                 */
9491 /*-----------------------------------------------------------------*/
9492 static void genLeftShift (iCode *ic)
9493 {
9494   operand *left,*right, *result;
9495   int size, offset;
9496 //  char *l;
9497   symbol *tlbl , *tlbl1;
9498   pCodeOp *pctemp;
9499
9500   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9501
9502   right = IC_RIGHT(ic);
9503   left  = IC_LEFT(ic);
9504   result = IC_RESULT(ic);
9505
9506   pic16_aopOp(right,ic,FALSE);
9507
9508   /* if the shift count is known then do it 
9509      as efficiently as possible */
9510   if (AOP_TYPE(right) == AOP_LIT) {
9511     pic16_genLeftShiftLiteral (left,right,result,ic);
9512     return ;
9513   }
9514
9515   /* shift count is unknown then we have to form
9516    * a loop. Get the loop count in WREG : Note: we take
9517    * only the lower order byte since shifting
9518    * more than 32 bits make no sense anyway, ( the
9519    * largest size of an object can be only 32 bits ) */
9520   
9521   pic16_aopOp(left,ic,FALSE);
9522   pic16_aopOp(result,ic,FALSE);
9523
9524   /* now move the left to the result if they are not the
9525    * same, and if size > 1,
9526    * and if right is not same to result (!!!) -- VR */
9527   if (!pic16_sameRegs(AOP(left),AOP(result))
9528       && (AOP_SIZE(result) > 1)) {
9529
9530     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9531
9532     size = AOP_SIZE(result);
9533     offset=0;
9534     while (size--) {
9535
9536 #if 0
9537       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9538       if (*l == '@' && (IS_AOP_PREG(result))) {
9539
9540           pic16_emitcode("mov","a,%s",l);
9541           pic16_aopPut(AOP(result),"a",offset);
9542       } else
9543 #endif
9544       {
9545         /* we don't know if left is a literal or a register, take care -- VR */
9546         pic16_mov2f(AOP(result), AOP(left), offset);
9547       }
9548       offset++;
9549     }
9550   }
9551
9552   size = AOP_SIZE(result);
9553
9554   /* if it is only one byte then */
9555   if (size == 1) {
9556     if(optimized_for_speed) {
9557       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9558       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9559       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9560       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9561       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9562       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9563       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9564       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9565       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9566       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9567       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9568       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9569     } else {
9570
9571       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9572
9573       tlbl = newiTempLabel(NULL);
9574
9575 #if 1
9576       /* this is already done, why change it? */
9577       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9578                 pic16_mov2f(AOP(result), AOP(left), 0);
9579       }
9580 #endif
9581
9582       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9583       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9584       pic16_emitpLabel(tlbl->key);
9585       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9586       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9587       emitSKPC;
9588       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9589     }
9590     goto release ;
9591   }
9592     
9593   if (pic16_sameRegs(AOP(left),AOP(result))) {
9594
9595     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9596     
9597     tlbl = newiTempLabel(NULL);
9598     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9599     genMultiAsm(POC_RRCF, result, size,1);
9600     pic16_emitpLabel(tlbl->key);
9601     genMultiAsm(POC_RLCF, result, size,0);
9602     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9603     emitSKPC;
9604     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9605     goto release;
9606   }
9607
9608   //tlbl = newiTempLabel(NULL);
9609   //offset = 0 ;   
9610   //tlbl1 = newiTempLabel(NULL);
9611
9612   //reAdjustPreg(AOP(result));    
9613     
9614   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9615   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9616   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9617   //MOVA(l);
9618   //pic16_emitcode("add","a,acc");         
9619   //pic16_aopPut(AOP(result),"a",offset++);
9620   //while (--size) {
9621   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9622   //  MOVA(l);
9623   //  pic16_emitcode("rlc","a");         
9624   //  pic16_aopPut(AOP(result),"a",offset++);
9625   //}
9626   //reAdjustPreg(AOP(result));
9627
9628   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9629   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9630
9631
9632   tlbl = newiTempLabel(NULL);
9633   tlbl1= newiTempLabel(NULL);
9634
9635   size = AOP_SIZE(result);
9636   offset = 1;
9637
9638   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9639
9640   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9641
9642   /* offset should be 0, 1 or 3 */
9643   
9644   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9645   emitSKPNZ;
9646   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9647
9648   pic16_emitpcode(POC_MOVWF, pctemp);
9649
9650
9651   pic16_emitpLabel(tlbl->key);
9652
9653   emitCLRC;
9654   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9655   while(--size)
9656     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9657
9658   pic16_emitpcode(POC_DECFSZ,  pctemp);
9659   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9660   pic16_emitpLabel(tlbl1->key);
9661
9662   pic16_popReleaseTempReg(pctemp,1);
9663
9664
9665  release:
9666   pic16_freeAsmop (right,NULL,ic,TRUE);
9667   pic16_freeAsmop(left,NULL,ic,TRUE);
9668   pic16_freeAsmop(result,NULL,ic,TRUE);
9669 }
9670 #endif
9671
9672
9673 #if 0
9674 #error old code (left here for reference)
9675 /*-----------------------------------------------------------------*/
9676 /* genLeftShift - generates code for left shifting                 */
9677 /*-----------------------------------------------------------------*/
9678 static void genLeftShift (iCode *ic)
9679 {
9680   operand *left,*right, *result;
9681   int size, offset;
9682   char *l;
9683   symbol *tlbl , *tlbl1;
9684   pCodeOp *pctemp;
9685
9686   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9687
9688   right = IC_RIGHT(ic);
9689   left  = IC_LEFT(ic);
9690   result = IC_RESULT(ic);
9691
9692   pic16_aopOp(right,ic,FALSE);
9693
9694   /* if the shift count is known then do it 
9695      as efficiently as possible */
9696   if (AOP_TYPE(right) == AOP_LIT) {
9697     pic16_genLeftShiftLiteral (left,right,result,ic);
9698     return ;
9699   }
9700
9701   /* shift count is unknown then we have to form 
9702      a loop get the loop count in B : Note: we take
9703      only the lower order byte since shifting
9704      more that 32 bits make no sense anyway, ( the
9705      largest size of an object can be only 32 bits ) */  
9706
9707     
9708   pic16_aopOp(left,ic,FALSE);
9709   pic16_aopOp(result,ic,FALSE);
9710
9711   /* now move the left to the result if they are not the
9712      same */
9713   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9714       AOP_SIZE(result) > 1) {
9715
9716     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9717
9718     size = AOP_SIZE(result);
9719     offset=0;
9720     while (size--) {
9721       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9722       if (*l == '@' && (IS_AOP_PREG(result))) {
9723
9724         pic16_emitcode("mov","a,%s",l);
9725         pic16_aopPut(AOP(result),"a",offset);
9726       } else {
9727
9728         /* we don't know if left is a literal or a register, take care -- VR */
9729         pic16_mov2f(AOP(result), AOP(left), offset);
9730       }
9731       offset++;
9732     }
9733   }
9734
9735   size = AOP_SIZE(result);
9736
9737   /* if it is only one byte then */
9738   if (size == 1) {
9739     if(optimized_for_speed) {
9740       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9741       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9742       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9743       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9744       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9745       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9746       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9747       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9748       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9749       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9750       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9751       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9752     } else {
9753
9754       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9755
9756       tlbl = newiTempLabel(NULL);
9757       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9758                 pic16_mov2f(AOP(result), AOP(left), 0);
9759                 
9760 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9761 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9762       }
9763
9764       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9765       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9766       pic16_emitpLabel(tlbl->key);
9767       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9768       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9769       emitSKPC;
9770       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9771     }
9772     goto release ;
9773   }
9774     
9775   if (pic16_sameRegs(AOP(left),AOP(result))) {
9776
9777     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9778     
9779     tlbl = newiTempLabel(NULL);
9780     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9781     genMultiAsm(POC_RRCF, result, size,1);
9782     pic16_emitpLabel(tlbl->key);
9783     genMultiAsm(POC_RLCF, result, size,0);
9784     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9785     emitSKPC;
9786     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9787     goto release;
9788   }
9789
9790   //tlbl = newiTempLabel(NULL);
9791   //offset = 0 ;   
9792   //tlbl1 = newiTempLabel(NULL);
9793
9794   //reAdjustPreg(AOP(result));    
9795     
9796   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9797   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9798   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9799   //MOVA(l);
9800   //pic16_emitcode("add","a,acc");         
9801   //pic16_aopPut(AOP(result),"a",offset++);
9802   //while (--size) {
9803   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9804   //  MOVA(l);
9805   //  pic16_emitcode("rlc","a");         
9806   //  pic16_aopPut(AOP(result),"a",offset++);
9807   //}
9808   //reAdjustPreg(AOP(result));
9809
9810   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9811   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9812
9813
9814   tlbl = newiTempLabel(NULL);
9815   tlbl1= newiTempLabel(NULL);
9816
9817   size = AOP_SIZE(result);
9818   offset = 1;
9819
9820   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9821
9822   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9823
9824   /* offset should be 0, 1 or 3 */
9825   
9826   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9827   emitSKPNZ;
9828   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9829
9830   pic16_emitpcode(POC_MOVWF, pctemp);
9831
9832
9833   pic16_emitpLabel(tlbl->key);
9834
9835   emitCLRC;
9836   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9837   while(--size)
9838     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9839
9840   pic16_emitpcode(POC_DECFSZ,  pctemp);
9841   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9842   pic16_emitpLabel(tlbl1->key);
9843
9844   pic16_popReleaseTempReg(pctemp,1);
9845
9846
9847  release:
9848   pic16_freeAsmop (right,NULL,ic,TRUE);
9849   pic16_freeAsmop(left,NULL,ic,TRUE);
9850   pic16_freeAsmop(result,NULL,ic,TRUE);
9851 }
9852 #endif
9853
9854 /*-----------------------------------------------------------------*/
9855 /* genrshOne - right shift a one byte quantity by known count      */
9856 /*-----------------------------------------------------------------*/
9857 static void genrshOne (operand *result, operand *left,
9858                        int shCount, int sign)
9859 {
9860     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9861     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9862 }
9863
9864 /*-----------------------------------------------------------------*/
9865 /* genrshTwo - right shift two bytes by known amount != 0          */
9866 /*-----------------------------------------------------------------*/
9867 static void genrshTwo (operand *result,operand *left,
9868                        int shCount, int sign)
9869 {
9870   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9871   /* if shCount >= 8 */
9872   if (shCount >= 8) {
9873     shCount -= 8 ;
9874     if (shCount)
9875       shiftR1Left2Result(left, MSB16, result, LSB,
9876                          shCount, sign);
9877     else
9878       movLeft2Result(left, MSB16, result, LSB);
9879
9880     pic16_addSign (result, 1, sign);
9881   }
9882
9883   /*  1 <= shCount <= 7 */
9884   else
9885     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9886 }
9887
9888 /*-----------------------------------------------------------------*/
9889 /* shiftRLong - shift right one long from left to result           */
9890 /* offl = LSB or MSB16                                             */
9891 /*-----------------------------------------------------------------*/
9892 static void shiftRLong (operand *left, int offl,
9893                         operand *result, int sign)
9894 {
9895     int size = AOP_SIZE(result);
9896     int same = pic16_sameRegs(AOP(left),AOP(result));
9897     int i;
9898     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9899
9900         if (same && (offl == MSB16)) { //shift one byte right
9901                 for(i=MSB16;i<size;i++) {
9902                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9903                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9904                 }
9905         }
9906
9907     if(sign)
9908                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9909         else
9910                 emitCLRC;
9911
9912         if (same) {
9913                 if (offl == LSB)
9914                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9915         } else {
9916         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9917         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9918         }
9919
9920     if(offl == MSB16) {
9921         /* add sign of "a" */
9922         pic16_addSign(result, MSB32, sign);
9923         }
9924
9925         if (same) {
9926         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9927         } else {
9928         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9929         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9930         }
9931         
9932         if (same) {
9933         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9934         } else {
9935         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9936         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9937         }
9938
9939         if (same) {
9940         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9941         } else {
9942         if(offl == LSB){
9943                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9944                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9945         }
9946         }
9947 }
9948
9949 /*-----------------------------------------------------------------*/
9950 /* genrshFour - shift four byte by a known amount != 0             */
9951 /*-----------------------------------------------------------------*/
9952 static void genrshFour (operand *result, operand *left,
9953                         int shCount, int sign)
9954 {
9955   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9956   /* if shifting more that 3 bytes */
9957   if(shCount >= 24 ) {
9958     shCount -= 24;
9959     if(shCount)
9960       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9961     else
9962       movLeft2Result(left, MSB32, result, LSB);
9963
9964     pic16_addSign(result, MSB16, sign);
9965   }
9966   else if(shCount >= 16){
9967     shCount -= 16;
9968     if(shCount)
9969       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9970     else{
9971       movLeft2Result(left, MSB24, result, LSB);
9972       movLeft2Result(left, MSB32, result, MSB16);
9973     }
9974     pic16_addSign(result, MSB24, sign);
9975   }
9976   else if(shCount >= 8){
9977     shCount -= 8;
9978     if(shCount == 1)
9979       shiftRLong(left, MSB16, result, sign);
9980     else if(shCount == 0){
9981       movLeft2Result(left, MSB16, result, LSB);
9982       movLeft2Result(left, MSB24, result, MSB16);
9983       movLeft2Result(left, MSB32, result, MSB24);
9984       pic16_addSign(result, MSB32, sign);
9985     }
9986     else{ //shcount >= 2
9987       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9988       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9989       /* the last shift is signed */
9990       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9991       pic16_addSign(result, MSB32, sign);
9992     }
9993   }
9994   else{   /* 1 <= shCount <= 7 */
9995     if(shCount <= 2){
9996       shiftRLong(left, LSB, result, sign);
9997       if(shCount == 2)
9998         shiftRLong(result, LSB, result, sign);
9999     }
10000     else{
10001       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10002       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10003       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10004     }
10005   }
10006 }
10007
10008 /*-----------------------------------------------------------------*/
10009 /* genRightShiftLiteral - right shifting by known count            */
10010 /*-----------------------------------------------------------------*/
10011 static void genRightShiftLiteral (operand *left,
10012                                   operand *right,
10013                                   operand *result,
10014                                   iCode *ic,
10015                                   int sign)
10016 {    
10017   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10018   int lsize,res_size;
10019
10020   pic16_freeAsmop(right,NULL,ic,TRUE);
10021
10022   pic16_aopOp(left,ic,FALSE);
10023   pic16_aopOp(result,ic,TRUE);
10024
10025   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10026
10027 #if VIEW_SIZE
10028   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10029                  AOP_SIZE(left));
10030 #endif
10031
10032   lsize = pic16_getDataSize(left);
10033   res_size = pic16_getDataSize(result);
10034   /* test the LEFT size !!! */
10035
10036   /* I suppose that the left size >= result size */
10037   if(shCount == 0){
10038     assert (res_size <= lsize);
10039     while (res_size--) {
10040       pic16_mov2f (AOP(result), AOP(left), res_size);
10041     } // for
10042   }
10043
10044   else if(shCount >= (lsize * 8)){
10045
10046     if(res_size == 1) {
10047       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10048       if(sign) {
10049         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10050         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10051       }
10052     } else {
10053
10054       if(sign) {
10055         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10056         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10057         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10058         while(res_size--)
10059           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10060
10061       } else {
10062
10063         while(res_size--)
10064           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10065       }
10066     }
10067   } else {
10068
10069     switch (res_size) {
10070     case 1:
10071       genrshOne (result,left,shCount,sign);
10072       break;
10073
10074     case 2:
10075       genrshTwo (result,left,shCount,sign);
10076       break;
10077
10078     case 4:
10079       genrshFour (result,left,shCount,sign);
10080       break;
10081     default :
10082       break;
10083     }
10084
10085   }
10086
10087   pic16_freeAsmop(left,NULL,ic,TRUE);
10088   pic16_freeAsmop(result,NULL,ic,TRUE);
10089 }
10090
10091 #if !(USE_GENERIC_SIGNED_SHIFT)
10092 /*-----------------------------------------------------------------*/
10093 /* genSignedRightShift - right shift of signed number              */
10094 /*-----------------------------------------------------------------*/
10095 static void genSignedRightShift (iCode *ic)
10096 {
10097   operand *right, *left, *result;
10098   int size, offset;
10099   //  char *l;
10100   symbol *tlbl, *tlbl1 ;
10101   pCodeOp *pctemp;
10102
10103   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10104
10105   /* we do it the hard way put the shift count in b
10106      and loop thru preserving the sign */
10107   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10108
10109   right = IC_RIGHT(ic);
10110   left  = IC_LEFT(ic);
10111   result = IC_RESULT(ic);
10112
10113   pic16_aopOp(right,ic,FALSE);  
10114   pic16_aopOp(left,ic,FALSE);
10115   pic16_aopOp(result,ic,FALSE);
10116
10117
10118   if ( AOP_TYPE(right) == AOP_LIT) {
10119     genRightShiftLiteral (left,right,result,ic,1);
10120     return ;
10121   }
10122   /* shift count is unknown then we have to form 
10123      a loop get the loop count in B : Note: we take
10124      only the lower order byte since shifting
10125      more that 32 bits make no sense anyway, ( the
10126      largest size of an object can be only 32 bits ) */  
10127
10128   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10129   //pic16_emitcode("inc","b");
10130   //pic16_freeAsmop (right,NULL,ic,TRUE);
10131   //pic16_aopOp(left,ic,FALSE);
10132   //pic16_aopOp(result,ic,FALSE);
10133
10134   /* now move the left to the result if they are not the
10135      same */
10136   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10137       AOP_SIZE(result) > 1) {
10138
10139     size = AOP_SIZE(result);
10140     offset=0;
10141     while (size--) { 
10142       /*
10143         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10144         if (*l == '@' && IS_AOP_PREG(result)) {
10145
10146         pic16_emitcode("mov","a,%s",l);
10147         pic16_aopPut(AOP(result),"a",offset);
10148         } else
10149         pic16_aopPut(AOP(result),l,offset);
10150       */
10151       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10152       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10153
10154       offset++;
10155     }
10156   }
10157
10158   /* mov the highest order bit to OVR */    
10159   tlbl = newiTempLabel(NULL);
10160   tlbl1= newiTempLabel(NULL);
10161
10162   size = AOP_SIZE(result);
10163   offset = size - 1;
10164
10165   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10166
10167   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10168
10169   /* offset should be 0, 1 or 3 */
10170   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10171   emitSKPNZ;
10172   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10173
10174   pic16_emitpcode(POC_MOVWF, pctemp);
10175
10176
10177   pic16_emitpLabel(tlbl->key);
10178
10179   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10180   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10181
10182   while(--size) {
10183     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10184   }
10185
10186   pic16_emitpcode(POC_DECFSZ,  pctemp);
10187   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10188   pic16_emitpLabel(tlbl1->key);
10189
10190   pic16_popReleaseTempReg(pctemp,1);
10191 #if 0
10192   size = AOP_SIZE(result);
10193   offset = size - 1;
10194   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10195   pic16_emitcode("rlc","a");
10196   pic16_emitcode("mov","ov,c");
10197   /* if it is only one byte then */
10198   if (size == 1) {
10199     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10200     MOVA(l);
10201     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10202     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10203     pic16_emitcode("mov","c,ov");
10204     pic16_emitcode("rrc","a");
10205     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10206     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10207     pic16_aopPut(AOP(result),"a",0);
10208     goto release ;
10209   }
10210
10211   reAdjustPreg(AOP(result));
10212   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10213   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10214   pic16_emitcode("mov","c,ov");
10215   while (size--) {
10216     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10217     MOVA(l);
10218     pic16_emitcode("rrc","a");         
10219     pic16_aopPut(AOP(result),"a",offset--);
10220   }
10221   reAdjustPreg(AOP(result));
10222   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10223   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10224
10225  release:
10226 #endif
10227
10228   pic16_freeAsmop(left,NULL,ic,TRUE);
10229   pic16_freeAsmop(result,NULL,ic,TRUE);
10230   pic16_freeAsmop(right,NULL,ic,TRUE);
10231 }
10232 #endif
10233
10234 #if !(USE_GENERIC_SIGNED_SHIFT)
10235 #warning This implementation of genRightShift() is incomplete!
10236 /*-----------------------------------------------------------------*/
10237 /* genRightShift - generate code for right shifting                */
10238 /*-----------------------------------------------------------------*/
10239 static void genRightShift (iCode *ic)
10240 {
10241     operand *right, *left, *result;
10242     sym_link *letype ;
10243     int size, offset;
10244     char *l;
10245     symbol *tlbl, *tlbl1 ;
10246
10247     /* if signed then we do it the hard way preserve the
10248     sign bit moving it inwards */
10249     letype = getSpec(operandType(IC_LEFT(ic)));
10250     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10251
10252     if (!SPEC_USIGN(letype)) {
10253         genSignedRightShift (ic);
10254         return ;
10255     }
10256
10257     /* signed & unsigned types are treated the same : i.e. the
10258     signed is NOT propagated inwards : quoting from the
10259     ANSI - standard : "for E1 >> E2, is equivalent to division
10260     by 2**E2 if unsigned or if it has a non-negative value,
10261     otherwise the result is implementation defined ", MY definition
10262     is that the sign does not get propagated */
10263
10264     right = IC_RIGHT(ic);
10265     left  = IC_LEFT(ic);
10266     result = IC_RESULT(ic);
10267
10268     pic16_aopOp(right,ic,FALSE);
10269
10270     /* if the shift count is known then do it 
10271     as efficiently as possible */
10272     if (AOP_TYPE(right) == AOP_LIT) {
10273         genRightShiftLiteral (left,right,result,ic, 0);
10274         return ;
10275     }
10276
10277     /* shift count is unknown then we have to form 
10278     a loop get the loop count in B : Note: we take
10279     only the lower order byte since shifting
10280     more that 32 bits make no sense anyway, ( the
10281     largest size of an object can be only 32 bits ) */  
10282
10283     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10284     pic16_emitcode("inc","b");
10285     pic16_aopOp(left,ic,FALSE);
10286     pic16_aopOp(result,ic,FALSE);
10287
10288     /* now move the left to the result if they are not the
10289     same */
10290     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10291         AOP_SIZE(result) > 1) {
10292
10293         size = AOP_SIZE(result);
10294         offset=0;
10295         while (size--) {
10296             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10297             if (*l == '@' && IS_AOP_PREG(result)) {
10298
10299                 pic16_emitcode("mov","a,%s",l);
10300                 pic16_aopPut(AOP(result),"a",offset);
10301             } else
10302                 pic16_aopPut(AOP(result),l,offset);
10303             offset++;
10304         }
10305     }
10306
10307     tlbl = newiTempLabel(NULL);
10308     tlbl1= newiTempLabel(NULL);
10309     size = AOP_SIZE(result);
10310     offset = size - 1;
10311
10312     /* if it is only one byte then */
10313     if (size == 1) {
10314
10315       tlbl = newiTempLabel(NULL);
10316       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10317         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10318         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10319       }
10320
10321       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10322       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10323       pic16_emitpLabel(tlbl->key);
10324       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10325       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10326       emitSKPC;
10327       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10328
10329       goto release ;
10330     }
10331
10332     reAdjustPreg(AOP(result));
10333     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10334     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10335     CLRC;
10336     while (size--) {
10337         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10338         MOVA(l);
10339         pic16_emitcode("rrc","a");         
10340         pic16_aopPut(AOP(result),"a",offset--);
10341     }
10342     reAdjustPreg(AOP(result));
10343
10344     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10345     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10346
10347 release:
10348     pic16_freeAsmop(left,NULL,ic,TRUE);
10349     pic16_freeAsmop (right,NULL,ic,TRUE);
10350     pic16_freeAsmop(result,NULL,ic,TRUE);
10351 }
10352 #endif
10353
10354 #if (USE_GENERIC_SIGNED_SHIFT)
10355 /*-----------------------------------------------------------------*/
10356 /* genGenericShift - generates code for left or right shifting     */
10357 /*-----------------------------------------------------------------*/
10358 static void genGenericShift (iCode *ic, int isShiftLeft) {
10359   operand *left,*right, *result;
10360   int offset;
10361   int sign, signedCount;
10362   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10363   PIC_OPCODE pos_shift, neg_shift;
10364
10365   FENTRY;
10366
10367   right = IC_RIGHT(ic);
10368   left  = IC_LEFT(ic);
10369   result = IC_RESULT(ic);
10370
10371   pic16_aopOp(right,ic,FALSE);
10372   pic16_aopOp(left,ic,FALSE);
10373   pic16_aopOp(result,ic,TRUE);
10374
10375   sign = !SPEC_USIGN(operandType (left));
10376   signedCount = !SPEC_USIGN(operandType (right));
10377
10378   /* if the shift count is known then do it 
10379      as efficiently as possible */
10380   if (AOP_TYPE(right) == AOP_LIT) {
10381     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10382     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10383     // we should modify right->aopu.aop_lit here!
10384     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10385     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10386     if (isShiftLeft)
10387       pic16_genLeftShiftLiteral (left,right,result,ic);
10388     else
10389       genRightShiftLiteral (left,right,result,ic, sign);
10390
10391     goto release;
10392   } // if (right is literal)
10393
10394   /* shift count is unknown then we have to form a loop.
10395    * Note: we take only the lower order byte since shifting
10396    * more than 32 bits make no sense anyway, ( the
10397    * largest size of an object can be only 32 bits )
10398    * Note: we perform arithmetic shifts if the left operand is
10399    * signed and we do an (effective) right shift, i. e. we
10400    * shift in the sign bit from the left. */
10401    
10402   label_complete = newiTempLabel ( NULL );
10403   label_loop_pos = newiTempLabel ( NULL );
10404   label_loop_neg = NULL;
10405   label_negative = NULL;
10406   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10407   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10408
10409   if (signedCount) {
10410     // additional labels needed
10411     label_loop_neg = newiTempLabel ( NULL );
10412     label_negative = newiTempLabel ( NULL );
10413   } // if
10414
10415   // copy source to result -- this will effectively truncate the left operand to the size of result!
10416   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10417   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10418   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10419     pic16_mov2f (AOP(result),AOP(left), offset);
10420   } // for
10421
10422   // if result is longer than left, fill with zeros (or sign)
10423   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10424     if (sign && AOP_SIZE(left) > 0) {
10425       // shift signed operand -- fill with sign
10426       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10427       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10428       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10429       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10430         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10431       } // for
10432     } else {
10433       // shift unsigned operand -- fill result with zeros
10434       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10435         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10436       } // for
10437     }
10438   } // if (size mismatch)
10439
10440   pic16_mov2w (AOP(right), 0);
10441   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10442   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10443   
10444 #if 0
10445   // perform a shift by one (shift count is positive)
10446   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10447   // 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])
10448   pic16_emitpLabel (label_loop_pos->key);
10449   emitCLRC;
10450   if (sign && (pos_shift == POC_RRCF)) {
10451     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10452     emitSETC;
10453   } // if
10454   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10455   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10456   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10457 #else
10458   // perform a shift by one (shift count is positive)
10459   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10460   // 2n+[2,3]+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])
10461   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10462   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10463   emitCLRC;
10464   pic16_emitpLabel (label_loop_pos->key);
10465   if (sign && (pos_shift == POC_RRCF)) {
10466     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10467     emitSETC;
10468   } // if
10469   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10470   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10471   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10472   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10473 #endif
10474
10475   if (signedCount) {
10476     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10477
10478     pic16_emitpLabel (label_negative->key);
10479     // perform a shift by -1 (shift count is negative)
10480     // 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)
10481     emitCLRC;
10482     pic16_emitpLabel (label_loop_neg->key);
10483     if (sign && (neg_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 (neg_shift, result, AOP_SIZE(result), neg_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_neg->key));
10491   } // if (signedCount)
10492
10493   pic16_emitpLabel (label_complete->key);
10494
10495 release:
10496   pic16_freeAsmop (right,NULL,ic,TRUE);
10497   pic16_freeAsmop(left,NULL,ic,TRUE);
10498   pic16_freeAsmop(result,NULL,ic,TRUE);
10499 }
10500
10501 static void genLeftShift (iCode *ic) {
10502   genGenericShift (ic, 1);
10503 }
10504
10505 static void genRightShift (iCode *ic) {
10506   genGenericShift (ic, 0);
10507 }
10508 #endif
10509
10510
10511 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10512 void pic16_loadFSR0(operand *op, int lit)
10513 {
10514   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10515     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10516   } else {
10517     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10518     // set up FSR0 with address of result
10519     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10520     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10521   }
10522 }
10523
10524 /*----------------------------------------------------------------*/
10525 /* pic16_derefPtr - move one byte from the location ptr points to */
10526 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10527 /*                  to the location ptr points to (doWrite != 0)   */
10528 /*----------------------------------------------------------------*/
10529 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10530 {
10531   if (!IS_PTR(operandType(ptr)))
10532   {
10533     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10534     else pic16_mov2w (AOP(ptr), 0);
10535     return;
10536   }
10537
10538   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10539   /* We might determine pointer type right here: */
10540   p_type = DCL_TYPE(operandType(ptr));
10541
10542   switch (p_type) {
10543     case FPOINTER:
10544     case POINTER:
10545       if (!fsr0_setup || !*fsr0_setup)
10546       {
10547         pic16_loadFSR0( ptr, 0 );
10548         if (fsr0_setup) *fsr0_setup = 1;
10549       }
10550       if (doWrite)
10551         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10552       else
10553         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10554       break;
10555
10556     case GPOINTER:
10557       if (AOP(ptr)->aopu.aop_reg[2]) {
10558         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10559         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10560         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10561         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10562         pic16_mov2w(AOP(ptr), 2);
10563         pic16_callGenericPointerRW(doWrite, 1);
10564       } else {
10565         // data pointer (just 2 byte given)
10566         if (!fsr0_setup || !*fsr0_setup)
10567         {
10568           pic16_loadFSR0( ptr, 0 );
10569           if (fsr0_setup) *fsr0_setup = 1;
10570         }
10571         if (doWrite)
10572           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10573         else
10574           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10575       }
10576       break;
10577
10578     default:
10579       assert (0 && "invalid pointer type specified");
10580       break;
10581   }
10582 }
10583
10584 /*-----------------------------------------------------------------*/
10585 /* genUnpackBits - generates code for unpacking bits               */
10586 /*-----------------------------------------------------------------*/
10587 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10588 {    
10589   int shCnt ;
10590   sym_link *etype, *letype;
10591   int blen=0, bstr=0;
10592   int lbstr;
10593   int same;
10594   pCodeOp *op;
10595
10596   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10597   etype = getSpec(operandType(result));
10598   letype = getSpec(operandType(left));
10599
10600   //    if(IS_BITFIELD(etype)) {
10601   blen = SPEC_BLEN(etype);
10602   bstr = SPEC_BSTR(etype);
10603   //    }
10604
10605   lbstr = SPEC_BSTR( letype );
10606
10607   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10608       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10609
10610 #if 1
10611   if((blen == 1) && (bstr < 8)
10612       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10613     /* it is a single bit, so use the appropriate bit instructions */
10614     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10615
10616     same = pic16_sameRegs(AOP(left),AOP(result));
10617     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10618     pic16_emitpcode(POC_CLRF, op);
10619
10620     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10621       /* workaround to reduce the extra lfsr instruction */
10622       pic16_emitpcode(POC_BTFSC,
10623           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10624     } else {
10625       assert (PIC_IS_DATA_PTR (operandType(left)));
10626       pic16_loadFSR0 (left, 0);
10627       pic16_emitpcode(POC_BTFSC,
10628           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10629     }
10630
10631     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10632       /* unsigned bitfields result in either 0 or 1 */
10633       pic16_emitpcode(POC_INCF, op);
10634     } else {
10635       /* signed bitfields result in either 0 or -1 */
10636       pic16_emitpcode(POC_DECF, op);
10637     }
10638     if (same) {
10639       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10640     }
10641
10642     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10643     return;
10644   }
10645
10646 #endif
10647
10648   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10649     // access symbol directly
10650     pic16_mov2w (AOP(left), 0);
10651   } else {
10652     pic16_derefPtr (left, ptype, 0, NULL);
10653   }
10654
10655   /* if we have bitdisplacement then it fits   */
10656   /* into this byte completely or if length is */
10657   /* less than a byte                          */
10658   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10659
10660     /* shift right acc */
10661     AccRsh(shCnt, 0);
10662
10663     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10664           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10665
10666     /* VR -- normally I would use the following, but since we use the hack,
10667      * to avoid the masking from AccRsh, why not mask it right now? */
10668
10669     /*
10670        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10671      */
10672
10673     /* extend signed bitfields to 8 bits */
10674     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10675     {
10676       assert (blen + bstr > 0);
10677       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10678       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10679     }
10680
10681     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10682
10683     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10684     return ;
10685   }
10686
10687   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10688   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10689   exit(-1);
10690
10691   return ;
10692 }
10693
10694
10695 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10696 {
10697   int size, offset = 0, leoffset=0 ;
10698
10699         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10700         pic16_aopOp(result, ic, TRUE);
10701
10702         FENTRY;
10703
10704         size = AOP_SIZE(result);
10705 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10706
10707
10708 #if 1
10709         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10710                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10711                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10712                 goto release;
10713         }
10714 #endif
10715
10716         if(AOP(left)->aopu.pcop->type == PO_DIR)
10717                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10718
10719         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10720
10721         while (size--) {
10722                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10723                 
10724 //              pic16_DumpOp("(result)",result);
10725                 if(is_LitAOp(AOP(result))) {
10726                         pic16_mov2w(AOP(left), offset); // patch 8
10727                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10728                 } else {
10729                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10730                                 pic16_popGet(AOP(left), offset), //patch 8
10731                                 pic16_popGet(AOP(result), offset)));
10732                 }
10733
10734                 offset++;
10735                 leoffset++;
10736         }
10737
10738 release:
10739     pic16_freeAsmop(result,NULL,ic,TRUE);
10740 }
10741
10742
10743
10744 /*-----------------------------------------------------------------*/
10745 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10746 /*-----------------------------------------------------------------*/
10747 static void genNearPointerGet (operand *left, 
10748                                operand *result, 
10749                                iCode *ic)
10750 {
10751 //  asmop *aop = NULL;
10752   //regs *preg = NULL ;
10753   sym_link *rtype, *retype;
10754   sym_link *ltype, *letype;
10755
10756     FENTRY;
10757     
10758     rtype = operandType(result);
10759     retype= getSpec(rtype);
10760     ltype = operandType(left);
10761     letype= getSpec(ltype);
10762     
10763     pic16_aopOp(left,ic,FALSE);
10764
10765 //    pic16_DumpOp("(left)",left);
10766 //    pic16_DumpOp("(result)",result);
10767
10768     /* if left is rematerialisable and
10769      * result is not bit variable type and
10770      * the left is pointer to data space i.e
10771      * lower 128 bytes of space */
10772     
10773     if (AOP_TYPE(left) == AOP_PCODE
10774       && !IS_BITFIELD(retype)
10775       && DCL_TYPE(ltype) == POINTER) {
10776
10777         genDataPointerGet (left,result,ic);
10778         pic16_freeAsmop(left, NULL, ic, TRUE);
10779         return ;
10780     }
10781     
10782     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10783     pic16_aopOp (result,ic,TRUE);
10784     
10785     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10786
10787 #if 1
10788     if(IS_BITFIELD( retype )
10789       && (SPEC_BLEN(operandType(result))==1)
10790     ) {
10791       iCode *nextic;
10792       pCodeOp *jop;
10793       int bitstrt, bytestrt;
10794
10795         /* if this is bitfield of size 1, see if we are checking the value
10796          * of a single bit in an if-statement,
10797          * if yes, then don't generate usual code, but execute the
10798          * genIfx directly -- VR */
10799
10800         nextic = ic->next;
10801
10802         /* CHECK: if next iCode is IFX
10803          * and current result operand is nextic's conditional operand
10804          * and current result operand live ranges ends at nextic's key number
10805          */
10806         if((nextic->op == IFX)
10807           && (result == IC_COND(nextic))
10808           && (OP_LIVETO(result) == nextic->seq)
10809           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10810           ) {
10811             /* everything is ok then */
10812             /* find a way to optimize the genIfx iCode */
10813
10814             bytestrt = SPEC_BSTR(operandType(result))/8;
10815             bitstrt = SPEC_BSTR(operandType(result))%8;
10816             
10817             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10818
10819             genIfxpCOpJump(nextic, jop);
10820             
10821             pic16_freeAsmop(left, NULL, ic, TRUE);
10822             pic16_freeAsmop(result, NULL, ic, TRUE);
10823             return;
10824         }
10825     }
10826 #endif
10827
10828     /* if bitfield then unpack the bits */
10829     if (IS_BITFIELD(letype)) 
10830       genUnpackBits (result, left, NULL, POINTER);
10831     else {
10832       /* we have can just get the values */
10833       int size = AOP_SIZE(result);
10834       int offset = 0;   
10835         
10836       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10837
10838       pic16_loadFSR0( left, 0 );
10839
10840       while(size--) {
10841         if(size) {
10842           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10843                 pic16_popGet(AOP(result), offset++)));
10844         } else {
10845           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10846                 pic16_popGet(AOP(result), offset++)));
10847         }
10848       }
10849     }
10850
10851 #if 0
10852     /* now some housekeeping stuff */
10853     if (aop) {
10854       /* we had to allocate for this iCode */
10855       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10856       pic16_freeAsmop(NULL,aop,ic,TRUE);
10857     } else { 
10858       /* we did not allocate which means left
10859        * already in a pointer register, then
10860        * if size > 0 && this could be used again
10861        * we have to point it back to where it 
10862        * belongs */
10863       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10864       if (AOP_SIZE(result) > 1
10865         && !OP_SYMBOL(left)->remat
10866         && ( OP_SYMBOL(left)->liveTo > ic->seq
10867             || ic->depth )) {
10868 //        int size = AOP_SIZE(result) - 1;
10869 //        while (size--)
10870 //          pic16_emitcode("dec","%s",rname);
10871         }
10872     }
10873 #endif
10874
10875     /* done */
10876     pic16_freeAsmop(left,NULL,ic,TRUE);
10877     pic16_freeAsmop(result,NULL,ic,TRUE);
10878 }
10879
10880 /*-----------------------------------------------------------------*/
10881 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10882 /*-----------------------------------------------------------------*/
10883 static void genPagedPointerGet (operand *left, 
10884                                operand *result, 
10885                                iCode *ic)
10886 {
10887     asmop *aop = NULL;
10888     regs *preg = NULL ;
10889     char *rname ;
10890     sym_link *rtype, *retype;    
10891
10892     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10893
10894     rtype = operandType(result);
10895     retype= getSpec(rtype);
10896     
10897     pic16_aopOp(left,ic,FALSE);
10898
10899   /* if the value is already in a pointer register
10900        then don't need anything more */
10901     if (!AOP_INPREG(AOP(left))) {
10902         /* otherwise get a free pointer register */
10903         aop = newAsmop(0);
10904         preg = getFreePtr(ic,&aop,FALSE);
10905         pic16_emitcode("mov","%s,%s",
10906                 preg->name,
10907                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10908         rname = preg->name ;
10909     } else
10910         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10911     
10912     pic16_freeAsmop(left,NULL,ic,TRUE);
10913     pic16_aopOp (result,ic,TRUE);
10914
10915     /* if bitfield then unpack the bits */
10916     if (IS_BITFIELD(retype)) 
10917         genUnpackBits (result,left,rname,PPOINTER);
10918     else {
10919         /* we have can just get the values */
10920         int size = AOP_SIZE(result);
10921         int offset = 0 ;        
10922         
10923         while (size--) {
10924             
10925             pic16_emitcode("movx","a,@%s",rname);
10926             pic16_aopPut(AOP(result),"a",offset);
10927             
10928             offset++ ;
10929             
10930             if (size)
10931                 pic16_emitcode("inc","%s",rname);
10932         }
10933     }
10934
10935     /* now some housekeeping stuff */
10936     if (aop) {
10937         /* we had to allocate for this iCode */
10938         pic16_freeAsmop(NULL,aop,ic,TRUE);
10939     } else { 
10940         /* we did not allocate which means left
10941            already in a pointer register, then
10942            if size > 0 && this could be used again
10943            we have to point it back to where it 
10944            belongs */
10945         if (AOP_SIZE(result) > 1 &&
10946             !OP_SYMBOL(left)->remat &&
10947             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10948               ic->depth )) {
10949             int size = AOP_SIZE(result) - 1;
10950             while (size--)
10951                 pic16_emitcode("dec","%s",rname);
10952         }
10953     }
10954
10955     /* done */
10956     pic16_freeAsmop(result,NULL,ic,TRUE);
10957     
10958         
10959 }
10960
10961 #if 0
10962 /* This code is not adjusted to PIC16 and fails utterly.
10963  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10964
10965 /*-----------------------------------------------------------------*/
10966 /* genFarPointerGet - gget value from far space                    */
10967 /*-----------------------------------------------------------------*/
10968 static void genFarPointerGet (operand *left,
10969                               operand *result, iCode *ic)
10970 {
10971     int size, offset ;
10972     sym_link *retype = getSpec(operandType(result));
10973
10974     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10975
10976     pic16_aopOp(left,ic,FALSE);
10977
10978     /* if the operand is already in dptr 
10979     then we do nothing else we move the value to dptr */
10980     if (AOP_TYPE(left) != AOP_STR) {
10981         /* if this is remateriazable */
10982         if (AOP_TYPE(left) == AOP_IMMD)
10983             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10984         else { /* we need to get it byte by byte */
10985             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10986             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10987             if (options.model == MODEL_FLAT24)
10988             {
10989                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10990             }
10991         }
10992     }
10993     /* so dptr know contains the address */
10994     pic16_freeAsmop(left,NULL,ic,TRUE);
10995     pic16_aopOp(result,ic,TRUE);
10996
10997     /* if bit then unpack */
10998     if (IS_BITFIELD(retype)) 
10999         genUnpackBits(result,left,"dptr",FPOINTER);
11000     else {
11001         size = AOP_SIZE(result);
11002         offset = 0 ;
11003
11004         while (size--) {
11005             pic16_emitcode("movx","a,@dptr");
11006             pic16_aopPut(AOP(result),"a",offset++);
11007             if (size)
11008                 pic16_emitcode("inc","dptr");
11009         }
11010     }
11011
11012     pic16_freeAsmop(result,NULL,ic,TRUE);
11013 }
11014 #endif
11015
11016 #if 0
11017 /*-----------------------------------------------------------------*/
11018 /* genCodePointerGet - get value from code space                  */
11019 /*-----------------------------------------------------------------*/
11020 static void genCodePointerGet (operand *left,
11021                                 operand *result, iCode *ic)
11022 {
11023     int size, offset ;
11024     sym_link *retype = getSpec(operandType(result));
11025
11026     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11027
11028     pic16_aopOp(left,ic,FALSE);
11029
11030     /* if the operand is already in dptr 
11031     then we do nothing else we move the value to dptr */
11032     if (AOP_TYPE(left) != AOP_STR) {
11033         /* if this is remateriazable */
11034         if (AOP_TYPE(left) == AOP_IMMD)
11035             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11036         else { /* we need to get it byte by byte */
11037             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11038             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11039             if (options.model == MODEL_FLAT24)
11040             {
11041                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11042             }
11043         }
11044     }
11045     /* so dptr know contains the address */
11046     pic16_freeAsmop(left,NULL,ic,TRUE);
11047     pic16_aopOp(result,ic,FALSE);
11048
11049     /* if bit then unpack */
11050     if (IS_BITFIELD(retype)) 
11051         genUnpackBits(result,left,"dptr",CPOINTER);
11052     else {
11053         size = AOP_SIZE(result);
11054         offset = 0 ;
11055
11056         while (size--) {
11057             pic16_emitcode("clr","a");
11058             pic16_emitcode("movc","a,@a+dptr");
11059             pic16_aopPut(AOP(result),"a",offset++);
11060             if (size)
11061                 pic16_emitcode("inc","dptr");
11062         }
11063     }
11064
11065     pic16_freeAsmop(result,NULL,ic,TRUE);
11066 }
11067 #endif
11068
11069 #if 0
11070 /*-----------------------------------------------------------------*/
11071 /* genGenPointerGet - gget value from generic pointer space        */
11072 /*-----------------------------------------------------------------*/
11073 static void genGenPointerGet (operand *left,
11074                               operand *result, iCode *ic)
11075 {
11076   int size, offset, lit;
11077   sym_link *retype = getSpec(operandType(result));
11078
11079         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11080         pic16_aopOp(left,ic,FALSE);
11081         pic16_aopOp(result,ic,FALSE);
11082         size = AOP_SIZE(result);
11083
11084         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11085
11086         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11087
11088                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11089                 // load FSR0 from immediate
11090                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11091
11092 //              pic16_loadFSR0( left );
11093
11094                 offset = 0;
11095                 while(size--) {
11096                         if(size) {
11097                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11098                         } else {
11099                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11100                         }
11101                         offset++;
11102                 }
11103                 goto release;
11104
11105         }
11106         else { /* we need to get it byte by byte */
11107                 // set up FSR0 with address from left
11108                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11109                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11110                 
11111                 offset = 0 ;
11112
11113                 while(size--) {
11114                         if(size) {
11115                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11116                         } else {
11117                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11118                         }
11119                         offset++;
11120                 }
11121                 goto release;
11122         }
11123
11124   /* if bit then unpack */
11125         if (IS_BITFIELD(retype)) 
11126                 genUnpackBits(result,left,"BAD",GPOINTER);
11127
11128         release:
11129         pic16_freeAsmop(left,NULL,ic,TRUE);
11130         pic16_freeAsmop(result,NULL,ic,TRUE);
11131
11132 }
11133 #endif
11134
11135
11136 /*-----------------------------------------------------------------*/
11137 /* genGenPointerGet - gget value from generic pointer space        */
11138 /*-----------------------------------------------------------------*/
11139 static void genGenPointerGet (operand *left,
11140                               operand *result, iCode *ic)
11141 {
11142   int size, offset, lit;
11143   sym_link *letype = getSpec(operandType(left));
11144
11145     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11146     pic16_aopOp(left,ic,FALSE);
11147     pic16_aopOp(result,ic,TRUE);
11148     size = AOP_SIZE(result);
11149
11150     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11151   
11152     /* if bit then unpack */
11153     if (IS_BITFIELD(letype)) {
11154       genUnpackBits(result,left,"BAD",GPOINTER);
11155       goto release;
11156     }
11157
11158     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11159
11160       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11161       // load FSR0 from immediate
11162       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11163
11164       werror(W_POSSBUG2, __FILE__, __LINE__);
11165
11166       offset = 0;
11167       while(size--) {
11168         if(size) {
11169           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11170         } else {
11171           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11172         }
11173         offset++;
11174       }
11175
11176       goto release;
11177
11178     } else { /* we need to get it byte by byte */
11179
11180       /* set up WREG:PRODL:FSR0L with address from left */
11181       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11182       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11183       pic16_mov2w(AOP(left), 2);
11184       pic16_callGenericPointerRW(0, size);
11185       
11186       assignResultValue(result, 1);
11187       
11188       goto release;
11189     }
11190
11191 release:
11192   pic16_freeAsmop(left,NULL,ic,TRUE);
11193   pic16_freeAsmop(result,NULL,ic,TRUE);
11194 }
11195
11196 /*-----------------------------------------------------------------*/
11197 /* genConstPointerGet - get value from const generic pointer space */
11198 /*-----------------------------------------------------------------*/
11199 static void genConstPointerGet (operand *left,
11200                                 operand *result, iCode *ic)
11201 {
11202   //sym_link *retype = getSpec(operandType(result));
11203   // symbol *albl = newiTempLabel(NULL);        // patch 15
11204   // symbol *blbl = newiTempLabel(NULL);        //
11205   // PIC_OPCODE poc;                            // patch 15
11206   int size;
11207   int offset = 0;
11208
11209   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11210   pic16_aopOp(left,ic,FALSE);
11211   pic16_aopOp(result,ic,TRUE);
11212   size = AOP_SIZE(result);
11213
11214   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11215
11216   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11217
11218   // set up table pointer
11219   if( (AOP_TYPE(left) == AOP_PCODE) 
11220       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11221           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11222     {
11223       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11224       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11225       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11226       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11227       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11228       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11229   } else {
11230     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11231     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11232     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11233   }
11234
11235   while(size--) {
11236     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11237     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11238     offset++;
11239   }
11240     
11241   pic16_freeAsmop(left,NULL,ic,TRUE);
11242   pic16_freeAsmop(result,NULL,ic,TRUE);
11243 }
11244
11245
11246 /*-----------------------------------------------------------------*/
11247 /* genPointerGet - generate code for pointer get                   */
11248 /*-----------------------------------------------------------------*/
11249 static void genPointerGet (iCode *ic)
11250 {
11251   operand *left, *result ;
11252   sym_link *type, *etype;
11253   int p_type;
11254
11255     FENTRY;
11256     
11257     left = IC_LEFT(ic);
11258     result = IC_RESULT(ic) ;
11259
11260     /* depending on the type of pointer we need to
11261     move it to the correct pointer register */
11262     type = operandType(left);
11263     etype = getSpec(type);
11264
11265 #if 0
11266     if (IS_PTR_CONST(type))
11267 #else
11268     if (IS_CODEPTR(type))
11269 #endif
11270       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11271
11272     /* if left is of type of pointer then it is simple */
11273     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11274       p_type = DCL_TYPE(type);
11275     else {
11276       /* we have to go by the storage class */
11277       p_type = PTR_TYPE(SPEC_OCLS(etype));
11278
11279       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11280
11281       if (SPEC_OCLS(etype)->codesp ) {
11282         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11283         //p_type = CPOINTER ;   
11284       } else
11285       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11286         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11287         /*p_type = FPOINTER ;*/ 
11288       } else
11289       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11290         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11291         /* p_type = PPOINTER; */
11292       } else
11293       if (SPEC_OCLS(etype) == idata ) {
11294         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11295         /* p_type = IPOINTER; */
11296       } else {
11297         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11298         /* p_type = POINTER ; */
11299       }
11300     }
11301
11302     /* now that we have the pointer type we assign
11303     the pointer values */
11304     switch (p_type) {
11305       case POINTER:     
11306       case FPOINTER:
11307       case IPOINTER:
11308         genNearPointerGet (left,result,ic);
11309         break;
11310
11311       case PPOINTER:
11312         genPagedPointerGet(left,result,ic);
11313         break;
11314
11315 #if 0
11316       /* PICs do not support FAR pointers... */
11317       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11318       case FPOINTER:
11319         genFarPointerGet (left,result,ic);
11320         break;
11321 #endif
11322
11323       case CPOINTER:
11324         genConstPointerGet (left,result,ic);
11325         //pic16_emitcodePointerGet (left,result,ic);
11326         break;
11327
11328       case GPOINTER:
11329 #if 0
11330       if (IS_PTR_CONST(type))
11331         genConstPointerGet (left,result,ic);
11332       else
11333 #endif
11334         genGenPointerGet (left,result,ic);
11335       break;
11336
11337     default:
11338       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11339               "genPointerGet: illegal pointer type");
11340     
11341     }
11342 }
11343
11344 /*-----------------------------------------------------------------*/
11345 /* genPackBits - generates code for packed bit storage             */
11346 /*-----------------------------------------------------------------*/
11347 static void genPackBits (sym_link    *etype , operand *result,
11348                          operand *right ,
11349                          char *rname, int p_type)
11350 {
11351   int shCnt = 0 ;
11352   int offset = 0  ;
11353   int rLen = 0 ;
11354   int blen, bstr ;   
11355   int shifted_and_masked = 0;
11356   unsigned long lit = (unsigned long)-1;
11357   sym_link *retype;
11358
11359   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11360   blen = SPEC_BLEN(etype);
11361   bstr = SPEC_BSTR(etype);
11362
11363   retype = getSpec(operandType(right));
11364
11365   if(AOP_TYPE(right) == AOP_LIT) {
11366     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11367     
11368     if((blen == 1) && (bstr < 8)) {
11369       /* it is a single bit, so use the appropriate bit instructions */
11370
11371       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11372
11373       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11374         /* workaround to reduce the extra lfsr instruction */
11375         if(lit) {
11376           pic16_emitpcode(POC_BSF,
11377               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11378         } else {
11379           pic16_emitpcode(POC_BCF,
11380               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11381         }
11382       } else {
11383         if (PIC_IS_DATA_PTR(operandType(result))) {
11384           pic16_loadFSR0(result, 0);
11385           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11386               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11387         } else {
11388           /* get old value */
11389           pic16_derefPtr (result, p_type, 0, NULL);
11390           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11391               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11392           /* write back new value */
11393           pic16_derefPtr (result, p_type, 1, NULL);
11394         }
11395       }
11396
11397       return;
11398     }
11399     /* IORLW below is more efficient */
11400     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11401     lit = (lit & ((1UL << blen) - 1)) << bstr;
11402     shifted_and_masked = 1;
11403     offset++;
11404   } else
11405     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11406         && IS_BITFIELD(retype) 
11407         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11408         && (blen == 1)) {
11409       int rblen, rbstr;
11410
11411       rblen = SPEC_BLEN( retype );
11412       rbstr = SPEC_BSTR( retype );
11413
11414       if(IS_BITFIELD(etype)) {
11415         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11416         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11417       } else {
11418         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11419       }
11420
11421       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11422
11423       if(IS_BITFIELD(etype)) {
11424         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11425       } else {
11426         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11427       }
11428
11429       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11430
11431       return;
11432     } else {
11433       /* move right to W */
11434       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11435     }
11436
11437   /* if the bit length is less than or   */
11438   /* it exactly fits a byte then         */
11439   if((shCnt=SPEC_BSTR(etype))
11440       || SPEC_BLEN(etype) <= 8 )  {
11441     int fsr0_setup = 0;
11442
11443     if (blen != 8 || bstr != 0) {
11444       // we need to combine the value with the old value
11445       if(!shifted_and_masked)
11446       {
11447         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11448
11449         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11450             SPEC_BSTR(etype), SPEC_BLEN(etype));
11451
11452         /* shift left acc, do NOT mask the result again */
11453         AccLsh(shCnt, 0);
11454
11455         /* using PRODH as a temporary register here */
11456         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11457       }
11458
11459       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11460         || IS_DIRECT(result)) {
11461         /* access symbol directly */
11462         pic16_mov2w (AOP(result), 0);
11463       } else {
11464         /* get old value */
11465         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11466       }
11467 #if 1
11468       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11469             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11470                             (unsigned char)(0xff >> (8-bstr))) ));
11471       if (!shifted_and_masked) {
11472         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11473       } else {
11474         /* We have the shifted and masked (literal) right value in `lit' */
11475         if (lit != 0)
11476           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11477       }
11478     } // if (blen != 8 || bstr != 0)
11479
11480     /* write new value back */
11481     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11482         || IS_DIRECT(result)) {
11483       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11484     } else {
11485       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11486     }
11487 #endif
11488
11489     return;
11490   }
11491
11492
11493 #if 0
11494   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11495   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11496   exit(-1);
11497 #endif
11498
11499
11500   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11501   rLen = SPEC_BLEN(etype)-8;
11502
11503   /* now generate for lengths greater than one byte */
11504   while (1) {
11505     rLen -= 8 ;
11506     if (rLen <= 0 ) {
11507       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11508       break ;
11509     }
11510
11511     switch (p_type) {
11512       case POINTER:
11513         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11514         break;
11515
11516         /*
11517            case FPOINTER:
11518            MOVA(l);
11519            pic16_emitcode("movx","@dptr,a");
11520            break;
11521
11522            case GPOINTER:
11523            MOVA(l);
11524            DEBUGpic16_emitcode(";lcall","__gptrput");
11525            break;  
11526          */
11527       default:
11528         assert(0);
11529     }   
11530
11531
11532     pic16_mov2w(AOP(right), offset++);
11533   }
11534
11535   /* last last was not complete */
11536   if (rLen)   {
11537     /* save the byte & read byte */
11538     switch (p_type) {
11539       case POINTER:
11540         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11541         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11542         break;
11543
11544         /*
11545            case FPOINTER:
11546            pic16_emitcode ("mov","b,a");
11547            pic16_emitcode("movx","a,@dptr");
11548            break;
11549
11550            case GPOINTER:
11551            pic16_emitcode ("push","b");
11552            pic16_emitcode ("push","acc");
11553            pic16_emitcode ("lcall","__gptrget");
11554            pic16_emitcode ("pop","b");
11555            break;
11556          */
11557       default:
11558         assert(0);
11559     }
11560     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11561     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11562     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11563     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11564     //        pic16_emitcode ("orl","a,b");
11565   }
11566
11567   //    if (p_type == GPOINTER)
11568   //        pic16_emitcode("pop","b");
11569
11570   switch (p_type) {
11571
11572     case POINTER:
11573       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11574       //        pic16_emitcode("mov","@%s,a",rname);
11575       break;
11576       /*
11577          case FPOINTER:
11578          pic16_emitcode("movx","@dptr,a");
11579          break;
11580
11581          case GPOINTER:
11582          DEBUGpic16_emitcode(";lcall","__gptrput");
11583          break;                 
11584        */
11585     default:
11586       assert(0);
11587   }
11588
11589   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11590 }
11591
11592 /*-----------------------------------------------------------------*/
11593 /* genDataPointerSet - remat pointer to data space                 */
11594 /*-----------------------------------------------------------------*/
11595 static void genDataPointerSet(operand *right,
11596                               operand *result,
11597                               iCode *ic)
11598 {
11599   int size, offset = 0, resoffset=0 ;
11600
11601     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11602     pic16_aopOp(right,ic,FALSE);
11603
11604     size = AOP_SIZE(right);
11605
11606 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11607
11608 #if 0
11609     if ( AOP_TYPE(result) == AOP_PCODE) {
11610       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11611               AOP(result)->aopu.pcop->name,
11612                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11613               PCOR(AOP(result)->aopu.pcop)->instance:
11614               PCOI(AOP(result)->aopu.pcop)->offset);
11615     }
11616 #endif
11617
11618     if(AOP(result)->aopu.pcop->type == PO_DIR)
11619       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11620
11621     while (size--) {
11622       if (AOP_TYPE(right) == AOP_LIT) {
11623         unsigned int lit;
11624
11625           if(!IS_FLOAT(operandType( right )))
11626             lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11627           else {
11628             union {
11629               unsigned long lit_int;
11630               float lit_float;
11631             } info;
11632         
11633               /* take care if literal is a float */
11634               info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11635               lit = info.lit_int;
11636           }
11637                     lit = lit >> (8*offset);
11638                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11639                 } else {
11640                   pic16_mov2w(AOP(right), offset);
11641                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11642                 }
11643                 offset++;
11644                 resoffset++;
11645         }
11646
11647     pic16_freeAsmop(right,NULL,ic,TRUE);
11648 }
11649
11650
11651
11652 /*-----------------------------------------------------------------*/
11653 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11654 /*-----------------------------------------------------------------*/
11655 static void genNearPointerSet (operand *right,
11656                                operand *result, 
11657                                iCode *ic)
11658 {
11659   asmop *aop = NULL;
11660   sym_link *retype;
11661   sym_link *ptype = operandType(result);
11662   sym_link *resetype;
11663     
11664     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11665     retype= getSpec(operandType(right));
11666     resetype = getSpec(operandType(result));
11667   
11668     pic16_aopOp(result,ic,FALSE);
11669     
11670     /* if the result is rematerializable &
11671      * in data space & not a bit variable */
11672         
11673     /* and result is not a bit variable */
11674     if (AOP_TYPE(result) == AOP_PCODE
11675 //      && AOP_TYPE(result) == AOP_IMMD
11676       && DCL_TYPE(ptype) == POINTER
11677       && !IS_BITFIELD(retype)
11678       && !IS_BITFIELD(resetype)) {
11679
11680         genDataPointerSet (right,result,ic);
11681         pic16_freeAsmop(result,NULL,ic,TRUE);
11682       return;
11683     }
11684
11685     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11686     pic16_aopOp(right,ic,FALSE);
11687     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11688
11689     /* if bitfield then unpack the bits */
11690     if (IS_BITFIELD(resetype)) {
11691       genPackBits (resetype, result, right, NULL, POINTER);
11692     } else {
11693       /* we have can just get the values */
11694       int size = AOP_SIZE(right);
11695       int offset = 0 ;    
11696
11697         pic16_loadFSR0(result, 0);
11698             
11699         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11700         while (size--) {
11701           if (AOP_TYPE(right) == AOP_LIT) {
11702             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11703             if (size) {
11704               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11705             } else {
11706               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11707             }
11708           } else { // no literal
11709             if(size) {
11710               pic16_emitpcode(POC_MOVFF,
11711                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11712                   pic16_popCopyReg(&pic16_pc_postinc0)));
11713             } else {
11714               pic16_emitpcode(POC_MOVFF,
11715                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11716                   pic16_popCopyReg(&pic16_pc_indf0)));
11717             }
11718           }
11719           
11720           offset++;
11721         }
11722     }
11723
11724     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11725     /* now some housekeeping stuff */
11726     if (aop) {
11727       /* we had to allocate for this iCode */
11728       pic16_freeAsmop(NULL,aop,ic,TRUE);
11729     } else { 
11730       /* we did not allocate which means left
11731        * already in a pointer register, then
11732        * if size > 0 && this could be used again
11733        * we have to point it back to where it 
11734        * belongs */
11735       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11736       if (AOP_SIZE(right) > 1
11737         && !OP_SYMBOL(result)->remat
11738         && ( OP_SYMBOL(result)->liveTo > ic->seq
11739         || ic->depth )) {
11740
11741           int size = AOP_SIZE(right) - 1;
11742
11743             while (size--)
11744               pic16_emitcode("decf","fsr0,f");
11745               //pic16_emitcode("dec","%s",rname);
11746       }
11747     }
11748
11749     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11750     /* done */
11751 //release:
11752     pic16_freeAsmop(right,NULL,ic,TRUE);
11753     pic16_freeAsmop(result,NULL,ic,TRUE);
11754 }
11755
11756 /*-----------------------------------------------------------------*/
11757 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11758 /*-----------------------------------------------------------------*/
11759 static void genPagedPointerSet (operand *right,
11760                                operand *result, 
11761                                iCode *ic)
11762 {
11763     asmop *aop = NULL;
11764     regs *preg = NULL ;
11765     char *rname , *l;
11766     sym_link *retype;
11767        
11768     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11769
11770     retype= getSpec(operandType(right));
11771     
11772     pic16_aopOp(result,ic,FALSE);
11773     
11774     /* if the value is already in a pointer register
11775        then don't need anything more */
11776     if (!AOP_INPREG(AOP(result))) {
11777         /* otherwise get a free pointer register */
11778         aop = newAsmop(0);
11779         preg = getFreePtr(ic,&aop,FALSE);
11780         pic16_emitcode("mov","%s,%s",
11781                 preg->name,
11782                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11783         rname = preg->name ;
11784     } else
11785         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11786     
11787     pic16_freeAsmop(result,NULL,ic,TRUE);
11788     pic16_aopOp (right,ic,FALSE);
11789
11790     /* if bitfield then unpack the bits */
11791     if (IS_BITFIELD(retype)) 
11792         genPackBits (retype,result,right,rname,PPOINTER);
11793     else {
11794         /* we have can just get the values */
11795         int size = AOP_SIZE(right);
11796         int offset = 0 ;        
11797         
11798         while (size--) {
11799             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11800             
11801             MOVA(l);
11802             pic16_emitcode("movx","@%s,a",rname);
11803
11804             if (size)
11805                 pic16_emitcode("inc","%s",rname);
11806
11807             offset++;
11808         }
11809     }
11810     
11811     /* now some housekeeping stuff */
11812     if (aop) {
11813         /* we had to allocate for this iCode */
11814         pic16_freeAsmop(NULL,aop,ic,TRUE);
11815     } else { 
11816         /* we did not allocate which means left
11817            already in a pointer register, then
11818            if size > 0 && this could be used again
11819            we have to point it back to where it 
11820            belongs */
11821         if (AOP_SIZE(right) > 1 &&
11822             !OP_SYMBOL(result)->remat &&
11823             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11824               ic->depth )) {
11825             int size = AOP_SIZE(right) - 1;
11826             while (size--)
11827                 pic16_emitcode("dec","%s",rname);
11828         }
11829     }
11830
11831     /* done */
11832     pic16_freeAsmop(right,NULL,ic,TRUE);
11833     
11834         
11835 }
11836
11837 #if 0
11838 /* This code is not adjusted to PIC16 and fails utterly...
11839  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11840
11841 /*-----------------------------------------------------------------*/
11842 /* genFarPointerSet - set value from far space                     */
11843 /*-----------------------------------------------------------------*/
11844 static void genFarPointerSet (operand *right,
11845                               operand *result, iCode *ic)
11846 {
11847     int size, offset ;
11848     sym_link *retype = getSpec(operandType(right));
11849
11850     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11851     pic16_aopOp(result,ic,FALSE);
11852
11853     /* if the operand is already in dptr 
11854     then we do nothing else we move the value to dptr */
11855     if (AOP_TYPE(result) != AOP_STR) {
11856         /* if this is remateriazable */
11857         if (AOP_TYPE(result) == AOP_IMMD)
11858             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11859         else { /* we need to get it byte by byte */
11860             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11861             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11862             if (options.model == MODEL_FLAT24)
11863             {
11864                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11865             }
11866         }
11867     }
11868     /* so dptr know contains the address */
11869     pic16_freeAsmop(result,NULL,ic,TRUE);
11870     pic16_aopOp(right,ic,FALSE);
11871
11872     /* if bit then unpack */
11873     if (IS_BITFIELD(retype)) 
11874         genPackBits(retype,result,right,"dptr",FPOINTER);
11875     else {
11876         size = AOP_SIZE(right);
11877         offset = 0 ;
11878
11879         while (size--) {
11880             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11881             MOVA(l);
11882             pic16_emitcode("movx","@dptr,a");
11883             if (size)
11884                 pic16_emitcode("inc","dptr");
11885         }
11886     }
11887
11888     pic16_freeAsmop(right,NULL,ic,TRUE);
11889 }
11890 #endif
11891
11892 /*-----------------------------------------------------------------*/
11893 /* genGenPointerSet - set value from generic pointer space         */
11894 /*-----------------------------------------------------------------*/
11895 #if 0
11896 static void genGenPointerSet (operand *right,
11897                               operand *result, iCode *ic)
11898 {
11899         int i, size, offset, lit;
11900         sym_link *retype = getSpec(operandType(right));
11901
11902         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11903
11904         pic16_aopOp(result,ic,FALSE);
11905         pic16_aopOp(right,ic,FALSE);
11906         size = AOP_SIZE(right);
11907         offset = 0;
11908
11909         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11910
11911         /* if the operand is already in dptr 
11912                 then we do nothing else we move the value to dptr */
11913         if (AOP_TYPE(result) != AOP_STR) {
11914                 /* if this is remateriazable */
11915                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11916                 // WARNING: anythig until "else" is untested!
11917                 if (AOP_TYPE(result) == AOP_IMMD) {
11918                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11919                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11920                         // load FSR0 from immediate
11921                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11922                         offset = 0;
11923                         while(size--) {
11924                                 if(size) {
11925                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11926                                 } else {
11927                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11928                                 }
11929                                 offset++;
11930                         }
11931                         goto release;
11932                 }
11933                 else { /* we need to get it byte by byte */
11934                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11935                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11936
11937                         // set up FSR0 with address of result
11938                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11939                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11940
11941                         /* hack hack! see if this the FSR. If so don't load W */
11942                         if(AOP_TYPE(right) != AOP_ACC) {
11943
11944                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11945
11946                                 if(AOP_TYPE(right) == AOP_LIT)
11947                                 {
11948                                         // copy literal
11949                                         // note: pic16_popGet handles sign extension
11950                                         for(i=0;i<size;i++) {
11951                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11952                                                 if(i < size-1)
11953                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11954                                                 else
11955                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11956                                         }
11957                                 } else {
11958                                         // copy regs
11959
11960                                         for(i=0;i<size;i++) {
11961                                                 if(i < size-1)
11962                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11963                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11964                                                 else
11965                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11966                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11967                                         }
11968                                 }
11969                                 goto release;
11970                         } 
11971                         // right = ACC
11972                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11973                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11974                         goto release;
11975         } // if (AOP_TYPE(result) != AOP_IMMD)
11976
11977         } // if (AOP_TYPE(result) != AOP_STR)
11978         /* so dptr know contains the address */
11979
11980
11981         /* if bit then unpack */
11982         if (IS_BITFIELD(retype)) 
11983                 genPackBits(retype,result,right,"dptr",GPOINTER);
11984         else {
11985                 size = AOP_SIZE(right);
11986                 offset = 0 ;
11987
11988                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11989
11990                 // set up FSR0 with address of result
11991                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11992                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11993         
11994                 while (size--) {
11995                         if (AOP_TYPE(right) == AOP_LIT) {
11996                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11997                                 if (size) {
11998                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11999                                 } else {
12000                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12001                                 }
12002                         } else { // no literal
12003                                 if(size) {
12004                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12005                                 } else {
12006                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12007                                 }
12008                         }
12009                         offset++;
12010                 }
12011         }
12012
12013         release:
12014         pic16_freeAsmop(right,NULL,ic,TRUE);
12015         pic16_freeAsmop(result,NULL,ic,TRUE);
12016 }
12017 #endif
12018
12019 static void genGenPointerSet (operand *right,
12020                               operand *result, iCode *ic)
12021 {
12022   int size;
12023   sym_link *retype = getSpec(operandType(result));
12024
12025     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12026
12027     pic16_aopOp(result,ic,FALSE);
12028     pic16_aopOp(right,ic,FALSE);
12029     size = AOP_SIZE(right);
12030
12031     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12032
12033
12034     /* if bit then unpack */
12035     if (IS_BITFIELD(retype)) {
12036 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12037       genPackBits(retype,result,right,"dptr",GPOINTER);
12038       goto release;
12039     }
12040
12041     size = AOP_SIZE(right);
12042
12043     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12044
12045
12046     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12047
12048     /* value of right+0 is placed on stack, which will be retrieved
12049      * by the support function thus restoring the stack. The important
12050      * thing is that there is no need to manually restore stack pointer
12051      * here */
12052     pushaop(AOP(right), 0);
12053 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12054     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12055     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12056     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12057     
12058     /* load address to write to in WREG:FSR0H:FSR0L */
12059     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12060                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12061     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12062                                 pic16_popCopyReg(&pic16_pc_prodl)));
12063     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12064     
12065     pic16_callGenericPointerRW(1, size);
12066
12067 release:
12068     pic16_freeAsmop(right,NULL,ic,TRUE);
12069     pic16_freeAsmop(result,NULL,ic,TRUE);
12070 }
12071
12072 /*-----------------------------------------------------------------*/
12073 /* genPointerSet - stores the value into a pointer location        */
12074 /*-----------------------------------------------------------------*/
12075 static void genPointerSet (iCode *ic)
12076 {    
12077   operand *right, *result ;
12078   sym_link *type, *etype;
12079   int p_type;
12080
12081     FENTRY;
12082
12083     right = IC_RIGHT(ic);
12084     result = IC_RESULT(ic) ;
12085
12086     /* depending on the type of pointer we need to
12087     move it to the correct pointer register */
12088     type = operandType(result);
12089     etype = getSpec(type);
12090     
12091     /* if left is of type of pointer then it is simple */
12092     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12093         p_type = DCL_TYPE(type);
12094     }
12095     else {
12096         /* we have to go by the storage class */
12097         p_type = PTR_TYPE(SPEC_OCLS(etype));
12098
12099 /*      if (SPEC_OCLS(etype)->codesp ) { */
12100 /*          p_type = CPOINTER ;  */
12101 /*      } */
12102 /*      else */
12103 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12104 /*              p_type = FPOINTER ; */
12105 /*          else */
12106 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12107 /*                  p_type = PPOINTER ; */
12108 /*              else */
12109 /*                  if (SPEC_OCLS(etype) == idata ) */
12110 /*                      p_type = IPOINTER ; */
12111 /*                  else */
12112 /*                      p_type = POINTER ; */
12113     }
12114
12115     /* now that we have the pointer type we assign
12116     the pointer values */
12117     switch (p_type) {
12118       case POINTER:
12119       case FPOINTER:
12120       case IPOINTER:
12121         genNearPointerSet (right,result,ic);
12122         break;
12123
12124       case PPOINTER:
12125         genPagedPointerSet (right,result,ic);
12126         break;
12127
12128 #if 0
12129       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12130       case FPOINTER:
12131         genFarPointerSet (right,result,ic);
12132         break;
12133 #endif
12134         
12135       case GPOINTER:
12136         genGenPointerSet (right,result,ic);
12137         break;
12138
12139       default:
12140         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12141           "genPointerSet: illegal pointer type");
12142     }
12143 }
12144
12145 /*-----------------------------------------------------------------*/
12146 /* genIfx - generate code for Ifx statement                        */
12147 /*-----------------------------------------------------------------*/
12148 static void genIfx (iCode *ic, iCode *popIc)
12149 {
12150   operand *cond = IC_COND(ic);
12151   int isbit =0;
12152
12153     FENTRY;
12154
12155     pic16_aopOp(cond,ic,FALSE);
12156
12157     /* get the value into acc */
12158     if (AOP_TYPE(cond) != AOP_CRY)
12159       pic16_toBoolean(cond);
12160     else
12161       isbit = 1;
12162     /* the result is now in the accumulator */
12163     pic16_freeAsmop(cond,NULL,ic,TRUE);
12164
12165     /* if there was something to be popped then do it */
12166     if (popIc)
12167       genIpop(popIc);
12168
12169     /* if the condition is  a bit variable */
12170     if (isbit && IS_ITEMP(cond) && 
12171         SPIL_LOC(cond)) {
12172       genIfxJump(ic,"c");
12173       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12174     } else {
12175       if (isbit && !IS_ITEMP(cond))
12176         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12177         else
12178         genIfxJump(ic,"a");
12179     }
12180     ic->generated = 1;
12181 }
12182
12183 /*-----------------------------------------------------------------*/
12184 /* genAddrOf - generates code for address of                       */
12185 /*-----------------------------------------------------------------*/
12186 static void genAddrOf (iCode *ic)
12187 {
12188   operand *result, *left;
12189   int size;
12190   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12191   pCodeOp *pcop0, *pcop1, *pcop2;
12192
12193     FENTRY;
12194
12195     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12196
12197     sym = OP_SYMBOL( IC_LEFT(ic) );
12198     
12199     if(sym->onStack) {
12200       /* get address of symbol on stack */
12201       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12202 #if 0
12203       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12204                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12205 #endif
12206
12207       // operands on stack are accessible via "FSR2 + index" with index
12208       // starting at 2 for arguments and growing from 0 downwards for
12209       // local variables (index == 0 is not assigned so we add one here)
12210       {
12211         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12212
12213           if (soffs <= 0) {
12214             assert (soffs < 0);
12215             soffs++;
12216           } // if
12217
12218           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12219           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12220           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12221           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12222           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12223           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12224           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12225       }
12226
12227       goto release;
12228     }
12229         
12230 //      if(pic16_debug_verbose) {
12231 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12232 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12233 //      }
12234         
12235     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12236     size = AOP_SIZE(IC_RESULT(ic));
12237
12238     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12239     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12240     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12241         
12242     if (size == 3) {
12243       pic16_emitpcode(POC_MOVLW, pcop0);
12244       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12245       pic16_emitpcode(POC_MOVLW, pcop1);
12246       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12247       pic16_emitpcode(POC_MOVLW, pcop2);
12248       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12249     } else
12250     if (size == 2) {
12251       pic16_emitpcode(POC_MOVLW, pcop0);
12252       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12253       pic16_emitpcode(POC_MOVLW, pcop1);
12254     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12255     } else {
12256       pic16_emitpcode(POC_MOVLW, pcop0);
12257       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12258     }
12259
12260     pic16_freeAsmop(left, NULL, ic, FALSE);
12261 release:
12262     pic16_freeAsmop(result,NULL,ic,TRUE);
12263 }
12264
12265
12266 #if 0
12267 /*-----------------------------------------------------------------*/
12268 /* genFarFarAssign - assignment when both are in far space         */
12269 /*-----------------------------------------------------------------*/
12270 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12271 {
12272     int size = AOP_SIZE(right);
12273     int offset = 0;
12274     char *l ;
12275     /* first push the right side on to the stack */
12276     while (size--) {
12277         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12278         MOVA(l);
12279         pic16_emitcode ("push","acc");
12280     }
12281     
12282     pic16_freeAsmop(right,NULL,ic,FALSE);
12283     /* now assign DPTR to result */
12284     pic16_aopOp(result,ic,FALSE);
12285     size = AOP_SIZE(result);
12286     while (size--) {
12287         pic16_emitcode ("pop","acc");
12288         pic16_aopPut(AOP(result),"a",--offset);
12289     }
12290     pic16_freeAsmop(result,NULL,ic,FALSE);
12291         
12292 }
12293 #endif
12294
12295 /*-----------------------------------------------------------------*/
12296 /* genAssign - generate code for assignment                        */
12297 /*-----------------------------------------------------------------*/
12298 static void genAssign (iCode *ic)
12299 {
12300   operand *result, *right;
12301   sym_link *restype, *rtype;
12302   int size, offset,know_W;
12303   unsigned long lit = 0L;
12304
12305     result = IC_RESULT(ic);
12306     right  = IC_RIGHT(ic) ;
12307
12308     FENTRY;
12309   
12310     /* if they are the same */
12311     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12312       return ;
12313
12314     /* reversed order operands are aopOp'ed so that result operand
12315      * is effective in case right is a stack symbol. This maneauver
12316      * allows to use the _G.resDirect flag later */
12317      pic16_aopOp(result,ic,TRUE);
12318     pic16_aopOp(right,ic,FALSE);
12319
12320     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12321
12322     /* if they are the same registers */
12323     if (pic16_sameRegs(AOP(right),AOP(result)))
12324       goto release;
12325
12326     /* if the result is a bit */
12327     if (AOP_TYPE(result) == AOP_CRY) {
12328       /* if the right size is a literal then
12329          we know what the value is */
12330       if (AOP_TYPE(right) == AOP_LIT) {
12331           
12332         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12333             pic16_popGet(AOP(result),0));
12334
12335         if (((int) operandLitValue(right))) 
12336           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12337               AOP(result)->aopu.aop_dir,
12338               AOP(result)->aopu.aop_dir);
12339         else
12340           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12341               AOP(result)->aopu.aop_dir,
12342               AOP(result)->aopu.aop_dir);
12343         
12344         goto release;
12345       }
12346
12347       /* the right is also a bit variable */
12348       if (AOP_TYPE(right) == AOP_CRY) {
12349         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12350         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12351         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12352
12353         goto release ;
12354       }
12355
12356       /* we need to or */
12357       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12358       pic16_toBoolean(right);
12359       emitSKPZ;
12360       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12361       //pic16_aopPut(AOP(result),"a",0);
12362       goto release ;
12363     }
12364
12365     /* bit variables done */
12366     /* general case */
12367     size = AOP_SIZE(result);
12368     offset = 0 ;
12369
12370   /* bit variables done */
12371   /* general case */
12372   size = AOP_SIZE(result);
12373   restype = operandType(result);
12374   rtype = operandType(right);
12375   offset = 0 ;
12376
12377   if(AOP_TYPE(right) == AOP_LIT) {
12378     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12379     {
12380       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12381
12382       /* patch tag for literals that are cast to pointers */
12383       if (IS_CODEPTR(restype)) {
12384         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12385         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12386       } else {
12387         if (IS_GENPTR(restype))
12388         {
12389           if (IS_CODEPTR(rtype)) {
12390             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12391             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12392           } else if (PIC_IS_DATA_PTR(rtype)) {
12393             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12394             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12395           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12396             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12397           } else if (IS_PTR(rtype)) {
12398             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12399             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12400           }
12401         }
12402       }
12403     } else {
12404       union {
12405         unsigned long lit_int;
12406         float lit_float;
12407       } info;
12408
12409
12410       if(IS_FIXED16X16(operandType(right))) {
12411         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12412       } else {
12413         /* take care if literal is a float */
12414         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12415         lit = info.lit_int;
12416       }
12417     }
12418   }
12419
12420 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12421 //                      sizeof(unsigned long int), sizeof(float));
12422
12423
12424     if (AOP_TYPE(right) == AOP_REG) {
12425       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12426       while (size--) {
12427         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12428       } // while
12429       goto release;
12430     }
12431
12432     /* when do we have to read the program memory?
12433      * - if right itself is a symbol in code space
12434      *   (we don't care what it points to if it's a pointer)
12435      * - AND right is not a function (we would want its address)
12436      */
12437     if(AOP_TYPE(right) != AOP_LIT
12438       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12439       && !IS_FUNC(OP_SYM_TYPE(right))
12440       && !IS_ITEMP(right)) {
12441
12442       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12443       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12444       
12445       // set up table pointer
12446       if(is_LitOp(right)) {
12447 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12448         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12449         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12450         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12451         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12452         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12453         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12454       } else {
12455 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12456         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12457             pic16_popCopyReg(&pic16_pc_tblptrl)));
12458         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12459             pic16_popCopyReg(&pic16_pc_tblptrh)));
12460         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12461             pic16_popCopyReg(&pic16_pc_tblptru)));
12462       }
12463
12464       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12465       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12466       while(size--) {
12467         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12468         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12469             pic16_popGet(AOP(result),offset)));
12470         offset++;
12471       }
12472
12473       /* FIXME: for pointers we need to extend differently (according
12474        * to pointer type DATA/CODE/EEPROM/... :*/
12475       size = getSize(OP_SYM_TYPE(right));
12476       if(AOP_SIZE(result) > size) {
12477         size = AOP_SIZE(result) - size;
12478         while(size--) {
12479           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12480           offset++;
12481         }
12482       }
12483       goto release;
12484     }
12485
12486 #if 0
12487     /* VR - What is this?! */
12488     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12489       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12490       
12491       if(aopIdx(AOP(result),0) == 4) {
12492         /* this is a workaround to save value of right into wreg too,
12493          * value of wreg is going to be used later */
12494         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12495         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12496         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12497         goto release;
12498       } else
12499 //      assert(0);
12500       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12501     }
12502 #endif
12503
12504   know_W=-1;
12505   while (size--) {
12506     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12507     if(AOP_TYPE(right) == AOP_LIT) {
12508       if(lit&0xff) {
12509         if(know_W != (lit&0xff))
12510           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12511         know_W = lit&0xff;
12512         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12513       } else
12514         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12515
12516       lit >>= 8;
12517
12518     } else if (AOP_TYPE(right) == AOP_CRY) {
12519       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12520       if(offset == 0) {
12521         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12522         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12523         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12524       }
12525     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12526         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12527         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12528     } else {
12529       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12530
12531       if(!_G.resDirect) {                                               /* use this aopForSym feature */
12532           if(AOP_TYPE(result) == AOP_ACC) {
12533             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12534           } else
12535           if(AOP_TYPE(right) == AOP_ACC) {
12536             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12537           } else {
12538             pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12539           }
12540       }
12541     }
12542       
12543       offset++;
12544     }
12545   
12546 release:
12547   pic16_freeAsmop (right,NULL,ic,FALSE);
12548   pic16_freeAsmop (result,NULL,ic,TRUE);
12549
12550
12551 /*-----------------------------------------------------------------*/
12552 /* genJumpTab - generates code for jump table                       */
12553 /*-----------------------------------------------------------------*/
12554 static void genJumpTab (iCode *ic)
12555 {
12556   symbol *jtab;
12557   char *l;
12558   pCodeOp *jt_offs;
12559   pCodeOp *jt_offs_hi;
12560   pCodeOp *jt_label;
12561
12562     FENTRY;
12563
12564     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12565     /* get the condition into accumulator */
12566     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12567     MOVA(l);
12568     /* multiply by three */
12569     pic16_emitcode("add","a,acc");
12570     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12571
12572     jtab = newiTempLabel(NULL);
12573     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12574     pic16_emitcode("jmp","@a+dptr");
12575     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12576
12577 #if 0
12578     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12579     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12580     emitSKPNC;
12581     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12582     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12583     pic16_emitpLabel(jtab->key);
12584
12585 #else
12586
12587     jt_offs = pic16_popGetTempReg(0);
12588     jt_offs_hi = pic16_popGetTempReg(1);
12589     jt_label = pic16_popGetLabel (jtab->key);
12590     //fprintf (stderr, "Creating jump table...\n");
12591
12592     // calculate offset into jump table (idx * sizeof (GOTO))
12593     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12594     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12595     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12596     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12597     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12598     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12599     pic16_emitpcode(POC_MOVWF , jt_offs);
12600
12601     // prepare PCLATx (set to first entry in jump table)
12602     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12603     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12604     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12605     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12606     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12607
12608     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12609     pic16_emitpcode(POC_ADDWF , jt_offs);
12610     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12611     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12612     emitSKPNC;
12613     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12614
12615     // release temporaries and prepare jump into table (new PCL --> WREG)
12616     pic16_emitpcode(POC_MOVFW , jt_offs);
12617     pic16_popReleaseTempReg (jt_offs_hi, 1);
12618     pic16_popReleaseTempReg (jt_offs, 0);
12619
12620     // jump into the table
12621     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12622
12623     pic16_emitpLabelFORCE(jtab->key);
12624 #endif
12625
12626     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12627 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12628
12629     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12630     /* now generate the jump labels */
12631     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12632          jtab = setNextItem(IC_JTLABELS(ic))) {
12633 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12634         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12635         
12636     }
12637     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12638
12639 }
12640
12641 /*-----------------------------------------------------------------*/
12642 /* genMixedOperation - gen code for operators between mixed types  */
12643 /*-----------------------------------------------------------------*/
12644 /*
12645   TSD - Written for the PIC port - but this unfortunately is buggy.
12646   This routine is good in that it is able to efficiently promote 
12647   types to different (larger) sizes. Unfortunately, the temporary
12648   variables that are optimized out by this routine are sometimes
12649   used in other places. So until I know how to really parse the 
12650   iCode tree, I'm going to not be using this routine :(.
12651 */
12652 static int genMixedOperation (iCode *ic)
12653 {
12654 #if 0
12655   operand *result = IC_RESULT(ic);
12656   sym_link *ctype = operandType(IC_LEFT(ic));
12657   operand *right = IC_RIGHT(ic);
12658   int ret = 0;
12659   int big,small;
12660   int offset;
12661
12662   iCode *nextic;
12663   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12664
12665   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12666
12667   nextic = ic->next;
12668   if(!nextic)
12669     return 0;
12670
12671   nextright = IC_RIGHT(nextic);
12672   nextleft  = IC_LEFT(nextic);
12673   nextresult = IC_RESULT(nextic);
12674
12675   pic16_aopOp(right,ic,FALSE);
12676   pic16_aopOp(result,ic,FALSE);
12677   pic16_aopOp(nextright,  nextic, FALSE);
12678   pic16_aopOp(nextleft,   nextic, FALSE);
12679   pic16_aopOp(nextresult, nextic, FALSE);
12680
12681   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12682
12683     operand *t = right;
12684     right = nextright;
12685     nextright = t; 
12686
12687     pic16_emitcode(";remove right +","");
12688
12689   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12690 /*
12691     operand *t = right;
12692     right = nextleft;
12693     nextleft = t; 
12694 */
12695     pic16_emitcode(";remove left +","");
12696   } else
12697     return 0;
12698
12699   big = AOP_SIZE(nextleft);
12700   small = AOP_SIZE(nextright);
12701
12702   switch(nextic->op) {
12703
12704   case '+':
12705     pic16_emitcode(";optimize a +","");
12706     /* if unsigned or not an integral type */
12707     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12708       pic16_emitcode(";add a bit to something","");
12709     } else {
12710
12711       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12712
12713       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12714         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12715         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12716       } else
12717         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12718
12719       offset = 0;
12720       while(--big) {
12721
12722         offset++;
12723
12724         if(--small) {
12725           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12726             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12727             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12728           }
12729
12730           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12731           emitSKPNC;
12732           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12733                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12734                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12735           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12736           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12737
12738         } else {
12739           pic16_emitcode("rlf","known_zero,w");
12740
12741           /*
12742             if right is signed
12743               btfsc  right,7
12744                addlw ff
12745           */
12746           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12747             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12748             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12749           } else {
12750             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12751           }
12752         }
12753       }
12754       ret = 1;
12755     }
12756   }
12757   ret = 1;
12758
12759 release:
12760   pic16_freeAsmop(right,NULL,ic,TRUE);
12761   pic16_freeAsmop(result,NULL,ic,TRUE);
12762   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12763   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12764   if(ret)
12765     nextic->generated = 1;
12766
12767   return ret;
12768 #else
12769   return 0;
12770 #endif
12771 }
12772 /*-----------------------------------------------------------------*/
12773 /* genCast - gen code for casting                                  */
12774 /*-----------------------------------------------------------------*/
12775 static void genCast (iCode *ic)
12776 {
12777   operand *result = IC_RESULT(ic);
12778   sym_link *ctype = operandType(IC_LEFT(ic));
12779   sym_link *rtype = operandType(IC_RIGHT(ic));
12780   sym_link *restype = operandType(IC_RESULT(ic));
12781   operand *right = IC_RIGHT(ic);
12782   int size, offset ;
12783
12784
12785     FENTRY;
12786
12787         /* if they are equivalent then do nothing */
12788 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12789 //              return ;
12790
12791         pic16_aopOp(result,ic,FALSE);
12792         pic16_aopOp(right,ic,FALSE) ;
12793
12794         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12795
12796
12797         /* if the result is a bit */
12798         if (AOP_TYPE(result) == AOP_CRY) {
12799         
12800                 /* if the right size is a literal then
12801                  * we know what the value is */
12802                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12803
12804                 if (AOP_TYPE(right) == AOP_LIT) {
12805                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12806                                 pic16_popGet(AOP(result),0));
12807
12808                         if (((int) operandLitValue(right))) 
12809                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12810                                         AOP(result)->aopu.aop_dir,
12811                                         AOP(result)->aopu.aop_dir);
12812                         else
12813                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12814                                         AOP(result)->aopu.aop_dir,
12815                                         AOP(result)->aopu.aop_dir);
12816                         goto release;
12817                 }
12818
12819                 /* the right is also a bit variable */
12820                 if (AOP_TYPE(right) == AOP_CRY) {
12821                         emitCLRC;
12822                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12823
12824                         pic16_emitcode("clrc","");
12825                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12826                                 AOP(right)->aopu.aop_dir,
12827                                 AOP(right)->aopu.aop_dir);
12828                         pic16_aopPut(AOP(result),"c",0);
12829                         goto release ;
12830                 }
12831
12832                 /* we need to or */
12833                 if (AOP_TYPE(right) == AOP_REG) {
12834                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12835                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12836                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12837                 }
12838                 pic16_toBoolean(right);
12839                 pic16_aopPut(AOP(result),"a",0);
12840                 goto release ;
12841         }
12842
12843         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12844           int offset = 1;
12845
12846                 size = AOP_SIZE(result);
12847
12848                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12849
12850                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12851                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12852                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12853
12854                 while (size--)
12855                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12856
12857                 goto release;
12858         }
12859
12860         if(IS_BITFIELD(getSpec(restype))
12861           && IS_BITFIELD(getSpec(rtype))) {
12862           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12863         }
12864         
12865         /* port from pic14 to cope with generic pointers */
12866         if (PIC_IS_TAGGED(restype))
12867         {
12868           operand *result = IC_RESULT(ic);
12869           //operand *left = IC_LEFT(ic);
12870           operand *right = IC_RIGHT(ic);
12871           int tag = 0xff;
12872
12873           /* copy common part */
12874           int max, size = AOP_SIZE(result);
12875           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12876           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12877
12878           max = size;
12879           while (size--)
12880           {
12881             pic16_mov2w (AOP(right), size);
12882             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12883           } // while
12884
12885           /* upcast into generic pointer type? */
12886           if (IS_GENPTR(restype)
12887               && !PIC_IS_TAGGED(rtype)
12888               && (AOP_SIZE(result) > max))
12889           {
12890             /* determine appropriate tag for right */
12891             if (PIC_IS_DATA_PTR(rtype))
12892               tag = GPTR_TAG_DATA;
12893             else if (IS_CODEPTR(rtype))
12894               tag = GPTR_TAG_CODE;
12895             else if (PIC_IS_DATA_PTR(ctype)) {
12896               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12897               tag = GPTR_TAG_DATA;
12898             } else if (IS_CODEPTR(ctype)) {
12899               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12900               tag = GPTR_TAG_CODE;
12901             } else if (IS_PTR(rtype)) {
12902               PERFORM_ONCE(weirdcast,
12903               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12904               );
12905               tag = GPTR_TAG_DATA;
12906             } else {
12907               PERFORM_ONCE(weirdcast,
12908               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12909               );
12910               tag = GPTR_TAG_DATA;
12911             }
12912
12913             assert (AOP_SIZE(result) == 3);
12914             /* zero-extend address... */
12915             for (size = max; size < AOP_SIZE(result)-1; size++)
12916               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12917             /* ...and add tag */
12918             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12919           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12920             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12921             for (size = max; size < AOP_SIZE(result)-1; size++)
12922               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12923             /* add __code tag */
12924             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12925           } else if (AOP_SIZE(result) > max) {
12926             /* extend non-pointers */
12927             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12928             pic16_addSign(result, max, 0);
12929           } // if
12930           goto release;
12931         }
12932
12933         /* if they are the same size : or less */
12934         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12935
12936                 /* if they are in the same place */
12937                 if (pic16_sameRegs(AOP(right),AOP(result)))
12938                         goto release;
12939
12940                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12941 #if 0
12942                 if (IS_PTR_CONST(rtype))
12943 #else
12944                 if (IS_CODEPTR(rtype))
12945 #endif
12946                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12947
12948 #if 0
12949                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12950 #else
12951                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12952 #endif
12953                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12954
12955 #if 0
12956                 if(AOP_TYPE(right) == AOP_IMMD) {
12957                   pCodeOp *pcop0, *pcop1, *pcop2;
12958                   symbol *sym = OP_SYMBOL( right );
12959
12960                         size = AOP_SIZE(result);
12961                         /* low */
12962                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12963                         /* high */
12964                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12965                         /* upper */
12966                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12967         
12968                         if (size == 3) {
12969                                 pic16_emitpcode(POC_MOVLW, pcop0);
12970                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12971                                 pic16_emitpcode(POC_MOVLW, pcop1);
12972                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12973                                 pic16_emitpcode(POC_MOVLW, pcop2);
12974                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12975                         } else
12976                         if (size == 2) {
12977                                 pic16_emitpcode(POC_MOVLW, pcop0);
12978                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12979                                 pic16_emitpcode(POC_MOVLW, pcop1);
12980                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12981                         } else {
12982                                 pic16_emitpcode(POC_MOVLW, pcop0);
12983                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12984                         }
12985                 } else
12986 #endif
12987                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12988                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12989                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12990                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12991                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12992                         if(AOP_SIZE(result) <2)
12993                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12994                 } else {
12995                         /* if they in different places then copy */
12996                         size = AOP_SIZE(result);
12997                         offset = 0 ;
12998                         while (size--) {
12999                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13000                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13001                                 offset++;
13002                         }
13003                 }
13004                 goto release;
13005         }
13006
13007         /* if the result is of type pointer */
13008         if (IS_PTR(ctype)) {
13009           int p_type;
13010           sym_link *type = operandType(right);
13011           sym_link *etype = getSpec(type);
13012
13013                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13014
13015                 /* pointer to generic pointer */
13016                 if (IS_GENPTR(ctype)) {
13017                   char *l = zero;
13018             
13019                         if (IS_PTR(type)) 
13020                                 p_type = DCL_TYPE(type);
13021                         else {
13022                 /* we have to go by the storage class */
13023                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13024
13025 /*              if (SPEC_OCLS(etype)->codesp )  */
13026 /*                  p_type = CPOINTER ;  */
13027 /*              else */
13028 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13029 /*                      p_type = FPOINTER ; */
13030 /*                  else */
13031 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13032 /*                          p_type = PPOINTER; */
13033 /*                      else */
13034 /*                          if (SPEC_OCLS(etype) == idata ) */
13035 /*                              p_type = IPOINTER ; */
13036 /*                          else */
13037 /*                              p_type = POINTER ; */
13038             }
13039                 
13040             /* the first two bytes are known */
13041       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13042             size = GPTRSIZE - 1; 
13043             offset = 0 ;
13044             while (size--) {
13045               if(offset < AOP_SIZE(right)) {
13046                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13047                 pic16_mov2f(AOP(result), AOP(right), offset);
13048 /*
13049                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13050                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13051                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13052                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13053                 } else { 
13054                   
13055                   pic16_aopPut(AOP(result),
13056                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13057                          offset);
13058                 }
13059 */
13060               } else 
13061                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13062               offset++;
13063             }
13064             /* the last byte depending on type */
13065             switch (p_type) {
13066             case IPOINTER:
13067             case POINTER:
13068             case FPOINTER:
13069                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13070                 break;
13071
13072             case CPOINTER:
13073                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13074                 break;
13075
13076             case PPOINTER:
13077               pic16_emitcode(";BUG!? ","%d",__LINE__);
13078                 l = "#0x03";
13079                 break;
13080
13081             case GPOINTER:
13082                 if (GPTRSIZE > AOP_SIZE(right)) {
13083                   // assume __data pointer... THIS MIGHT BE WRONG!
13084                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13085                 } else {
13086                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13087                 }
13088               break;
13089               
13090             default:
13091                 /* this should never happen */
13092                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13093                        "got unknown pointer type");
13094                 exit(1);
13095             }
13096             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13097             goto release ;
13098         }
13099         
13100         
13101         assert( 0 );
13102         /* just copy the pointers */
13103         size = AOP_SIZE(result);
13104         offset = 0 ;
13105         while (size--) {
13106             pic16_aopPut(AOP(result),
13107                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13108                    offset);
13109             offset++;
13110         }
13111         goto release ;
13112     }
13113     
13114
13115
13116     /* so we now know that the size of destination is greater
13117     than the size of the source.
13118     Now, if the next iCode is an operator then we might be
13119     able to optimize the operation without performing a cast.
13120     */
13121     if(genMixedOperation(ic))
13122       goto release;
13123
13124     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13125     
13126     /* we move to result for the size of source */
13127     size = AOP_SIZE(right);
13128     offset = 0 ;
13129
13130     while (size--) {
13131       if(!_G.resDirect)
13132         pic16_mov2f(AOP(result), AOP(right), offset);
13133       offset++;
13134     }
13135
13136     /* now depending on the sign of the destination */
13137     size = AOP_SIZE(result) - AOP_SIZE(right);
13138     /* if unsigned or not an integral type */
13139     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13140       while (size--)
13141         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13142     } else {
13143       /* we need to extend the sign :( */
13144
13145       if(size == 1) {
13146         /* Save one instruction of casting char to int */
13147         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13148         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13149         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13150       } else {
13151         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13152
13153         if(offset)
13154           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13155         else
13156           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13157         
13158         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13159
13160         while (size--)
13161           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13162       }
13163     }
13164
13165 release:
13166     pic16_freeAsmop(right,NULL,ic,TRUE);
13167     pic16_freeAsmop(result,NULL,ic,TRUE);
13168
13169 }
13170
13171 /*-----------------------------------------------------------------*/
13172 /* genDjnz - generate decrement & jump if not zero instrucion      */
13173 /*-----------------------------------------------------------------*/
13174 static int genDjnz (iCode *ic, iCode *ifx)
13175 {
13176     symbol *lbl, *lbl1;
13177     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13178
13179     if (!ifx)
13180         return 0;
13181     
13182     /* if the if condition has a false label
13183        then we cannot save */
13184     if (IC_FALSE(ifx))
13185         return 0;
13186
13187     /* if the minus is not of the form 
13188        a = a - 1 */
13189     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13190         !IS_OP_LITERAL(IC_RIGHT(ic)))
13191         return 0;
13192
13193     if (operandLitValue(IC_RIGHT(ic)) != 1)
13194         return 0;
13195
13196     /* if the size of this greater than one then no
13197        saving */
13198     if (getSize(operandType(IC_RESULT(ic))) > 1)
13199         return 0;
13200
13201     /* otherwise we can save BIG */
13202     lbl = newiTempLabel(NULL);
13203     lbl1= newiTempLabel(NULL);
13204
13205     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13206     
13207     if (IS_AOP_PREG(IC_RESULT(ic))) {
13208         pic16_emitcode("dec","%s",
13209                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13210         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13211         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13212     } else {    
13213
13214
13215       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13216       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13217
13218       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13219       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13220
13221     }
13222     
13223     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13224     ifx->generated = 1;
13225     return 1;
13226 }
13227
13228 /*-----------------------------------------------------------------*/
13229 /* genReceive - generate code for a receive iCode                  */
13230 /*-----------------------------------------------------------------*/
13231 static void genReceive (iCode *ic)
13232 {    
13233
13234   FENTRY;
13235
13236 #if 0
13237   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13238         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13239 #endif
13240 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13241
13242   if (isOperandInFarSpace(IC_RESULT(ic))
13243       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13244           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13245
13246     int size = getSize(operandType(IC_RESULT(ic)));
13247     int offset =  pic16_fReturnSizePic - size;
13248
13249       assert( 0 );
13250       while (size--) {
13251         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13252                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13253                       offset++;
13254         }
13255
13256       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13257
13258       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13259       size = AOP_SIZE(IC_RESULT(ic));
13260       offset = 0;
13261       while (size--) {
13262         pic16_emitcode ("pop","acc");
13263         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13264       }
13265   } else {
13266     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13267     _G.accInUse++;
13268     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13269     _G.accInUse--;
13270
13271     /* set pseudo stack pointer to where it should be - dw*/
13272     GpsuedoStkPtr = ic->parmBytes;
13273
13274     /* setting GpsuedoStkPtr has side effects here: */
13275     assignResultValue(IC_RESULT(ic), 0);
13276   }
13277
13278   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13279 }
13280
13281 /*-----------------------------------------------------------------*/
13282 /* genDummyRead - generate code for dummy read of volatiles        */
13283 /*-----------------------------------------------------------------*/
13284 static void
13285 genDummyRead (iCode * ic)
13286 {
13287   operand *op;
13288   int i;
13289
13290   op = IC_RIGHT(ic);
13291   if (op && IS_SYMOP(op)) {
13292     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13293       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13294       return;
13295     }
13296     pic16_aopOp (op, ic, FALSE);
13297     for (i=0; i < AOP_SIZE(op); i++) {
13298       // may need to protect this from the peepholer -- this is not nice but works...
13299       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13300       pic16_mov2w (AOP(op),i);
13301       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13302     } // for i
13303     pic16_freeAsmop (op, NULL, ic, TRUE);
13304   } else if (op) {
13305     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13306   } // if
13307 }
13308
13309 /*-----------------------------------------------------------------*/
13310 /* genpic16Code - generate code for pic16 based controllers        */
13311 /*-----------------------------------------------------------------*/
13312 /*
13313  * At this point, ralloc.c has gone through the iCode and attempted
13314  * to optimize in a way suitable for a PIC. Now we've got to generate
13315  * PIC instructions that correspond to the iCode.
13316  *
13317  * Once the instructions are generated, we'll pass through both the
13318  * peep hole optimizer and the pCode optimizer.
13319  *-----------------------------------------------------------------*/
13320
13321 void genpic16Code (iCode *lic)
13322 {
13323   iCode *ic;
13324   int cln = 0;
13325
13326     lineHead = lineCurr = NULL;
13327
13328     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13329     pic16_addpBlock(pb);
13330
13331 #if 0
13332     /* if debug information required */
13333     if (options.debug && currFunc) {
13334       if (currFunc) {
13335         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13336       }
13337     }
13338 #endif
13339
13340     for (ic = lic ; ic ; ic = ic->next ) {
13341
13342       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13343       if ( cln != ic->lineno ) {
13344         if ( options.debug ) {
13345           debugFile->writeCLine (ic);
13346         }
13347         
13348         if(!options.noCcodeInAsm) {
13349           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13350               printCLine(ic->filename, ic->lineno)));
13351         }
13352
13353         cln = ic->lineno ;
13354       }
13355         
13356       if(options.iCodeInAsm) {
13357         char *l;
13358
13359           /* insert here code to print iCode as comment */
13360           l = Safe_strdup(printILine(ic));
13361           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13362       }
13363
13364       /* if the result is marked as
13365        * spilt and rematerializable or code for
13366        * this has already been generated then
13367        * do nothing */
13368       if (resultRemat(ic) || ic->generated ) 
13369         continue ;
13370         
13371       /* depending on the operation */
13372       switch (ic->op) {
13373         case '!' :
13374           pic16_genNot(ic);
13375           break;
13376             
13377         case '~' :
13378           pic16_genCpl(ic);
13379           break;
13380             
13381         case UNARYMINUS:
13382           genUminus (ic);
13383           break;
13384             
13385         case IPUSH:
13386           genIpush (ic);
13387           break;
13388             
13389         case IPOP:
13390           /* IPOP happens only when trying to restore a 
13391            * spilt live range, if there is an ifx statement
13392            * following this pop then the if statement might
13393            * be using some of the registers being popped which
13394            * would destroy the contents of the register so
13395            * we need to check for this condition and handle it */
13396            if (ic->next
13397              && ic->next->op == IFX
13398              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13399                genIfx (ic->next,ic);
13400           else
13401             genIpop (ic);
13402           break; 
13403             
13404         case CALL:
13405           genCall (ic);
13406           break;
13407             
13408         case PCALL:
13409           genPcall (ic);
13410           break;
13411             
13412         case FUNCTION:
13413           genFunction (ic);
13414           break;
13415             
13416         case ENDFUNCTION:
13417           genEndFunction (ic);
13418           break;
13419             
13420         case RETURN:
13421           genRet (ic);
13422           break;
13423             
13424         case LABEL:
13425           genLabel (ic);
13426           break;
13427             
13428         case GOTO:
13429           genGoto (ic);
13430           break;
13431             
13432         case '+' :
13433           pic16_genPlus (ic) ;
13434           break;
13435             
13436         case '-' :
13437           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13438             pic16_genMinus (ic);
13439           break;
13440
13441         case '*' :
13442           genMult (ic);
13443           break;
13444             
13445         case '/' :
13446           genDiv (ic) ;
13447           break;
13448             
13449         case '%' :
13450           genMod (ic);
13451           break;
13452             
13453         case '>' :
13454           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13455           break;
13456             
13457         case '<' :
13458           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13459           break;
13460             
13461         case LE_OP:
13462         case GE_OP:
13463         case NE_OP:
13464           /* note these two are xlated by algebraic equivalence
13465            * during parsing SDCC.y */
13466           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13467             "got '>=' or '<=' shouldn't have come here");
13468           break;
13469
13470         case EQ_OP:
13471           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13472           break;            
13473             
13474         case AND_OP:
13475           genAndOp (ic);
13476           break;
13477             
13478         case OR_OP:
13479           genOrOp (ic);
13480           break;
13481             
13482         case '^' :
13483           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13484           break;
13485             
13486         case '|' :
13487           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13488           break;
13489             
13490         case BITWISEAND:
13491           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13492           break;
13493             
13494         case INLINEASM:
13495           genInline (ic);
13496           break;
13497             
13498         case RRC:
13499           genRRC (ic);
13500           break;
13501             
13502         case RLC:
13503           genRLC (ic);
13504           break;
13505             
13506         case GETHBIT:
13507           genGetHbit (ic);
13508           break;
13509             
13510         case LEFT_OP:
13511           genLeftShift (ic);
13512           break;
13513             
13514         case RIGHT_OP:
13515           genRightShift (ic);
13516           break;
13517             
13518         case GET_VALUE_AT_ADDRESS:
13519           genPointerGet(ic);
13520           break;
13521             
13522         case '=' :
13523           if (POINTER_SET(ic))
13524             genPointerSet(ic);
13525           else
13526             genAssign(ic);
13527           break;
13528             
13529         case IFX:
13530           genIfx (ic,NULL);
13531           break;
13532             
13533         case ADDRESS_OF:
13534           genAddrOf (ic);
13535           break;
13536             
13537         case JUMPTABLE:
13538           genJumpTab (ic);
13539           break;
13540             
13541         case CAST:
13542           genCast (ic);
13543           break;
13544             
13545         case RECEIVE:
13546           genReceive(ic);
13547           break;
13548             
13549         case SEND:
13550           addSet(&_G.sendSet,ic);
13551           break;
13552
13553         case DUMMY_READ_VOLATILE:
13554           genDummyRead (ic);
13555           break;
13556
13557         default :
13558           ic = ic;
13559       }
13560     }
13561
13562
13563     /* now we are ready to call the
13564        peep hole optimizer */
13565     if (!options.nopeep)
13566       peepHole (&lineHead);
13567
13568     /* now do the actual printing */
13569     printLine (lineHead, codeOutFile);
13570
13571 #ifdef PCODE_DEBUG
13572     DFPRINTF((stderr,"printing pBlock\n\n"));
13573     pic16_printpBlock(stdout,pb);
13574 #endif
13575
13576     return;
13577 }
13578