* src/SDCCpeeph.c: made labelHashEntry global, made pcDistance, FBYNAME static,
[fw/sdcc] / src / pic16 / gen.c
1  /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
10   Bug Fixes  -  Raphael Neider <rneider AT web.de> (2004,2005)
11   
12   This program is free software; you can redistribute it and/or modify it
13   under the terms of the GNU General Public License as published by the
14   Free Software Foundation; either version 2, or (at your option) any
15   later version.
16   
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21   
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software
24   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25   
26   In other words, you are welcome to use, share and improve this program.
27   You are forbidden to forbid anyone else to use, share and improve
28   what you give them.   Help stamp out software-hoarding!
29   
30   Notes:
31   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
32                 Made everything static
33 -------------------------------------------------------------------------*/
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "SDCCglobl.h"
40 #include "newalloc.h"
41
42 #include "common.h"
43 #include "SDCCpeeph.h"
44 #include "ralloc.h"
45 #include "pcode.h"
46 #include "gen.h"
47 #include "genutils.h"
48 #include "device.h"
49 #include "main.h"
50 #include "glue.h"
51
52 /* Set the following to 1 to enable the slower/bigger
53  * but more robust generic shifting routine (which also
54  * operates correctly with negative shift values). */
55 #define USE_GENERIC_SIGNED_SHIFT 1
56
57 /* Set the following to 1 to enable the new
58  * stripped down genCmp version.
59  * This version should be easier to understand,
60  * more reliable and (sigh) slighly slower. */
61 #define USE_SIMPLE_GENCMP 1
62
63 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
64 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
66 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
67 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
68
69 /* If you change these, you also have to update the library files
70  * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
71 #define GPTR_TAG_DATA   0x80
72 #define GPTR_TAG_EEPROM 0x40
73 #define GPTR_TAG_CODE   0x00    /* must be 0 becaue of UPPER(sym)==0 */
74
75 /* Wrapper to execute `code' at most once. */
76 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
77
78 void pic16_genMult8X8_n (operand *, operand *,operand *);
79 #if 0
80 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
81 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
82 void pic16_genMult16X16_16(operand *, operand *, operand *);
83 void pic16_genMult32X32_32(operand *, operand *, operand *);
84 #endif
85 pCode *pic16_AssembleLine(char *line, int peeps);
86 extern void pic16_printpBlock(FILE *of, pBlock *pb);
87 static asmop *newAsmop (short type);
88 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
89 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
90 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
91 static pCodeOp *pic16_popRegFromIdx(int rIdx);
92
93 //static int aopIdx (asmop *aop, int offset);
94
95 int pic16_labelOffset=0;
96 extern int pic16_debug_verbose;
97 #if !(USE_GENERIC_SIGNED_SHIFT)
98 static int optimized_for_speed = 0;
99 #endif
100 /*
101   hack hack
102
103 */
104
105 extern set *externs;
106
107 /* max_key keeps track of the largest label number used in 
108    a function. This is then used to adjust the label offset
109    for the next function.
110 */
111 static int max_key=0;
112 static int GpsuedoStkPtr=0;
113
114 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
115
116 const char *pic16_AopType(short type);
117 static iCode *ifxForOp ( operand *op, iCode *ic );
118
119 void pic16_pushpCodeOp(pCodeOp *pcop);
120 void pic16_poppCodeOp(pCodeOp *pcop);
121
122 static bool is_LitOp(operand *op);
123 static bool is_LitAOp(asmop *aop);
124
125
126 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
127
128 /* set the following macro to 1 to enable passing the
129  * first byte of functions parameters via WREG */
130 #define USE_WREG_IN_FUNC_PARAMS 0
131
132
133 /* this is the down and dirty file with all kinds of 
134    kludgy & hacky stuff. This is what it is all about
135    CODE GENERATION for a specific MCU . some of the
136    routines may be reusable, will have to see */
137
138 static char *zero = "#0x00";
139 static char *one  = "#0x01";
140 //static char *spname = "sp";
141
142
143 /*
144  * Function return value policy (MSB-->LSB):
145  *  8 bits      -> WREG
146  * 16 bits      -> PRODL:WREG
147  * 24 bits      -> PRODH:PRODL:WREG
148  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
149  * >32 bits     -> on stack, and FSR0 points to the beginning
150  *
151  */
152  
153
154 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
155 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
156 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
157 static char **fReturn = fReturnpic16;
158
159 static char *accUse[] = {"WREG"};
160
161 //static short rbank = -1;
162
163 static struct {
164     short r0Pushed;
165     short r1Pushed;
166     short fsr0Pushed;
167     short accInUse;
168     short inLine;
169     short debugLine;
170     short nRegsSaved;
171     short ipushRegs;
172     set *sendSet;
173     set *stackRegSet;
174     int usefastretfie;
175     bitVect *fregsUsed;                 /* registers used in function */
176     bitVect *sregsAlloc;
177     set *sregsAllocSet;                 /* registers used to store stack variables */
178     int stack_lat;                      /* stack offset latency */
179     int resDirect;
180     int useWreg;                        /* flag when WREG is used to pass function parameter */
181 } _G;
182
183 extern int pic16_ptrRegReq ;
184 extern int pic16_nRegs;
185 extern FILE *codeOutFile;
186 //static void saverbank (int, iCode *,bool);
187
188 static lineNode *lineHead = NULL;
189 static lineNode *lineCurr = NULL;
190
191 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
192 0xE0, 0xC0, 0x80, 0x00};
193 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
194 0x07, 0x03, 0x01, 0x00};
195
196 static  pBlock *pb;
197
198 /*-----------------------------------------------------------------*/
199 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
200 /*                 exponent of 2 is returned, otherwise -1 is      */
201 /*                 returned.                                       */
202 /* note that this is similar to the function `powof2' in SDCCsymt  */
203 /* if(n == 2^y)                                                    */
204 /*   return y;                                                     */
205 /* return -1;                                                      */
206 /*-----------------------------------------------------------------*/
207 int pic16_my_powof2 (unsigned long num)
208 {
209   if(num) {
210     if( (num & (num-1)) == 0) {
211       int nshifts = -1;
212       while(num) {
213         num>>=1;
214         nshifts++;
215       }
216       return nshifts;
217     }
218   }
219
220   return -1;
221 }
222
223 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
224 {
225   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
226                        line_no,
227                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
228                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
229                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
230                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
231                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
232                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
233                        ((result) ? AOP_SIZE(result) : 0));
234 }
235
236 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
237 {
238
239   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
240                        line_no,
241                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
242                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
243                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
244                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
245                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
246                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
247
248 }
249
250 void pic16_emitpcomment (char *fmt, ...)
251 {
252     va_list ap;
253     char lb[INITIAL_INLINEASM];  
254     unsigned char *lbp = (unsigned char *)lb;
255
256     va_start(ap,fmt);   
257
258     lb[0] = ';';
259     vsprintf(lb+1,fmt,ap);
260
261     while (isspace(*lbp)) lbp++;
262
263     if (lbp && *lbp) 
264         lineCurr = (lineCurr ?
265                     connectLine(lineCurr,newLineNode(lb)) :
266                     (lineHead = newLineNode(lb)));
267     lineCurr->isInline = _G.inLine;
268     lineCurr->isDebug  = _G.debugLine;
269     lineCurr->isComment = 1;
270
271     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
272     va_end(ap);
273
274 //      fprintf(stderr, "%s\n", lb);
275 }
276
277 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
278 {
279     va_list ap;
280     char lb[INITIAL_INLINEASM];  
281     unsigned char *lbp = (unsigned char *)lb;
282
283     if(!pic16_debug_verbose)
284       return;
285
286     va_start(ap,fmt);   
287
288     if (inst && *inst) {
289         if (fmt && *fmt)
290             sprintf(lb,"%s\t",inst);
291         else
292             sprintf(lb,"%s",inst);
293         vsprintf(lb+(strlen(lb)),fmt,ap);
294     }  else
295         vsprintf(lb,fmt,ap);
296
297     while (isspace(*lbp)) lbp++;
298
299     if (lbp && *lbp) 
300         lineCurr = (lineCurr ?
301                     connectLine(lineCurr,newLineNode(lb)) :
302                     (lineHead = newLineNode(lb)));
303     lineCurr->isInline = _G.inLine;
304     lineCurr->isDebug  = _G.debugLine;
305
306     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
307     va_end(ap);
308
309 //      fprintf(stderr, "%s\n", lb);
310 }
311
312
313
314 void pic16_emitpLabel(int key)
315 {
316   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
317 }
318
319 void pic16_emitpLabelFORCE(int key)
320 {
321   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
322 }
323
324 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
325  * NEVER call pic16_emitpcode_real directly, please... */
326 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
327 {
328
329   if(pcop)
330     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
331   else
332     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
333 }
334
335 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
336 {
337   if(pcop)
338     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
339   else
340     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
341 }
342   
343 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
344 {
345
346   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
347
348 }
349
350
351 #if 1
352 #define pic16_emitcode  DEBUGpic16_emitcode
353 #else
354 /*-----------------------------------------------------------------*/
355 /* pic16_emitcode - writes the code into a file : for now it is simple    */
356 /*-----------------------------------------------------------------*/
357 void pic16_emitcode (char *inst,char *fmt, ...)
358 {
359     va_list ap;
360     char lb[INITIAL_INLINEASM];  
361     unsigned char *lbp = lb;
362
363     va_start(ap,fmt);   
364
365     if (inst && *inst) {
366         if (fmt && *fmt)
367             sprintf(lb,"%s\t",inst);
368         else
369             sprintf(lb,"%s",inst);
370         vsprintf(lb+(strlen(lb)),fmt,ap);
371     }  else
372         vsprintf(lb,fmt,ap);
373
374     while (isspace(*lbp)) lbp++;
375
376     if (lbp && *lbp) 
377         lineCurr = (lineCurr ?
378                     connectLine(lineCurr,newLineNode(lb)) :
379                     (lineHead = newLineNode(lb)));
380     lineCurr->isInline = _G.inLine;
381     lineCurr->isDebug  = _G.debugLine;
382     lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
383     lineCurr->isComment = (*lbp == ';');
384
385 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
386
387 //    if(pic16_debug_verbose)
388 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
389
390     va_end(ap);
391 }
392 #endif
393
394
395 /*-----------------------------------------------------------------*/
396 /* pic16_emitDebuggerSymbol - associate the current code location  */
397 /*   with a debugger symbol                                        */
398 /*-----------------------------------------------------------------*/
399 void
400 pic16_emitDebuggerSymbol (char * debugSym)
401 {
402   _G.debugLine = 1;
403   pic16_emitcode (";", "%s ==.", debugSym);
404   _G.debugLine = 0;
405 }
406
407
408 /*-----------------------------------------------------------------*/
409 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
410 /*-----------------------------------------------------------------*/
411 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
412 {
413 //    bool r0iu = FALSE , r1iu = FALSE;
414 //    bool r0ou = FALSE , r1ou = FALSE;
415     bool fsr0iu = FALSE, fsr0ou;
416     bool fsr2iu = FALSE, fsr2ou;
417     
418     //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__,  __FUNCTION__, __LINE__, ic->op, result);
419
420     
421     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
422     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
423     
424     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
425     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
426
427     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
428         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
429         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
430     }
431
432     if(!fsr0iu && !fsr0ou) {
433         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
434         (*aopp)->type = AOP_FSR0;
435
436         //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
437         
438       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
439     }
440
441 #if 0
442     /* no usage of FSR2 */
443     if(!fsr2iu && !fsr2ou) {
444         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
445         (*aopp)->type = AOP_FSR2;
446
447       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
448     }
449 #endif
450         
451     /* now we know they both have usage */
452     /* if fsr0 not used in this instruction */
453     if (!fsr0iu) {
454         if (!_G.fsr0Pushed) {
455                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
456                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
457                 _G.fsr0Pushed++;
458         }
459
460         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
461         (*aopp)->type = AOP_FSR0;
462
463 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
464
465       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
466     }
467         
468
469     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
470     assert( 0 );
471
472     return NULL;
473 #if 0
474     /* the logic: if r0 & r1 used in the instruction
475     then we are in trouble otherwise */
476
477     /* first check if r0 & r1 are used by this
478     instruction, in which case we are in trouble */
479     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
480         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
481     {
482         goto endOfWorld;      
483     }
484
485     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
486     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
487
488     /* if no usage of r0 then return it */
489     if (!r0iu && !r0ou) {
490         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
491         (*aopp)->type = AOP_R0; 
492         
493         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
494     }
495
496     /* if no usage of r1 then return it */
497     if (!r1iu && !r1ou) {
498         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
499         (*aopp)->type = AOP_R1;
500
501         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
502     }    
503
504     /* now we know they both have usage */
505     /* if r0 not used in this instruction */
506     if (!r0iu) {
507         /* push it if not already pushed */
508         if (!_G.r0Pushed) {
509           //pic16_emitcode ("push","%s",
510           //          pic16_regWithIdx(R0_IDX)->dname);
511             _G.r0Pushed++ ;
512         }
513         
514         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
515         (*aopp)->type = AOP_R0;
516
517         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
518     }
519
520     /* if r1 not used then */
521
522     if (!r1iu) {
523         /* push it if not already pushed */
524         if (!_G.r1Pushed) {
525           //pic16_emitcode ("push","%s",
526           //          pic16_regWithIdx(R1_IDX)->dname);
527             _G.r1Pushed++ ;
528         }
529         
530         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
531         (*aopp)->type = AOP_R1;
532         return pic16_regWithIdx(R1_IDX);
533     }
534
535 endOfWorld :
536     /* I said end of world but not quite end of world yet */
537     /* if this is a result then we can push it on the stack*/
538     if (result) {
539         (*aopp)->type = AOP_STK;    
540         return NULL;
541     }
542
543     /* other wise this is true end of the world */
544     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
545            "getFreePtr should never reach here");
546     exit(0);
547 #endif
548 }
549
550 /*-----------------------------------------------------------------*/
551 /* newAsmop - creates a new asmOp                                  */
552 /*-----------------------------------------------------------------*/
553 static asmop *newAsmop (short type)
554 {
555     asmop *aop;
556
557     aop = Safe_calloc(1,sizeof(asmop));
558     aop->type = type;
559     return aop;
560 }
561
562 static void genSetDPTR(int n)
563 {
564     if (!n)
565     {
566         pic16_emitcode(";", "Select standard DPTR");
567         pic16_emitcode("mov", "dps, #0x00");
568     }
569     else
570     {
571         pic16_emitcode(";", "Select alternate DPTR");
572         pic16_emitcode("mov", "dps, #0x01");
573     }
574 }
575
576 /*-----------------------------------------------------------------*/
577 /* resolveIfx - converts an iCode ifx into a form more useful for  */
578 /*              generating code                                    */
579 /*-----------------------------------------------------------------*/
580 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
581 {
582   FENTRY2;
583   
584 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
585
586   if(!resIfx) 
587     return;
588
589
590   resIfx->condition = 1;    /* assume that the ifx is true */
591   resIfx->generated = 0;    /* indicate that the ifx has not been used */
592
593   if(!ifx) {
594     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
595
596 #if 1
597     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
598                         __FUNCTION__,__LINE__,resIfx->lbl->key);
599 #endif
600
601   } else {
602     if(IC_TRUE(ifx)) {
603       resIfx->lbl = IC_TRUE(ifx);
604     } else {
605       resIfx->lbl = IC_FALSE(ifx);
606       resIfx->condition = 0;
607     }
608
609 #if 1
610     if(IC_TRUE(ifx)) 
611       DEBUGpic16_emitcode("; +++","ifx true is non-null");
612     else
613       DEBUGpic16_emitcode("; +++","ifx true is null");
614     if(IC_FALSE(ifx)) 
615       DEBUGpic16_emitcode("; +++","ifx false is non-null");
616     else
617       DEBUGpic16_emitcode("; +++","ifx false is null");
618 #endif
619   }
620
621   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
622
623 }
624 #if 0
625 /*-----------------------------------------------------------------*/
626 /* pointerCode - returns the code for a pointer type               */
627 /*-----------------------------------------------------------------*/
628 static int pointerCode (sym_link *etype)
629 {
630
631     return PTR_TYPE(SPEC_OCLS(etype));
632
633 }
634 #endif
635
636 /*-----------------------------------------------------------------*/
637 /* aopForSym - for a true symbol                                   */
638 /*-----------------------------------------------------------------*/
639 static asmop *aopForSym (iCode *ic, operand *op, bool result)
640 {
641     symbol *sym=OP_SYMBOL(op);
642     asmop *aop;
643     memmap *space= SPEC_OCLS(sym->etype);
644
645     FENTRY2;
646     
647     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
648     
649 //    sym = OP_SYMBOL(op);
650
651     /* if already has one */
652     if (sym->aop) {
653             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
654         return sym->aop;
655     }
656
657 #if 0
658     /* if symbol was initially placed onStack then we must re-place it
659      * to direct memory, since pic16 does not have a specific stack */
660     if(sym->onStack) {
661         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
662     }
663 #endif
664
665
666 #if 0
667     if(sym->iaccess) {
668       if(space->paged) {
669         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
670
671         sym->aop = aop = newAsmop (AOP_PAGED);
672         aop->aopu.aop_dir = sym->rname ;
673         aop->size = getSize(sym->type);
674         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
675         pic16_allocDirReg( IC_LEFT(ic) );
676         return aop;
677       }
678       assert( 0 );
679     }
680 #endif
681     
682 #if 1
683     /* assign depending on the storage class */
684     /* if it is on the stack or indirectly addressable */
685     /* space we need to assign either r0 or r1 to it   */    
686     if (sym->onStack)   // || sym->iaccess)
687     {
688       pCodeOp *pcop[4];
689       int i;
690       
691         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
692                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
693         
694         /* acquire a temporary register -- it is saved in function */
695
696         sym->aop = aop = newAsmop(AOP_STA);
697         aop->aopu.stk.stk = sym->stack;
698         aop->size = getSize(sym->type);
699
700
701         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
702         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
703           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
704 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
705           
706           for(i=0;i<aop->size;i++)
707             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
708             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
709         } else
710         if(1 && ic->op == SEND) {
711
712           /* if SEND do the send here */
713           _G.resDirect = 1;
714         } else {
715 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
716           for(i=0;i<aop->size;i++) {
717             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
718             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
719           }
720         }
721
722
723 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
724
725 #if 1
726         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
727
728         // we do not need to load the value if it is to be defined...
729         if (result) return aop;
730
731         if(_G.accInUse) {
732                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
733         }
734         
735         for(i=0;i<aop->size;i++) {
736
737           /* initialise for stack access via frame pointer */
738           // operands on stack are accessible via "{FRAME POINTER} + index" with index
739           // starting at 2 for arguments and growing from 0 downwards for
740           // local variables (index == 0 is not assigned so we add one here)
741           {
742             int soffs = sym->stack;
743             if (soffs <= 0) {
744               assert (soffs < 0);
745               soffs++;
746             } // if
747
748             if(1 && ic->op == SEND) {
749               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
750               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
751                     pic16_popCopyReg( pic16_frame_plusw ),
752                     pic16_popCopyReg(pic16_stack_postdec )));
753             } else {
754               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
755               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
756                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
757             }
758           }
759         }
760         
761         if(_G.accInUse) {
762                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
763         }
764         
765         return (aop);
766 #endif
767
768 #if 0
769         /* now assign the address of the variable to 
770         the pointer register */
771         if (aop->type != AOP_STK) {
772
773             if (sym->onStack) {
774                     if ( _G.accInUse )
775                         pic16_emitcode("push","acc");
776
777                     pic16_emitcode("mov","a,_bp");
778                     pic16_emitcode("add","a,#0x%02x",
779                              ((sym->stack < 0) ?
780                               ((char)(sym->stack - _G.nRegsSaved )) :
781                               ((char)sym->stack)) & 0xff);
782                     pic16_emitcode("mov","%s,a",
783                              aop->aopu.aop_ptr->name);
784
785                     if ( _G.accInUse )
786                         pic16_emitcode("pop","acc");
787             } else
788                 pic16_emitcode("mov","%s,#%s",
789                          aop->aopu.aop_ptr->name,
790                          sym->rname);
791             aop->paged = space->paged;
792         } else
793             aop->aopu.aop_stk = sym->stack;
794         return aop;
795 #endif
796
797     }
798 #endif
799
800 #if 0
801     if (sym->onStack && options.stack10bit)
802     {
803         /* It's on the 10 bit stack, which is located in
804          * far data space.
805          */
806          
807       //DEBUGpic16_emitcode(";","%d",__LINE__);
808
809         if ( _G.accInUse )
810                 pic16_emitcode("push","acc");
811
812         pic16_emitcode("mov","a,_bp");
813         pic16_emitcode("add","a,#0x%02x",
814                  ((sym->stack < 0) ?
815                    ((char)(sym->stack - _G.nRegsSaved )) :
816                    ((char)sym->stack)) & 0xff);
817         
818         genSetDPTR(1);
819         pic16_emitcode ("mov","dpx1,#0x40");
820         pic16_emitcode ("mov","dph1,#0x00");
821         pic16_emitcode ("mov","dpl1, a");
822         genSetDPTR(0);
823         
824         if ( _G.accInUse )
825             pic16_emitcode("pop","acc");
826             
827         sym->aop = aop = newAsmop(AOP_DPTR2);
828         aop->size = getSize(sym->type); 
829         return aop;
830     }
831 #endif
832
833 #if 1
834     /* special case for a function */
835     if (IS_FUNC(sym->type)) {   
836         sym->aop = aop = newAsmop(AOP_PCODE);
837         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
838         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
839         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
840         PCOI(aop->aopu.pcop)->index = 0;
841         aop->size = FPTRSIZE; 
842         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
843         return aop;
844     }
845 #endif
846
847
848
849     //DEBUGpic16_emitcode(";","%d",__LINE__);
850     /* if in bit space */
851     if (IN_BITSPACE(space)) {
852         sym->aop = aop = newAsmop (AOP_CRY);
853         aop->aopu.aop_dir = sym->rname ;
854         aop->size = getSize(sym->type);
855         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
856         return aop;
857     }
858     /* if it is in direct space */
859     if (IN_DIRSPACE(space)) {
860                 if(!strcmp(sym->rname, "_WREG")) {
861                         sym->aop = aop = newAsmop (AOP_ACC);
862                         aop->size = getSize(sym->type);         /* should always be 1 */
863                         assert(aop->size == 1);
864                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
865                         return (aop);
866                 } else {
867                         sym->aop = aop = newAsmop (AOP_DIR);
868                 aop->aopu.aop_dir = sym->rname ;
869             aop->size = getSize(sym->type);
870                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
871                         pic16_allocDirReg( IC_LEFT(ic) );
872                         return (aop);
873                 }
874         }
875
876     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
877         sym->aop = aop = newAsmop (AOP_DIR);
878         aop->aopu.aop_dir = sym->rname ;
879         aop->size = getSize(sym->type);
880         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
881         pic16_allocDirReg( IC_LEFT(ic) );
882         return aop;
883     }
884
885
886     /* only remaining is far space */
887     sym->aop = aop = newAsmop(AOP_PCODE);
888
889 /* change the next if to 1 to revert to good old immediate code */
890         if(IN_CODESPACE(space)) {
891                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
892                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
893                 PCOI(aop->aopu.pcop)->index = 0;
894         } else {
895                 /* try to allocate via direct register */
896                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
897 //              aop->size = getSize( sym->type );
898         }
899
900         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
901                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
902
903 #if 0
904         if(!pic16_allocDirReg (IC_LEFT(ic)))
905                 return NULL;
906 #endif
907
908         if(IN_DIRSPACE( space ))
909                 aop->size = PTRSIZE;
910         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
911                 aop->size = FPTRSIZE;
912         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
913         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
914         else if(sym->onStack) {
915                 aop->size = PTRSIZE;
916         } else {
917           if(SPEC_SCLS(sym->etype) == S_PDATA) {
918             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
919             aop->size = FPTRSIZE;
920           } else
921                 assert( 0 );
922         }
923
924     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
925
926     /* if it is in code space */
927     if (IN_CODESPACE(space))
928         aop->code = 1;
929
930     return aop;     
931 }
932
933 /*-----------------------------------------------------------------*/
934 /* aopForRemat - rematerialzes an object                           */
935 /*-----------------------------------------------------------------*/
936 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
937 {
938   symbol *sym = OP_SYMBOL(op);
939   operand *refop;
940   iCode *ic = NULL, *oldic;
941   asmop *aop = newAsmop(AOP_PCODE);
942   int val = 0;
943   int offset = 0;
944   int viaimmd=0;
945
946     FENTRY2;
947     
948         ic = sym->rematiCode;
949
950         if(IS_OP_POINTER(op)) {
951                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
952         }
953
954 //    if(!result)               /* fixme-vr */
955         for (;;) {
956                 oldic = ic;
957
958 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
959         
960                 if (ic->op == '+') {
961                         val += (int) operandLitValue(IC_RIGHT(ic));
962                 } else if (ic->op == '-') {
963                         val -= (int) operandLitValue(IC_RIGHT(ic));
964                 } else
965                         break;
966                 
967                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
968         }
969
970         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
971         refop = IC_LEFT(ic);
972
973         if(!op->isaddr)viaimmd++; else viaimmd=0;
974                 
975 /* set the following if to 1 to revert to good old immediate code */
976         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
977                 || viaimmd) {
978
979                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
980
981                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
982
983 #if 0
984                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
985 #else
986                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
987 #endif
988
989                 PCOI(aop->aopu.pcop)->index = val;
990                 
991                 aop->size = getSize( sym->type );
992         } else {
993                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
994
995                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
996                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
997
998                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
999         }
1000
1001
1002         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
1003                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1004 #if 0
1005                 val, IS_PTR_CONST(operandType(op)));
1006 #else
1007                 val, IS_CODEPTR(operandType(op)));
1008 #endif
1009
1010 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1011
1012         pic16_allocDirReg (IC_LEFT(ic));
1013
1014         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1015                 aop->code = 1;
1016
1017   return aop;        
1018 }
1019
1020 #if 0
1021 static int aopIdx (asmop *aop, int offset)
1022 {
1023   if(!aop)
1024     return -1;
1025
1026   if(aop->type !=  AOP_REG)
1027     return -2;
1028         
1029   return aop->aopu.aop_reg[offset]->rIdx;
1030
1031 }
1032 #endif
1033
1034 /*-----------------------------------------------------------------*/
1035 /* regsInCommon - two operands have some registers in common       */
1036 /*-----------------------------------------------------------------*/
1037 static bool regsInCommon (operand *op1, operand *op2)
1038 {
1039     symbol *sym1, *sym2;
1040     int i;
1041
1042     /* if they have registers in common */
1043     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1044         return FALSE ;
1045
1046     sym1 = OP_SYMBOL(op1);
1047     sym2 = OP_SYMBOL(op2);
1048
1049     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1050         return FALSE ;
1051
1052     for (i = 0 ; i < sym1->nRegs ; i++) {
1053         int j;
1054         if (!sym1->regs[i])
1055             continue ;
1056
1057         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1058             if (!sym2->regs[j])
1059                 continue ;
1060
1061             if (sym2->regs[j] == sym1->regs[i])
1062                 return TRUE ;
1063         }
1064     }
1065
1066     return FALSE ;
1067 }
1068
1069 /*-----------------------------------------------------------------*/
1070 /* operandsEqu - equivalent                                        */
1071 /*-----------------------------------------------------------------*/
1072 static bool operandsEqu ( operand *op1, operand *op2)
1073 {
1074     symbol *sym1, *sym2;
1075
1076     /* if they not symbols */
1077     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1078         return FALSE;
1079
1080     sym1 = OP_SYMBOL(op1);
1081     sym2 = OP_SYMBOL(op2);
1082
1083     /* if both are itemps & one is spilt
1084        and the other is not then false */
1085     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1086         sym1->isspilt != sym2->isspilt )
1087         return FALSE ;
1088
1089     /* if they are the same */
1090     if (sym1 == sym2)
1091         return TRUE ;
1092
1093     if (sym1->rname[0] && sym2->rname[0]
1094         && strcmp (sym1->rname, sym2->rname) == 0)
1095         return TRUE;
1096
1097
1098     /* if left is a tmp & right is not */
1099     if (IS_ITEMP(op1)  && 
1100         !IS_ITEMP(op2) &&
1101         sym1->isspilt  &&
1102         (sym1->usl.spillLoc == sym2))
1103         return TRUE;
1104
1105     if (IS_ITEMP(op2)  && 
1106         !IS_ITEMP(op1) &&
1107         sym2->isspilt  &&
1108         sym1->level > 0 &&
1109         (sym2->usl.spillLoc == sym1))
1110         return TRUE ;
1111
1112     return FALSE ;
1113 }
1114
1115 /*-----------------------------------------------------------------*/
1116 /* pic16_sameRegs - two asmops have the same registers                   */
1117 /*-----------------------------------------------------------------*/
1118 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1119 {
1120     int i;
1121
1122     if (aop1 == aop2)
1123         return TRUE ;
1124
1125     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1126                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1127
1128     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1129
1130     if (aop1->type != AOP_REG ||
1131         aop2->type != AOP_REG )
1132         return FALSE ;
1133
1134     /* This is a bit too restrictive if one is a subset of the other...
1135     if (aop1->size != aop2->size )
1136         return FALSE ;
1137     */
1138
1139     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1140 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1141
1142 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1143         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1144             return FALSE ;
1145     }
1146
1147     return TRUE ;
1148 }
1149
1150 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1151 {
1152     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1153                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1154
1155     if(aop1 == aop2)return TRUE;
1156     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1157       
1158       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1159     
1160   return TRUE;
1161 }
1162
1163
1164 /*-----------------------------------------------------------------*/
1165 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1166 /*-----------------------------------------------------------------*/
1167 void pic16_aopOp (operand *op, iCode *ic, bool result)
1168 {
1169     asmop *aop;
1170     symbol *sym;
1171     int i;
1172
1173     if (!op)
1174         return ;
1175
1176     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1177
1178     /* if this a literal */
1179     if (IS_OP_LITERAL(op)) {
1180         op->aop = aop = newAsmop(AOP_LIT);
1181         aop->aopu.aop_lit = op->operand.valOperand;
1182         aop->size = getSize(operandType(op));
1183         return;
1184     }
1185
1186     {
1187       sym_link *type = operandType(op);
1188 #if 0
1189       if(IS_PTR_CONST(type))
1190 #else
1191       if(IS_CODEPTR(type))
1192 #endif
1193         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1194     }
1195
1196     /* if already has a asmop then continue */
1197     if (op->aop)
1198         return ;
1199
1200     /* if the underlying symbol has a aop */
1201     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1202       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1203         op->aop = OP_SYMBOL(op)->aop;
1204         return;
1205     }
1206
1207     /* if this is a true symbol */
1208     if (IS_TRUE_SYMOP(op)) {    
1209         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1210       op->aop = aopForSym(ic, op, result);
1211       return ;
1212     }
1213
1214     /* this is a temporary : this has
1215     only four choices :
1216     a) register
1217     b) spillocation
1218     c) rematerialize 
1219     d) conditional   
1220     e) can be a return use only */
1221
1222     sym = OP_SYMBOL(op);
1223
1224     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1225     /* if the type is a conditional */
1226     if (sym->regType == REG_CND) {
1227         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1228         aop->size = 0;
1229         return;
1230     }
1231
1232     /* if it is spilt then two situations
1233     a) is rematerialize 
1234     b) has a spill location */
1235     if (sym->isspilt || sym->nRegs == 0) {
1236
1237 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1238       DEBUGpic16_emitcode(";","%d",__LINE__);
1239         /* rematerialize it NOW */
1240         if (sym->remat) {
1241
1242             sym->aop = op->aop = aop = aopForRemat (op, result);
1243 //            aop->size = getSize(sym->type);
1244 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1245             return;
1246         }
1247
1248 #if 1
1249         if (sym->accuse) {
1250             int i;
1251             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1252             aop->size = getSize(sym->type);
1253             for ( i = 0 ; i < 1 ; i++ ) {
1254                 aop->aopu.aop_str[i] = accUse[i];
1255 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1256             }
1257             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1258             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1259             return;  
1260         }
1261 #endif
1262
1263 #if 1
1264         if (sym->ruonly) {
1265           /*
1266           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1267           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1268           //pic16_allocDirReg (IC_LEFT(ic));
1269           aop->size = getSize(sym->type);
1270           */
1271
1272           unsigned i;
1273
1274           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1275           aop->size = getSize(sym->type);
1276           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1277             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1278
1279           DEBUGpic16_emitcode(";","%d",__LINE__);
1280           return;
1281         }
1282 #endif
1283         /* else spill location  */
1284         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1285             /* force a new aop if sizes differ */
1286             sym->usl.spillLoc->aop = NULL;
1287         }
1288
1289 #if 0
1290         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1291                             __FUNCTION__,__LINE__,
1292                             sym->usl.spillLoc->rname,
1293                             sym->rname, sym->usl.spillLoc->offset);
1294 #endif
1295
1296         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1297         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1298           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1299           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1300                                                   getSize(sym->type), 
1301                                                   sym->usl.spillLoc->offset, op);
1302         } else if (getSize(sym->type) <= 1) {
1303           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1304           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1305           assert (getSize(sym->type) <= 1);
1306           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1307           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1308         } else {
1309           /* We need some kind of dummy area for getSize(sym->type) byte,
1310            * use WREG for all storage locations.
1311            * XXX: This only works if we are implementing a `dummy read',
1312            *      the stored value will not be retrievable...
1313            *      See #1503234 for a case requiring this. */
1314           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1315           aop->size = getSize(sym->type);
1316           for ( i = 0 ; i < aop->size ;i++)
1317             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1318         }
1319         aop->size = getSize(sym->type);
1320
1321         return;
1322     }
1323
1324     {
1325       sym_link *type = operandType(op);
1326 #if 0
1327       if(IS_PTR_CONST(type)) 
1328 #else
1329       if(IS_CODEPTR(type)) 
1330 #endif
1331         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1332     }
1333
1334     /* must be in a register */
1335     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1336     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1337     aop->size = sym->nRegs;
1338     for ( i = 0 ; i < sym->nRegs ;i++)
1339         aop->aopu.aop_reg[i] = sym->regs[i];
1340 }
1341
1342 /*-----------------------------------------------------------------*/
1343 /* pic16_freeAsmop - free up the asmop given to an operand               */
1344 /*----------------------------------------------------------------*/
1345 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1346 {   
1347     asmop *aop ;
1348
1349     if (!op)
1350         aop = aaop;
1351     else 
1352         aop = op->aop;
1353
1354     if (!aop)
1355         return ;
1356
1357     if (aop->freed)
1358         goto dealloc; 
1359
1360     aop->freed = 1;
1361
1362     /* depending on the asmop type only three cases need work AOP_RO
1363        , AOP_R1 && AOP_STK */
1364 #if 1
1365     switch (aop->type) {
1366         case AOP_FSR0 :
1367             if (_G.fsr0Pushed ) {
1368                 if (pop) {
1369                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1370                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1371 //                    pic16_emitcode ("pop","ar0");
1372                     _G.fsr0Pushed--;
1373                 }
1374             }
1375             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1376             break;
1377
1378         case AOP_FSR2 :
1379             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1380             break;
1381
1382         case AOP_R0 :
1383             if (_G.r0Pushed ) {
1384                 if (pop) {
1385                     pic16_emitcode ("pop","ar0");     
1386                     _G.r0Pushed--;
1387                 }
1388             }
1389             bitVectUnSetBit(ic->rUsed,R0_IDX);
1390             break;
1391
1392         case AOP_R1 :
1393             if (_G.r1Pushed ) {
1394                 if (pop) {
1395                     pic16_emitcode ("pop","ar1");
1396                     _G.r1Pushed--;
1397                 }
1398             }
1399             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1400             break;
1401
1402         case AOP_STA:
1403           {
1404             int i;
1405
1406               /* we must store the result on stack */
1407               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1408                 // operands on stack are accessible via "FSR2 + index" with index
1409                 // starting at 2 for arguments and growing from 0 downwards for
1410                 // local variables (index == 0 is not assigned so we add one here)
1411                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1412                 if (soffs <= 0) {
1413                   assert (soffs < 0);
1414                   soffs++;
1415                 } // if
1416                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1417                 for(i=0;i<aop->size;i++) {
1418                   /* initialise for stack access via frame pointer */
1419                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1420                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1421                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1422                 }
1423         
1424                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1425               }
1426
1427               if(!_G.resDirect) {
1428                 for(i=0;i<aop->size;i++) {
1429                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1430
1431                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1432                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1433 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1434                   }
1435                 }
1436                 
1437                 {
1438                   regs *sr;
1439                   
1440                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1441                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1442                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1443                       deleteSetItem( &_G.sregsAllocSet, sr );
1444                     }
1445                 }
1446               }
1447               _G.resDirect = 0;
1448           }
1449           break;
1450 #if 0
1451         case AOP_STK :
1452         {
1453             int sz = aop->size;    
1454             int stk = aop->aopu.aop_stk + aop->size;
1455             bitVectUnSetBit(ic->rUsed,R0_IDX);
1456             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1457
1458             getFreePtr(ic,&aop,FALSE);
1459             
1460             if (options.stack10bit)
1461             {
1462                 /* I'm not sure what to do here yet... */
1463                 /* #STUB */
1464                 fprintf(stderr, 
1465                         "*** Warning: probably generating bad code for "
1466                         "10 bit stack mode.\n");
1467             }
1468             
1469             if (stk) {
1470                 pic16_emitcode ("mov","a,_bp");
1471                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1472                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1473             } else {
1474                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1475             }
1476
1477             while (sz--) {
1478                 pic16_emitcode("pop","acc");
1479                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1480                 if (!sz) break;
1481                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1482             }
1483             op->aop = aop;
1484             pic16_freeAsmop(op,NULL,ic,TRUE);
1485             if (_G.r0Pushed) {
1486                 pic16_emitcode("pop","ar0");
1487                 _G.r0Pushed--;
1488             }
1489
1490             if (_G.r1Pushed) {
1491                 pic16_emitcode("pop","ar1");
1492                 _G.r1Pushed--;
1493             }       
1494         }
1495 #endif
1496
1497     }
1498 #endif
1499
1500 dealloc:
1501     /* all other cases just dealloc */
1502     if (op ) {
1503         op->aop = NULL;
1504         if (IS_SYMOP(op)) {
1505             OP_SYMBOL(op)->aop = NULL;    
1506             /* if the symbol has a spill */
1507             if (SPIL_LOC(op))
1508                 SPIL_LOC(op)->aop = NULL;
1509         }
1510     }
1511 }
1512
1513 /*-----------------------------------------------------------------*/
1514 /* pic16_aopGet - for fetching value of the aop                          */
1515 /*-----------------------------------------------------------------*/
1516 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1517 {
1518     char *s = buffer ;
1519     char *rs;
1520
1521     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1522
1523     /* offset is greater than size then zero */
1524     if (offset > (aop->size - 1) &&
1525         aop->type != AOP_LIT)
1526         return zero;
1527
1528     /* depending on type */
1529     switch (aop->type) {
1530
1531     case AOP_FSR0:
1532     case AOP_FSR2:
1533       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1534       rs = Safe_calloc(1, strlen(s)+1);
1535       strcpy(rs, s);
1536       return (rs);
1537       
1538 #if 0
1539       /* if we need to increment it */
1540       while (offset > aop->coff)
1541         {
1542           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1543           aop->coff++;
1544         }
1545
1546       while (offset < aop->coff)
1547         {
1548           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1549           aop->coff--;
1550         }
1551       aop->coff = offset;
1552       if (aop->paged)
1553         {
1554           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1555           return (dname ? "acc" : "a");
1556         }
1557       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1558       rs = Safe_calloc (1, strlen (s) + 1);
1559       strcpy (rs, s);
1560       return rs;
1561 #endif
1562
1563         
1564     case AOP_IMMD:
1565         if (bit16) 
1566             sprintf (s,"%s",aop->aopu.aop_immd);
1567         else
1568             if (offset) 
1569                 sprintf(s,"(%s >> %d)",
1570                         aop->aopu.aop_immd,
1571                         offset*8);
1572             else
1573                 sprintf(s,"%s",
1574                         aop->aopu.aop_immd);
1575         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1576         rs = Safe_calloc(1,strlen(s)+1);
1577         strcpy(rs,s);   
1578         return rs;
1579         
1580     case AOP_DIR:
1581       if (offset) {
1582         sprintf(s,"(%s + %d)",
1583                 aop->aopu.aop_dir,
1584                 offset);
1585         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1586       } else
1587             sprintf(s,"%s",aop->aopu.aop_dir);
1588         rs = Safe_calloc(1,strlen(s)+1);
1589         strcpy(rs,s);   
1590         return rs;
1591         
1592     case AOP_REG:
1593       return aop->aopu.aop_reg[offset]->name;
1594         
1595     case AOP_CRY:
1596       return aop->aopu.aop_dir;
1597         
1598     case AOP_ACC:
1599         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1600 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1601 //        assert( 0 );
1602 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1603         rs = Safe_strdup("WREG");
1604         return (rs);
1605
1606     case AOP_LIT:
1607         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1608         rs = Safe_calloc(1,strlen(s)+1);
1609         strcpy(rs,s);   
1610         return rs;
1611         
1612     case AOP_STR:
1613         aop->coff = offset ;
1614
1615 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1616 //          dname)
1617 //          return "acc";
1618         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1619           aop->type = AOP_ACC;
1620           return Safe_strdup("_WREG");
1621         }
1622         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1623         
1624         return aop->aopu.aop_str[offset];
1625         
1626     case AOP_PCODE:
1627       {
1628         pCodeOp *pcop = aop->aopu.pcop;
1629         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1630         if(pcop->name) {
1631           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1632           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1633           if (offset) {
1634             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1635           } else {
1636             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1637           }
1638         } else
1639           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1640
1641       }
1642       rs = Safe_calloc(1,strlen(s)+1);
1643       strcpy(rs,s);   
1644       return rs;
1645
1646 #if 0
1647     case AOP_PAGED:
1648       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1649       if (offset) {
1650         sprintf(s,"(%s + %d)",
1651                 aop->aopu.aop_dir,
1652                 offset);
1653       } else
1654             sprintf(s,"%s",aop->aopu.aop_dir);
1655       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1656       rs = Safe_calloc(1,strlen(s)+1);
1657       strcpy(rs,s);   
1658       return rs;
1659 #endif
1660
1661     case AOP_STA:
1662         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1663         return (rs);
1664         
1665     case AOP_STK:
1666 //        pCodeOp *pcop = aop->aop
1667         break;
1668
1669     }
1670
1671     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1672     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1673            "aopget got unsupported aop->type");
1674     exit(0);
1675 }
1676
1677
1678
1679 /* lock has the following meaning: When allocating temporary registers
1680  * for stack variables storage, the value of the temporary register is
1681  * saved on stack. Its value is restored at the end. This procedure is
1682  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1683  * a possibility that before a call to pic16_aopOp, a temporary register
1684  * is allocated for a while and it is freed after some time, this will
1685  * mess the stack and values will not be restored properly. So use lock=1
1686  * to allocate temporary registers used internally by the programmer, and
1687  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1688  * to inform the compiler developer about a possible bug. This is an internal
1689  * feature for developing the compiler -- VR */
1690  
1691 int _TempReg_lock = 0;
1692 /*-----------------------------------------------------------------*/
1693 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1694 /*-----------------------------------------------------------------*/
1695 pCodeOp *pic16_popGetTempReg(int lock)
1696 {
1697   pCodeOp *pcop=NULL;
1698   symbol *cfunc;
1699
1700 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1701     if(_TempReg_lock) {
1702 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1703     }
1704     
1705     _TempReg_lock += lock;
1706     
1707     cfunc = currFunc;
1708     currFunc = NULL;
1709
1710 #if 0
1711         {
1712           regs *rr;
1713           int i;
1714
1715                 /* this code might seem better but it does the *same* job with
1716                  * the old code, it all depends on ralloc.c to get a free/unused
1717                  * register */
1718          
1719                 i=0;
1720                 while(i < pic16_nRegs) {
1721                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1722                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1723                         if((!rr || (rr && rr->isFree))
1724                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1725                                 pcop = pic16_newpCodeOpReg( i );
1726                                 PCOR(pcop)->r->wasUsed = 1;
1727                                 PCOR(pcop)->r->isFree = 0;
1728                                 break;
1729                         }
1730                         i++;
1731                 }
1732
1733                 if(pcop) {
1734                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1735                 }
1736         }
1737 #else
1738     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1739     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1740       PCOR(pcop)->r->wasUsed=1;
1741       PCOR(pcop)->r->isFree=0;
1742
1743       /* push value on stack */
1744       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1745     }
1746 #endif
1747
1748     currFunc = cfunc;
1749
1750   return pcop;
1751 }
1752
1753 /*-----------------------------------------------------------------*/
1754 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1755 /*                           is not part of f, but don't save if   */
1756 /*                           inside v                              */
1757 /*-----------------------------------------------------------------*/
1758 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1759 {
1760   pCodeOp *pcop=NULL;
1761   symbol *cfunc;
1762   int i;
1763
1764 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1765
1766     if(_TempReg_lock) {
1767 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1768     }
1769
1770     _TempReg_lock += lock;
1771
1772     cfunc = currFunc;
1773     currFunc = NULL;
1774
1775     i = bitVectFirstBit(f);
1776     while(i < 128) {
1777
1778       /* bypass registers that are used by function */
1779       if(!bitVectBitValue(f, i)) {
1780       
1781         /* bypass registers that are already allocated for stack access */
1782         if(!bitVectBitValue(v, i))  {
1783         
1784 //          debugf("getting register rIdx = %d\n", i);
1785           /* ok, get the operand */
1786           pcop = pic16_newpCodeOpReg( i );
1787     
1788           /* should never by NULL */
1789           assert( pcop != NULL );
1790
1791           
1792           /* sanity check */
1793           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1794             int found=0;
1795             
1796               PCOR(pcop)->r->wasUsed=1;
1797               PCOR(pcop)->r->isFree=0;
1798
1799
1800               {
1801                 regs *sr;
1802               
1803                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1804
1805                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1806                       /* already used in previous steps, break */
1807                       found=1;          
1808                       break;
1809                     }
1810                   }
1811               }
1812
1813               /* caller takes care of the following */
1814 //              bitVectSetBit(v, i);
1815
1816               if(!found) {
1817                 /* push value on stack */
1818                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1819                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1820               }
1821           
1822             break;
1823           }
1824         }
1825       }
1826       i++;
1827     }
1828
1829     currFunc = cfunc;
1830
1831   return pcop;
1832 }
1833
1834
1835 /*-----------------------------------------------------------------*/
1836 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1837 /*-----------------------------------------------------------------*/
1838 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1839 {
1840   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1841
1842   _TempReg_lock -= lock;
1843
1844   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1845     PCOR(pcop)->r->isFree = 1;
1846
1847     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1848   }
1849 }
1850 /*-----------------------------------------------------------------*/
1851 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1852 /*-----------------------------------------------------------------*/
1853 pCodeOp *pic16_popGetLabel(int key)
1854 {
1855
1856   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1857
1858   if(key>max_key)
1859     max_key = key;
1860
1861   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1862 }
1863
1864 /*-----------------------------------------------------------------*/
1865 /* pic16_popCopyReg - copy a pcode operator                              */
1866 /*-----------------------------------------------------------------*/
1867 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1868 {
1869   pCodeOpReg *pcor;
1870
1871   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1872   memcpy (pcor, pc, sizeof (pCodeOpReg));
1873   pcor->r->wasUsed = 1;
1874   
1875   //pcor->pcop.type = pc->pcop.type;
1876   if(pc->pcop.name) {
1877     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1878       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1879   } else
1880     pcor->pcop.name = NULL;
1881
1882   //pcor->r = pc->r;
1883   //pcor->rIdx = pc->rIdx;
1884   //pcor->r->wasUsed=1;
1885   //pcor->instance = pc->instance;
1886
1887 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1888
1889   return PCOP(pcor);
1890 }
1891
1892 /*-----------------------------------------------------------------*/
1893 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1894 /*-----------------------------------------------------------------*/
1895 pCodeOp *pic16_popGetLit(int lit)
1896 {
1897   return pic16_newpCodeOpLit(lit);
1898 }
1899
1900 /* Allow for 12 bit literals (LFSR x, <here!>). */
1901 pCodeOp *pic16_popGetLit12(int lit)
1902 {
1903   return pic16_newpCodeOpLit12(lit);
1904 }
1905
1906 /*-----------------------------------------------------------------*/
1907 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1908 /*-----------------------------------------------------------------*/
1909 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1910 {
1911   return pic16_newpCodeOpLit2(lit, arg2);
1912 }
1913
1914
1915 /*-----------------------------------------------------------------*/
1916 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1917 /*-----------------------------------------------------------------*/
1918 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1919 {
1920   return pic16_newpCodeOpImmd(name, offset,index, 0);
1921 }
1922
1923
1924 /*-----------------------------------------------------------------*/
1925 /* pic16_popGet - asm operator to pcode operator conversion              */
1926 /*-----------------------------------------------------------------*/
1927 pCodeOp *pic16_popGetWithString(char *str)
1928 {
1929   pCodeOp *pcop;
1930
1931
1932   if(!str) {
1933     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1934     exit (1);
1935   }
1936
1937   pcop = pic16_newpCodeOp(str,PO_STR);
1938
1939   return pcop;
1940 }
1941
1942 /*-----------------------------------------------------------------*/
1943 /* pic16_popRegFromString -                                        */
1944 /*-----------------------------------------------------------------*/
1945 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1946 {
1947
1948   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1949   pcop->type = PO_DIR;
1950
1951   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1952   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1953
1954   if(!str)
1955     str = "BAD_STRING";
1956
1957   pcop->name = Safe_calloc(1,strlen(str)+1);
1958   strcpy(pcop->name,str);
1959
1960   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1961
1962   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1963 //  PCOR(pcop)->r->wasUsed = 1;
1964
1965   /* make sure that register doesn't exist,
1966    * and operand isn't NULL
1967    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1968   if((PCOR(pcop)->r == NULL) 
1969     && (op)
1970     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1971 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1972 //              __FUNCTION__, __LINE__, str, size, offset);
1973
1974     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1975     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1976
1977   }
1978   PCOR(pcop)->instance = offset;
1979
1980   return pcop;
1981 }
1982
1983 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1984 {
1985   pCodeOp *pcop;
1986
1987 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1988 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1989         
1990         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1991         PCOR(pcop)->rIdx = rIdx;
1992         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1993         if(!PCOR(pcop)->r)
1994                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1995                 
1996         PCOR(pcop)->r->isFree = 0;
1997         PCOR(pcop)->r->wasUsed = 1;
1998
1999         pcop->type = PCOR(pcop)->r->pc_type;
2000
2001   return pcop;
2002 }
2003
2004 /*---------------------------------------------------------------------------------*/
2005 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2006 /*                 VR 030601                                                       */
2007 /*---------------------------------------------------------------------------------*/
2008 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2009 {
2010   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2011         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2012   return PCOP(pcop2);
2013 }
2014
2015
2016
2017 /*--------------------------------------------------------------------------------.-*/
2018 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2019 /*                  VR 030601 , adapted by Hans Dorn                                */
2020 /*--------------------------------------------------------------------------------.-*/
2021 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2022 {
2023   pCodeOp2 *pcop2;
2024   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2025   return PCOP(pcop2);
2026 }
2027
2028 /*---------------------------------------------------------------------------------*/
2029 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2030 /*                     movff instruction                                           */
2031 /*---------------------------------------------------------------------------------*/
2032 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2033 {
2034   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2035         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2036
2037   return PCOP(pcop2);
2038 }
2039
2040
2041 /*-----------------------------------------------------------------*/
2042 /* pic16_popGet - asm operator to pcode operator conversion              */
2043 /*-----------------------------------------------------------------*/
2044 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2045 {
2046 //  char *s = buffer ;
2047 //  char *rs;
2048   pCodeOp *pcop;
2049
2050     FENTRY2;
2051     
2052       /* offset is greater than size then zero */
2053
2054 //    if (offset > (aop->size - 1) &&
2055 //        aop->type != AOP_LIT)
2056 //      return NULL;  //zero;
2057
2058     /* depending on type */
2059     switch (aop->type) {
2060                 case AOP_R0:
2061                 case AOP_R1:
2062                 case AOP_DPTR:
2063                 case AOP_DPTR2:
2064                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2065                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2066                         assert( 0 );
2067                         return NULL;
2068
2069                 case AOP_FSR0:
2070                 case AOP_FSR2:
2071                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2072                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2073                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2074                         PCOR(pcop)->r->wasUsed = 1;
2075                         PCOR(pcop)->r->isFree = 0;
2076       
2077                         PCOR(pcop)->instance = offset;
2078                         pcop->type = PCOR(pcop)->r->pc_type;
2079                         return (pcop);
2080
2081                 case AOP_IMMD:
2082                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2083                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2084
2085                 case AOP_STA:
2086                         /* pCodeOp is already allocated from aopForSym */
2087                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2088                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2089                         return (pcop);
2090       
2091                 case AOP_ACC:
2092                         {
2093                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2094
2095                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2096
2097                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2098         
2099                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2100                                 PCOR(pcop)->rIdx = rIdx;
2101                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2102                                 PCOR(pcop)->r->wasUsed=1;
2103                                 PCOR(pcop)->r->isFree=0;
2104
2105                                 PCOR(pcop)->instance = offset;
2106                                 pcop->type = PCOR(pcop)->r->pc_type;
2107 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2108                                 return pcop;
2109
2110
2111 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2112 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2113
2114 //      assert( 0 );
2115                         }
2116         
2117     case AOP_DIR:
2118       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2119       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2120         
2121 #if 0
2122     case AOP_PAGED:
2123       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2124       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2125 #endif
2126
2127     case AOP_REG:
2128       {
2129         int rIdx;
2130
2131 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
2132 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
2133         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2134
2135         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2136         
2137         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2138 //      pcop->type = PO_GPR_REGISTER;
2139         PCOR(pcop)->rIdx = rIdx;
2140         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2141         PCOR(pcop)->r->wasUsed=1;
2142         PCOR(pcop)->r->isFree=0;
2143
2144         PCOR(pcop)->instance = offset;
2145         pcop->type = PCOR(pcop)->r->pc_type;
2146         
2147         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2148 //      rs = aop->aopu.aop_reg[offset]->name;
2149 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2150         return pcop;
2151       }
2152
2153     case AOP_CRY:
2154         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2155
2156       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2157       PCOR(pcop)->instance = offset;
2158       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2159       //if(PCOR(pcop)->r == NULL)
2160       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2161       return pcop;
2162         
2163     case AOP_LIT:
2164         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2165       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2166
2167     case AOP_STR:
2168       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2169       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2170
2171       /*
2172       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2173       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2174       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2175       pcop->type = PCOR(pcop)->r->pc_type;
2176       pcop->name = PCOR(pcop)->r->name;
2177
2178       return pcop;
2179       */
2180
2181     case AOP_PCODE:
2182       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2183                           __LINE__, 
2184                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2185       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2186       switch( aop->aopu.pcop->type ) {
2187         case PO_DIR: PCOR(pcop)->instance += offset; break;
2188         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2189         case PO_WREG:
2190             assert (offset==0);
2191             break;
2192         default:
2193           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2194           assert( 0 );  /* should never reach here */;
2195       }
2196       return pcop;
2197     }
2198
2199     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2200            "pic16_popGet got unsupported aop->type");
2201     exit(0);
2202 }
2203 /*-----------------------------------------------------------------*/
2204 /* pic16_aopPut - puts a string for a aop                                */
2205 /*-----------------------------------------------------------------*/
2206 void pic16_aopPut (asmop *aop, char *s, int offset)
2207 {
2208     char *d = buffer ;
2209     symbol *lbl ;
2210
2211     return;
2212
2213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2214
2215     if (aop->size && offset > ( aop->size - 1)) {
2216         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2217                "pic16_aopPut got offset > aop->size");
2218         exit(0);
2219     }
2220
2221     /* will assign value to value */
2222     /* depending on where it is ofcourse */
2223     switch (aop->type) {
2224     case AOP_DIR:
2225       if (offset) {
2226         sprintf(d,"(%s + %d)",
2227                 aop->aopu.aop_dir,offset);
2228         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2229
2230       } else
2231             sprintf(d,"%s",aop->aopu.aop_dir);
2232         
2233         if (strcmp(d,s)) {
2234           DEBUGpic16_emitcode(";","%d",__LINE__);
2235           if(strcmp(s,"W"))
2236             pic16_emitcode("movf","%s,w",s);
2237           pic16_emitcode("movwf","%s",d);
2238
2239           if(strcmp(s,"W")) {
2240             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2241             if(offset >= aop->size) {
2242               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2243               break;
2244             } else
2245               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2246           }
2247
2248           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2249
2250
2251         }
2252         break;
2253         
2254     case AOP_REG:
2255       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2256         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2257           /*
2258             if (*s == '@'           ||
2259                 strcmp(s,"r0") == 0 ||
2260                 strcmp(s,"r1") == 0 ||
2261                 strcmp(s,"r2") == 0 ||
2262                 strcmp(s,"r3") == 0 ||
2263                 strcmp(s,"r4") == 0 ||
2264                 strcmp(s,"r5") == 0 ||
2265                 strcmp(s,"r6") == 0 || 
2266                 strcmp(s,"r7") == 0 )
2267                 pic16_emitcode("mov","%s,%s  ; %d",
2268                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2269             else
2270           */
2271
2272           if(strcmp(s,"W")==0 )
2273             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2274
2275           pic16_emitcode("movwf","%s",
2276                    aop->aopu.aop_reg[offset]->name);
2277
2278           if(strcmp(s,zero)==0) {
2279             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2280
2281           } else if(strcmp(s,"W")==0) {
2282             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2283             pcop->type = PO_GPR_REGISTER;
2284
2285             PCOR(pcop)->rIdx = -1;
2286             PCOR(pcop)->r = NULL;
2287
2288             DEBUGpic16_emitcode(";","%d",__LINE__);
2289             pcop->name = Safe_strdup(s);
2290             pic16_emitpcode(POC_MOVFW,pcop);
2291             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2292           } else if(strcmp(s,one)==0) {
2293             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2294             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2295           } else {
2296             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2297           }
2298         }
2299         break;
2300         
2301     case AOP_DPTR:
2302     case AOP_DPTR2:
2303     
2304     if (aop->type == AOP_DPTR2)
2305     {
2306         genSetDPTR(1);
2307     }
2308     
2309         if (aop->code) {
2310             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2311                    "pic16_aopPut writting to code space");
2312             exit(0);
2313         }
2314         
2315         while (offset > aop->coff) {
2316             aop->coff++;
2317             pic16_emitcode ("inc","dptr");
2318         }
2319         
2320         while (offset < aop->coff) {
2321             aop->coff-- ;
2322             pic16_emitcode("lcall","__decdptr");
2323         }
2324         
2325         aop->coff = offset;
2326         
2327         /* if not in accumulater */
2328         MOVA(s);        
2329         
2330         pic16_emitcode ("movx","@dptr,a");
2331         
2332     if (aop->type == AOP_DPTR2)
2333     {
2334         genSetDPTR(0);
2335     }
2336         break;
2337         
2338     case AOP_R0:
2339     case AOP_R1:
2340         while (offset > aop->coff) {
2341             aop->coff++;
2342             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2343         }
2344         while (offset < aop->coff) {
2345             aop->coff-- ;
2346             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2347         }
2348         aop->coff = offset;
2349         
2350         if (aop->paged) {
2351             MOVA(s);           
2352             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2353             
2354         } else
2355             if (*s == '@') {
2356                 MOVA(s);
2357                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2358             } else
2359                 if (strcmp(s,"r0") == 0 ||
2360                     strcmp(s,"r1") == 0 ||
2361                     strcmp(s,"r2") == 0 ||
2362                     strcmp(s,"r3") == 0 ||
2363                     strcmp(s,"r4") == 0 ||
2364                     strcmp(s,"r5") == 0 ||
2365                     strcmp(s,"r6") == 0 || 
2366                     strcmp(s,"r7") == 0 ) {
2367                     char buffer[10];
2368                     sprintf(buffer,"a%s",s);
2369                     pic16_emitcode("mov","@%s,%s",
2370                              aop->aopu.aop_ptr->name,buffer);
2371                 } else
2372                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2373         
2374         break;
2375         
2376     case AOP_STK:
2377         if (strcmp(s,"a") == 0)
2378             pic16_emitcode("push","acc");
2379         else
2380             pic16_emitcode("push","%s",s);
2381         
2382         break;
2383         
2384     case AOP_CRY:
2385         /* if bit variable */
2386         if (!aop->aopu.aop_dir) {
2387             pic16_emitcode("clr","a");
2388             pic16_emitcode("rlc","a");
2389         } else {
2390             if (s == zero) 
2391                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2392             else
2393                 if (s == one)
2394                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2395                 else
2396                     if (!strcmp(s,"c"))
2397                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2398                     else {
2399                         lbl = newiTempLabel(NULL);
2400                         
2401                         if (strcmp(s,"a")) {
2402                             MOVA(s);
2403                         }
2404                         pic16_emitcode("clr","c");
2405                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2406                         pic16_emitcode("cpl","c");
2407                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2408                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2409                     }
2410         }
2411         break;
2412         
2413     case AOP_STR:
2414         aop->coff = offset;
2415         if (strcmp(aop->aopu.aop_str[offset],s))
2416             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2417         break;
2418         
2419     case AOP_ACC:
2420         aop->coff = offset;
2421         if (!offset && (strcmp(s,"acc") == 0))
2422             break;
2423         
2424         if (strcmp(aop->aopu.aop_str[offset],s))
2425             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2426         break;
2427
2428     default :
2429         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2430 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2431 //             "pic16_aopPut got unsupported aop->type");
2432 //      exit(0);    
2433     }    
2434
2435 }
2436
2437 /*-----------------------------------------------------------------*/
2438 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2439 /*-----------------------------------------------------------------*/
2440 void pic16_mov2w (asmop *aop, int offset)
2441 {
2442   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2443
2444   if(is_LitAOp(aop))
2445     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2446   else
2447     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2448 }
2449
2450 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2451 {
2452   if(is_LitAOp(src)) {
2453     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2454     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2455   } else {
2456     if(pic16_sameRegsOfs(src, dst, offset))return;
2457     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2458                       pic16_popGet(dst, offset)));
2459   }
2460 }
2461
2462 static void pic16_movLit2f(pCodeOp *pc, int lit)
2463 {
2464   if (0 == (lit & 0x00ff))
2465   {
2466     pic16_emitpcode (POC_CLRF, pc);
2467   } else if (0xff == (lit & 0x00ff))
2468   {
2469     pic16_emitpcode (POC_SETF, pc);
2470   } else {
2471     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2472     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2473   }
2474 }
2475
2476 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2477 {
2478   if(is_LitAOp(src)) {
2479     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2480     pic16_emitpcode(POC_MOVWF, dst);
2481   } else {
2482     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2483   }
2484 }
2485
2486 void pic16_testStackOverflow(void)
2487 {
2488 #define GSTACK_TEST_NAME        "_gstack_test"
2489
2490   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2491   
2492   {
2493     symbol *sym;
2494
2495       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2496       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2497 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2498       checkAddSym(&externs, sym);
2499   }
2500
2501 }
2502
2503 /* push pcop into stack */
2504 void pic16_pushpCodeOp(pCodeOp *pcop)
2505 {
2506 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2507   if (pcop->type == PO_LITERAL) {
2508     pic16_emitpcode(POC_MOVLW, pcop);
2509     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2510   } else {
2511     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2512   }
2513   if(pic16_options.gstack)
2514     pic16_testStackOverflow();
2515     
2516 }
2517
2518 /* pop pcop from stack */
2519 void pic16_poppCodeOp(pCodeOp *pcop)
2520 {
2521   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2522   if(pic16_options.gstack)
2523     pic16_testStackOverflow();
2524 }
2525
2526
2527 /*-----------------------------------------------------------------*/
2528 /* pushw - pushes wreg to stack                                    */
2529 /*-----------------------------------------------------------------*/
2530 void pushw(void)
2531 {
2532   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2533   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2534   if(pic16_options.gstack)
2535     pic16_testStackOverflow();
2536 }
2537
2538                 
2539 /*-----------------------------------------------------------------*/
2540 /* pushaop - pushes aop to stack                                   */
2541 /*-----------------------------------------------------------------*/
2542 void pushaop(asmop *aop, int offset)
2543 {
2544   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2545
2546   if(_G.resDirect)return;
2547   
2548   if(is_LitAOp(aop)) {
2549     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2550     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2551   } else {
2552     pic16_emitpcode(POC_MOVFF,
2553       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2554   }
2555
2556   if(pic16_options.gstack)
2557     pic16_testStackOverflow();
2558 }
2559
2560 /*-----------------------------------------------------------------*/
2561 /* popaop - pops aop from stack                                    */
2562 /*-----------------------------------------------------------------*/
2563 void popaop(asmop *aop, int offset)
2564 {
2565   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2566   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2567   if(pic16_options.gstack)
2568     pic16_testStackOverflow();
2569 }
2570
2571 void popaopidx(asmop *aop, int offset, int index)
2572 {
2573   int ofs=1;
2574
2575     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2576
2577     if(STACK_MODEL_LARGE)ofs++;
2578
2579     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2580     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2581     if(pic16_options.gstack)
2582       pic16_testStackOverflow();
2583 }
2584
2585 #if !(USE_GENERIC_SIGNED_SHIFT)
2586 /*-----------------------------------------------------------------*/
2587 /* reAdjustPreg - points a register back to where it should        */
2588 /*-----------------------------------------------------------------*/
2589 static void reAdjustPreg (asmop *aop)
2590 {
2591     int size ;
2592
2593     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2594     aop->coff = 0;
2595     if ((size = aop->size) <= 1)
2596         return ;
2597     size-- ;
2598     switch (aop->type) {
2599         case AOP_R0 :
2600         case AOP_R1 :
2601             while (size--)
2602                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2603             break;          
2604         case AOP_DPTR :
2605         case AOP_DPTR2:
2606             if (aop->type == AOP_DPTR2)
2607             {
2608                 genSetDPTR(1);
2609             } 
2610             while (size--)
2611             {
2612                 pic16_emitcode("lcall","__decdptr");
2613             }
2614                 
2615             if (aop->type == AOP_DPTR2)
2616             {
2617                 genSetDPTR(0);
2618             }                
2619             break;  
2620
2621     }   
2622
2623 }
2624 #endif
2625
2626 #if 0
2627 /*-----------------------------------------------------------------*/
2628 /* opIsGptr: returns non-zero if the passed operand is             */   
2629 /* a generic pointer type.                                         */
2630 /*-----------------------------------------------------------------*/ 
2631 static int opIsGptr(operand *op)
2632 {
2633     sym_link *type = operandType(op);
2634     
2635     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2636     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2637     {
2638         return 1;
2639     }
2640     return 0;        
2641 }
2642 #endif
2643
2644 /*-----------------------------------------------------------------*/
2645 /* pic16_getDataSize - get the operand data size                         */
2646 /*-----------------------------------------------------------------*/
2647 int pic16_getDataSize(operand *op)
2648 {
2649     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2650
2651
2652     return AOP_SIZE(op);
2653
2654     // tsd- in the pic port, the genptr size is 1, so this code here
2655     // fails. ( in the 8051 port, the size was 4).
2656 #if 0
2657     int size;
2658     size = AOP_SIZE(op);
2659     if (size == GPTRSIZE)
2660     {
2661         sym_link *type = operandType(op);
2662         if (IS_GENPTR(type))
2663         {
2664             /* generic pointer; arithmetic operations
2665              * should ignore the high byte (pointer type).
2666              */
2667             size--;
2668     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2669         }
2670     }
2671     return size;
2672 #endif
2673 }
2674
2675 /*-----------------------------------------------------------------*/
2676 /* pic16_outAcc - output Acc                                             */
2677 /*-----------------------------------------------------------------*/
2678 void pic16_outAcc(operand *result)
2679 {
2680   int size,offset;
2681   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2682   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2683
2684
2685   size = pic16_getDataSize(result);
2686   if(size){
2687     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2688     size--;
2689     offset = 1;
2690     /* unsigned or positive */
2691     while(size--)
2692       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2693   }
2694
2695 }
2696
2697 /*-----------------------------------------------------------------*/
2698 /* pic16_outBitC - output a bit C                                  */
2699 /*                 Move to result the value of Carry flag -- VR    */
2700 /*-----------------------------------------------------------------*/
2701 void pic16_outBitC(operand *result)
2702 {
2703   int i;
2704
2705     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2706
2707     /* if the result is bit */
2708     if (AOP_TYPE(result) == AOP_CRY) {
2709         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2710         pic16_aopPut(AOP(result),"c",0);
2711     } else {
2712
2713         i = AOP_SIZE(result);
2714         while(i--) {
2715                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2716         }
2717         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2718     }
2719 }
2720
2721 /*-----------------------------------------------------------------*/
2722 /* pic16_outBitOp - output a bit from Op                           */
2723 /*                 Move to result the value of set/clr op -- VR    */
2724 /*-----------------------------------------------------------------*/
2725 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2726 {
2727   int i;
2728
2729     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2730
2731     /* if the result is bit */
2732     if (AOP_TYPE(result) == AOP_CRY) {
2733         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2734         pic16_aopPut(AOP(result),"c",0);
2735     } else {
2736
2737         i = AOP_SIZE(result);
2738         while(i--) {
2739                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2740         }
2741         pic16_emitpcode(POC_RRCF, pcop);          
2742         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2743     }
2744 }
2745
2746 /*-----------------------------------------------------------------*/
2747 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2748 /*-----------------------------------------------------------------*/
2749 void pic16_toBoolean(operand *oper)
2750 {
2751     int size = AOP_SIZE(oper) - 1;
2752     int offset = 1;
2753
2754     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2755
2756     if ( AOP_TYPE(oper) != AOP_ACC) {
2757       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2758     }
2759     while (size--) {
2760       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2761     }
2762 }
2763
2764 /*-----------------------------------------------------------------*/
2765 /* genUminusFloat - unary minus for floating points                */
2766 /*-----------------------------------------------------------------*/
2767 static void genUminusFloat(operand *op,operand *result)
2768 {
2769   int size ,offset =0 ;
2770   
2771     FENTRY;
2772     /* for this we just need to flip the 
2773     first it then copy the rest in place */
2774     size = AOP_SIZE(op);
2775     assert( size == AOP_SIZE(result) );
2776
2777     while(size--) {
2778       pic16_mov2f(AOP(result), AOP(op), offset);
2779       offset++;
2780     }
2781     
2782     /* toggle the MSB's highest bit */
2783     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2784 }
2785
2786 /*-----------------------------------------------------------------*/
2787 /* genUminus - unary minus code generation                         */
2788 /*-----------------------------------------------------------------*/
2789 static void genUminus (iCode *ic)
2790 {
2791   int size, i;
2792   sym_link *optype, *rtype;
2793   symbol *label;
2794   int needLabel=0;
2795
2796     FENTRY;     
2797     
2798     /* assign asmops */
2799     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2800     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2801
2802     /* if both in bit space then special case */
2803     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2804       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2805         
2806         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2807         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2808         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2809         goto release; 
2810     } 
2811
2812     optype = operandType(IC_LEFT(ic));
2813     rtype = operandType(IC_RESULT(ic));
2814
2815
2816     /* if float then do float stuff */
2817     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2818       if(IS_FIXED(optype))
2819         debugf("implement fixed16x16 type\n", 0);
2820         
2821         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2822         goto release;
2823     }
2824
2825     /* otherwise subtract from zero by taking the 2's complement */
2826     size = AOP_SIZE(IC_LEFT(ic));
2827     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2828     label = newiTempLabel ( NULL );
2829     
2830     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2831       for (i=size-1; i > 0; i--) {
2832         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2833       } // for
2834       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2835       for (i=1; i < size; i++) {
2836         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2837         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2838       } // for
2839     } else {
2840       for (i=size-1; i >= 0; i--) {
2841         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2842         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2843       } // for
2844       if (size > 1) {
2845         for (i=0; i < size-2; i++) {
2846           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2847           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2848         } // for
2849         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2850       } // if
2851       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2852     }
2853     if (needLabel)
2854       pic16_emitpLabel (label->key);
2855
2856 release:
2857     /* release the aops */
2858     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2859     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2860 }
2861
2862 #if 0
2863 /*-----------------------------------------------------------------*/
2864 /* saveRegisters - will look for a call and save the registers     */
2865 /*-----------------------------------------------------------------*/
2866 static void saveRegisters(iCode *lic) 
2867 {
2868     int i;
2869     iCode *ic;
2870     bitVect *rsave;
2871     sym_link *dtype;
2872
2873     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2874     /* look for call */
2875     for (ic = lic ; ic ; ic = ic->next) 
2876         if (ic->op == CALL || ic->op == PCALL)
2877             break;
2878
2879     if (!ic) {
2880         fprintf(stderr,"found parameter push with no function call\n");
2881         return ;
2882     }
2883
2884     /* if the registers have been saved already then
2885     do nothing */
2886     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2887         return ;
2888
2889     /* find the registers in use at this time 
2890     and push them away to safety */
2891     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2892                           ic->rUsed);
2893
2894     ic->regsSaved = 1;
2895     if (options.useXstack) {
2896         if (bitVectBitValue(rsave,R0_IDX))
2897             pic16_emitcode("mov","b,r0");
2898         pic16_emitcode("mov","r0,%s",spname);
2899         for (i = 0 ; i < pic16_nRegs ; i++) {
2900             if (bitVectBitValue(rsave,i)) {
2901                 if (i == R0_IDX)
2902                     pic16_emitcode("mov","a,b");
2903                 else
2904                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2905                 pic16_emitcode("movx","@r0,a");
2906                 pic16_emitcode("inc","r0");
2907             }
2908         }
2909         pic16_emitcode("mov","%s,r0",spname);
2910         if (bitVectBitValue(rsave,R0_IDX))
2911             pic16_emitcode("mov","r0,b");           
2912     }// else
2913     //for (i = 0 ; i < pic16_nRegs ; i++) {
2914     //    if (bitVectBitValue(rsave,i))
2915     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2916     //}
2917
2918     dtype = operandType(IC_LEFT(ic));
2919     if (currFunc && dtype && 
2920         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2921         IFFUNC_ISISR(currFunc->type) &&
2922         !ic->bankSaved) 
2923
2924         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2925
2926 }
2927 /*-----------------------------------------------------------------*/
2928 /* unsaveRegisters - pop the pushed registers                      */
2929 /*-----------------------------------------------------------------*/
2930 static void unsaveRegisters (iCode *ic)
2931 {
2932     int i;
2933     bitVect *rsave;
2934
2935     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2936     /* find the registers in use at this time 
2937     and push them away to safety */
2938     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2939                           ic->rUsed);
2940     
2941     if (options.useXstack) {
2942         pic16_emitcode("mov","r0,%s",spname);   
2943         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2944             if (bitVectBitValue(rsave,i)) {
2945                 pic16_emitcode("dec","r0");
2946                 pic16_emitcode("movx","a,@r0");
2947                 if (i == R0_IDX)
2948                     pic16_emitcode("mov","b,a");
2949                 else
2950                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2951             }       
2952
2953         }
2954         pic16_emitcode("mov","%s,r0",spname);
2955         if (bitVectBitValue(rsave,R0_IDX))
2956             pic16_emitcode("mov","r0,b");
2957     } //else
2958     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2959     //    if (bitVectBitValue(rsave,i))
2960     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2961     //}
2962
2963 }  
2964 #endif
2965
2966 #if 0  // patch 14
2967 /*-----------------------------------------------------------------*/
2968 /* pushSide -                                                      */
2969 /*-----------------------------------------------------------------*/
2970 static void pushSide(operand * oper, int size)
2971 {
2972         int offset = 0;
2973     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2974         while (size--) {
2975                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2976                 if (AOP_TYPE(oper) != AOP_REG &&
2977                     AOP_TYPE(oper) != AOP_DIR &&
2978                     strcmp(l,"a") ) {
2979                         pic16_emitcode("mov","a,%s",l);
2980                         pic16_emitcode("push","acc");
2981                 } else
2982                         pic16_emitcode("push","%s",l);
2983         }
2984 }
2985 #endif // patch 14
2986
2987 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2988 {
2989   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2990     pic16_emitpcode(POC_MOVFW, src);
2991     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2992   } else {
2993     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2994         src, pic16_popGet(AOP(op), offset)));
2995   }
2996 }
2997
2998
2999 /*-----------------------------------------------------------------*/
3000 /* assignResultValue - assign results to oper, rescall==1 is       */
3001 /*                     called from genCall() or genPcall()         */
3002 /*-----------------------------------------------------------------*/
3003 static void assignResultValue(operand * oper, int res_size, int rescall)
3004 {
3005   int size = AOP_SIZE(oper);
3006   int offset=0;
3007   
3008     FENTRY2;
3009 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3010     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3011
3012     if(rescall) {
3013       /* assign result from a call/pcall function() */
3014                 
3015       /* function results are stored in a special order,
3016        * see top of file with Function return policy, or manual */
3017
3018       if(size <= 4) {
3019         /* 8-bits, result in WREG */
3020         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3021                         
3022         if(size > 1 && res_size > 1) {
3023           /* 16-bits, result in PRODL:WREG */
3024           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3025         }
3026                         
3027         if(size > 2 && res_size > 2) {
3028           /* 24-bits, result in PRODH:PRODL:WREG */
3029           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3030         }
3031                         
3032         if(size > 3 && res_size > 3) {
3033           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3034           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3035         }
3036
3037         pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
3038       
3039       } else {
3040         /* >32-bits, result on stack, and FSR0 points to beginning.
3041          * Fix stack when done */
3042         /* FIXME FIXME */
3043 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3044         while (size--) {
3045 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3046 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3047                 
3048           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3049           GpsuedoStkPtr++;
3050         }
3051                         
3052         /* fix stack */
3053         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3054         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3055         if(STACK_MODEL_LARGE) {
3056           emitSKPNC;
3057           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3058         }
3059       }                 
3060     } else {
3061       int areg = 0;             /* matching argument register */
3062       
3063 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3064       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3065
3066
3067       /* its called from genReceive (probably) -- VR */
3068       /* I hope this code will not be called from somewhere else in the future! 
3069        * We manually set the pseudo stack pointer in genReceive. - dw
3070        */
3071       if(!GpsuedoStkPtr && _G.useWreg) {
3072 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3073
3074         /* The last byte in the assignment is in W */
3075         if(areg <= GpsuedoStkPtr) {
3076           size--;
3077           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3078           offset++;
3079 //          debugf("receive from WREG\n", 0);
3080         }
3081         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3082       }
3083 //      GpsuedoStkPtr++;
3084       _G.stack_lat = AOP_SIZE(oper)-1;
3085
3086       while (size) {
3087         size--;
3088         GpsuedoStkPtr++;
3089         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3090 //        debugf("receive from STACK\n", 0);
3091         offset++;
3092       }
3093     }
3094 }
3095
3096
3097 /*-----------------------------------------------------------------*/
3098 /* genIpush - generate code for pushing this gets a little complex */
3099 /*-----------------------------------------------------------------*/
3100 static void genIpush (iCode *ic)
3101 {
3102 //  int size, offset=0;
3103
3104   FENTRY;
3105   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3106
3107   if(ic->parmPush) {
3108     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3109
3110     /* send to stack as normal */
3111     addSet(&_G.sendSet,ic);
3112 //    addSetHead(&_G.sendSet,ic);
3113     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3114   }
3115
3116         
3117 #if 0
3118     int size, offset = 0 ;
3119     char *l;
3120
3121
3122     /* if this is not a parm push : ie. it is spill push 
3123     and spill push is always done on the local stack */
3124     if (!ic->parmPush) {
3125
3126         /* and the item is spilt then do nothing */
3127         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3128             return ;
3129
3130         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3131         size = AOP_SIZE(IC_LEFT(ic));
3132         /* push it on the stack */
3133         while(size--) {
3134             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3135             if (*l == '#') {
3136                 MOVA(l);
3137                 l = "acc";
3138             }
3139             pic16_emitcode("push","%s",l);
3140         }
3141         return ;        
3142     }
3143
3144     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3145 #endif
3146 }
3147
3148 /*-----------------------------------------------------------------*/
3149 /* genIpop - recover the registers: can happen only for spilling   */
3150 /*-----------------------------------------------------------------*/
3151 static void genIpop (iCode *ic)
3152 {
3153   FENTRY;
3154   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3155 #if 0
3156     int size,offset ;
3157
3158
3159     /* if the temp was not pushed then */
3160     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3161         return ;
3162
3163     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3164     size = AOP_SIZE(IC_LEFT(ic));
3165     offset = (size-1);
3166     while (size--) 
3167         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3168                                    FALSE,TRUE));
3169
3170     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3171 #endif
3172 }
3173
3174 #if 0
3175 /*-----------------------------------------------------------------*/
3176 /* unsaverbank - restores the resgister bank from stack            */
3177 /*-----------------------------------------------------------------*/
3178 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3179 {
3180   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3181 #if 0
3182     int i;
3183     asmop *aop ;
3184     regs *r = NULL;
3185
3186     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3187     if (popPsw) {
3188         if (options.useXstack) {
3189             aop = newAsmop(0);
3190             r = getFreePtr(ic,&aop,FALSE);
3191             
3192             
3193             pic16_emitcode("mov","%s,_spx",r->name);
3194             pic16_emitcode("movx","a,@%s",r->name);
3195             pic16_emitcode("mov","psw,a");
3196             pic16_emitcode("dec","%s",r->name);
3197             
3198         }else
3199             pic16_emitcode ("pop","psw");
3200     }
3201
3202     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3203         if (options.useXstack) {       
3204             pic16_emitcode("movx","a,@%s",r->name);
3205             //pic16_emitcode("mov","(%s+%d),a",
3206             //       regspic16[i].base,8*bank+regspic16[i].offset);
3207             pic16_emitcode("dec","%s",r->name);
3208
3209         } else 
3210           pic16_emitcode("pop",""); //"(%s+%d)",
3211         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3212     }
3213
3214     if (options.useXstack) {
3215
3216         pic16_emitcode("mov","_spx,%s",r->name);
3217         pic16_freeAsmop(NULL,aop,ic,TRUE);
3218
3219     }
3220 #endif 
3221 }
3222
3223 /*-----------------------------------------------------------------*/
3224 /* saverbank - saves an entire register bank on the stack          */
3225 /*-----------------------------------------------------------------*/
3226 static void saverbank (int bank, iCode *ic, bool pushPsw)
3227 {
3228   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3229 #if 0
3230     int i;
3231     asmop *aop ;
3232     regs *r = NULL;
3233
3234     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3235     if (options.useXstack) {
3236
3237         aop = newAsmop(0);
3238         r = getFreePtr(ic,&aop,FALSE);  
3239         pic16_emitcode("mov","%s,_spx",r->name);
3240
3241     }
3242
3243     for (i = 0 ; i < pic16_nRegs ;i++) {
3244         if (options.useXstack) {
3245             pic16_emitcode("inc","%s",r->name);
3246             //pic16_emitcode("mov","a,(%s+%d)",
3247             //         regspic16[i].base,8*bank+regspic16[i].offset);
3248             pic16_emitcode("movx","@%s,a",r->name);           
3249         } else 
3250           pic16_emitcode("push","");// "(%s+%d)",
3251                      //regspic16[i].base,8*bank+regspic16[i].offset);
3252     }
3253     
3254     if (pushPsw) {
3255         if (options.useXstack) {
3256             pic16_emitcode("mov","a,psw");
3257             pic16_emitcode("movx","@%s,a",r->name);     
3258             pic16_emitcode("inc","%s",r->name);
3259             pic16_emitcode("mov","_spx,%s",r->name);       
3260             pic16_freeAsmop (NULL,aop,ic,TRUE);
3261             
3262         } else
3263             pic16_emitcode("push","psw");
3264         
3265         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3266     }
3267     ic->bankSaved = 1;
3268 #endif
3269 }
3270 #endif  /* 0 */
3271
3272
3273 static int wparamCmp(void *p1, void *p2)
3274 {
3275   return (!strcmp((char *)p1, (char *)p2));
3276 }
3277
3278 int inWparamList(char *s)
3279 {
3280   return isinSetWith(wparamList, s, wparamCmp);
3281
3282
3283
3284 /*-----------------------------------------------------------------*/
3285 /* genCall - generates a call statement                            */
3286 /*-----------------------------------------------------------------*/
3287 static void genCall (iCode *ic)
3288 {
3289   sym_link *ftype;   
3290   int stackParms=0;
3291   int use_wreg=0;
3292   int inwparam=0;
3293   char *fname;
3294   
3295     FENTRY;
3296
3297     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3298     /* if caller saves & we have not saved then */
3299 //    if (!ic->regsSaved)
3300 //      saveRegisters(ic);
3301
3302         /* initialise stackParms for IPUSH pushes */
3303 //      stackParms = psuedoStkPtr;
3304 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3305     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3306     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3307
3308 #if 0
3309     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3310 #endif
3311
3312     /* if send set is not empty the assign */
3313     if (_G.sendSet) {
3314       iCode *sic;
3315       int psuedoStkPtr=-1; 
3316       int firstTimeThruLoop = 1;
3317
3318
3319         /* reverse sendSet if function is not reentrant */
3320         if(!IFFUNC_ISREENT(ftype))
3321           _G.sendSet = reverseSet(_G.sendSet);
3322
3323         /* First figure how many parameters are getting passed */
3324         stackParms = 0;
3325         use_wreg = 0;
3326         
3327         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3328           int size;
3329 //          int offset = 0;
3330
3331             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3332             size = AOP_SIZE(IC_LEFT(sic));
3333
3334             stackParms += size;
3335
3336             /* pass the last byte through WREG */
3337             if(inwparam) {
3338
3339               while (size--) {
3340                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3341                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3342                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3343
3344                 if(!firstTimeThruLoop) {
3345                   /* If this is not the first time we've been through the loop
3346                    * then we need to save the parameter in a temporary
3347                    * register. The last byte of the last parameter is
3348                    * passed in W. */
3349
3350                   pushw();
3351 //                  --psuedoStkPtr;             // sanity check
3352                   use_wreg = 1;
3353                 }
3354                 
3355                 firstTimeThruLoop=0;
3356
3357                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3358
3359 //                offset++;
3360               }
3361             } else {
3362               /* all arguments are passed via stack */
3363               use_wreg = 0;
3364
3365               while (size--) {
3366                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3367                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3368                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3369
3370 //                pushaop(AOP(IC_LEFT(sic)), size);
3371                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3372                                 
3373                 if(!_G.resDirect)
3374                   pushw();
3375               }
3376             }
3377
3378             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3379           }
3380
3381           if(inwparam) {
3382             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3383               pushw();  /* save last parameter to stack if functions has varargs */
3384               use_wreg = 0;
3385             } else
3386               use_wreg = 1;
3387           } else use_wreg = 0;
3388
3389           _G.stackRegSet = _G.sendSet;
3390           _G.sendSet = NULL;
3391     }
3392
3393     /* make the call */
3394     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3395
3396     GpsuedoStkPtr=0;
3397     
3398     /* if we need to assign a result value */
3399     if ((IS_ITEMP(IC_RESULT(ic))
3400           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3401               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3402         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3403
3404       _G.accInUse++;
3405       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3406       _G.accInUse--;
3407
3408       /* Must not assign an 8-bit result to a 16-bit variable;
3409        * this would use (used...) the uninitialized PRODL! */
3410       /* FIXME: Need a proper way to obtain size of function result type,
3411        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
3412       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
3413
3414       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3415                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3416                 
3417       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3418     }
3419
3420     if(!stackParms && ic->parmBytes) {
3421       stackParms = ic->parmBytes;
3422     }
3423       
3424     stackParms -= use_wreg;
3425     
3426     if(stackParms>0) {
3427       if(stackParms == 1) {
3428         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3429       } else {
3430         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3431         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3432       }
3433       if(STACK_MODEL_LARGE) {
3434         emitSKPNC;
3435         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3436       }
3437     }
3438
3439 #if 0
3440     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3441 #endif
3442
3443     /* adjust the stack for parameters if required */
3444 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3445
3446 #if 0
3447       /* if register bank was saved then pop them */
3448       if (ic->bankSaved)
3449         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3450
3451       /* if we hade saved some registers then unsave them */
3452       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3453         unsaveRegisters (ic);
3454 #endif
3455 }
3456
3457
3458
3459 /*-----------------------------------------------------------------*/
3460 /* genPcall - generates a call by pointer statement                */
3461 /*            new version, created from genCall - HJD              */
3462 /*-----------------------------------------------------------------*/
3463 static void genPcall (iCode *ic)
3464 {
3465   sym_link *fntype;
3466   int stackParms=0;
3467   symbol *retlbl = newiTempLabel(NULL);
3468   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3469   
3470     FENTRY;
3471
3472     fntype = operandType( IC_LEFT(ic) )->next;
3473
3474     /* if send set is not empty the assign */
3475     if (_G.sendSet) {
3476       iCode *sic;
3477       int psuedoStkPtr=-1; 
3478
3479       /* reverse sendSet if function is not reentrant */
3480       if(!IFFUNC_ISREENT(fntype))
3481         _G.sendSet = reverseSet(_G.sendSet);
3482
3483       stackParms = 0;
3484       
3485       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3486         int size;
3487
3488           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3489           size = AOP_SIZE(IC_LEFT(sic));
3490           stackParms += size;
3491
3492           /* all parameters are passed via stack, since WREG is clobbered
3493            * by the calling sequence */
3494           while (size--) {
3495             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3496             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3497             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3498
3499             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3500             pushw();
3501           }
3502
3503           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3504       }
3505
3506       _G.stackRegSet = _G.sendSet;
3507       _G.sendSet = NULL;
3508     }
3509
3510     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3511
3512     // push return address
3513     // push $ on return stack, then replace with retlbl
3514
3515     /* Thanks to Thorsten Klose for pointing out that the following
3516      * snippet should be interrupt safe */
3517     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3518     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3519
3520     pic16_emitpcodeNULLop(POC_PUSH);
3521
3522     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3523     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3524     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3525     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3526     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3527     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3528
3529
3530     /* restore interrupt control register */
3531     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3532     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3533
3534     /* make the call by writing the pointer into pc */
3535     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3536     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3537
3538     // note: MOVFF to PCL not allowed
3539     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3540     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3541
3542
3543     /* return address is here: (X) */
3544     pic16_emitpLabelFORCE(retlbl->key);
3545
3546     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3547
3548     GpsuedoStkPtr=0;
3549     /* if we need assign a result value */
3550     if ((IS_ITEMP(IC_RESULT(ic))
3551           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3552               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3553         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3554
3555       _G.accInUse++;
3556       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3557       _G.accInUse--;
3558
3559       /* FIXME: Need proper way to obtain the function result's type.
3560        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
3561       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
3562
3563       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3564               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3565                 
3566       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3567     }
3568
3569 //    stackParms -= use_wreg;
3570     
3571     if(stackParms>0) {
3572       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3573       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3574       if(STACK_MODEL_LARGE) {
3575         emitSKPNC;
3576         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3577       }
3578     }
3579 }
3580
3581 /*-----------------------------------------------------------------*/
3582 /* resultRemat - result  is rematerializable                       */
3583 /*-----------------------------------------------------------------*/
3584 static int resultRemat (iCode *ic)
3585 {
3586   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3587   if (SKIP_IC(ic) || ic->op == IFX)
3588     return 0;
3589
3590   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3591     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3592     if (sym->remat && !POINTER_SET(ic)) 
3593       return 1;
3594   }
3595
3596   return 0;
3597 }
3598
3599 #if defined(__BORLANDC__) || defined(_MSC_VER)
3600 #define STRCASECMP stricmp
3601 #else
3602 #define STRCASECMP strcasecmp
3603 #endif
3604
3605 #if 0
3606 /*-----------------------------------------------------------------*/
3607 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3608 /*-----------------------------------------------------------------*/
3609 static bool inExcludeList(char *s)
3610 {
3611   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3612     int i =0;
3613     
3614     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3615     if (options.excludeRegs[i] &&
3616     STRCASECMP(options.excludeRegs[i],"none") == 0)
3617         return FALSE ;
3618
3619     for ( i = 0 ; options.excludeRegs[i]; i++) {
3620         if (options.excludeRegs[i] &&
3621         STRCASECMP(s,options.excludeRegs[i]) == 0)
3622             return TRUE;
3623     }
3624     return FALSE ;
3625 }
3626 #endif
3627
3628 /*-----------------------------------------------------------------*/
3629 /* genFunction - generated code for function entry                 */
3630 /*-----------------------------------------------------------------*/
3631 static void genFunction (iCode *ic)
3632 {
3633   symbol *sym;
3634   sym_link *ftype;
3635   
3636     FENTRY;
3637     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3638
3639     pic16_labelOffset += (max_key+4);
3640     max_key=0;
3641     GpsuedoStkPtr=0;
3642     _G.nRegsSaved = 0;
3643         
3644     ftype = operandType(IC_LEFT(ic));
3645     sym = OP_SYMBOL(IC_LEFT(ic));
3646
3647     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3648       /* create an absolute section at the interrupt vector:
3649        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3650       symbol *asym;
3651       char asymname[128];
3652       pBlock *apb;
3653
3654 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3655
3656         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3657           sprintf(asymname, "ivec_%s", sym->name);
3658         else
3659           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3660   
3661         /* when an interrupt is declared as naked, do not emit the special
3662          * wrapper segment at vector address. The user should take care for
3663          * this instead. -- VR */
3664
3665         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3666           asym = newSymbol(asymname, 0);
3667           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3668           pic16_addpBlock( apb );
3669
3670           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3671           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3672           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3673           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3674           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3675                 
3676           /* mark the end of this tiny function */
3677           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3678         } else {
3679           sprintf(asymname, "%s", sym->rname);
3680         }
3681
3682         {
3683           absSym *abSym;
3684
3685             abSym = Safe_calloc(1, sizeof(absSym));
3686             strcpy(abSym->name, asymname);
3687
3688             switch( FUNC_INTNO(sym->type) ) {
3689               case 0: abSym->address = 0x000000; break;
3690               case 1: abSym->address = 0x000008; break;
3691               case 2: abSym->address = 0x000018; break;
3692               
3693               default:
3694 //                fprintf(stderr, "no interrupt number is given\n");
3695                 abSym->address = -1; break;
3696             }
3697
3698             /* relocate interrupt vectors if needed */
3699             if(abSym->address != -1)
3700               abSym->address += pic16_options.ivt_loc;
3701
3702             addSet(&absSymSet, abSym);
3703         }
3704     }
3705
3706     /* create the function header */
3707     pic16_emitcode(";","-----------------------------------------");
3708     pic16_emitcode(";"," function %s",sym->name);
3709     pic16_emitcode(";","-----------------------------------------");
3710
3711     /* prevent this symbol from being emitted as 'extern' */
3712     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3713
3714     pic16_emitcode("","%s:",sym->rname);
3715     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3716
3717     {
3718       absSym *ab;
3719
3720         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3721           if(!strcmp(ab->name, sym->rname)) {
3722             pic16_pBlockConvert2Absolute(pb);
3723             break;
3724           }
3725         }
3726     }
3727
3728     if(IFFUNC_ISNAKED(ftype)) {
3729       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3730       return;
3731     }
3732         
3733     /* if critical function then turn interrupts off */
3734     if (IFFUNC_ISCRITICAL(ftype)) {
3735       //pic16_emitcode("clr","ea");
3736     }
3737
3738     currFunc = sym;             /* update the currFunc symbol */
3739     _G.fregsUsed = sym->regsUsed;
3740     _G.sregsAlloc = newBitVect(128);
3741     
3742
3743     /* if this is an interrupt service routine then
3744      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3745     if (IFFUNC_ISISR(sym->type)) {
3746         _G.usefastretfie = 1;   /* use shadow registers by default */
3747         
3748         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3749         if(!FUNC_ISSHADOWREGS(sym->type)) {
3750           /* do not save WREG,STATUS,BSR for high priority interrupts
3751            * because they are stored in the hardware shadow registers already */
3752           _G.usefastretfie = 0;
3753           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3754           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3755           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3756         }
3757
3758         /* these should really be optimized somehow, because not all
3759          * interrupt handlers modify them */
3760         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3761         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3762         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3763         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3764         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3765         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3766         
3767 //        pic16_pBlockConvert2ISR(pb);
3768     }
3769
3770     /* emit code to setup stack frame if user enabled,
3771      * and function is not main() */
3772     
3773 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3774     if(strcmp(sym->name, "main")) {
3775       if(0 
3776         || !options.ommitFramePtr 
3777 //        || sym->regsUsed
3778         || IFFUNC_ARGS(sym->type)
3779         || FUNC_HASSTACKPARM(sym->etype)
3780         ) {
3781         /* setup the stack frame */
3782         if(STACK_MODEL_LARGE)
3783           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3784         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3785
3786         if(STACK_MODEL_LARGE)
3787           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3788         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3789       }
3790     }
3791
3792     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3793           && sym->stack) {
3794
3795       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3796
3797       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3798       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3799       emitSKPC;
3800       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3801     }
3802           
3803     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3804       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3805         _G.useWreg = 0;
3806       else
3807         _G.useWreg = 1;
3808     } else
3809       _G.useWreg = 0;
3810
3811     /* if callee-save to be used for this function
3812      * then save the registers being used in this function */
3813 //    if (IFFUNC_CALLEESAVES(sym->type))
3814     if(strcmp(sym->name, "main")) {
3815       int i;
3816
3817         /* if any registers used */
3818         if (sym->regsUsed) {
3819                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3820
3821           if(!xinst) {
3822             /* save the registers used */
3823             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3824             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3825               if (bitVectBitValue(sym->regsUsed,i)) {
3826 #if 0
3827                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3828 #endif
3829                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3830                 _G.nRegsSaved++;
3831
3832                 if(!pic16_regWithIdx(i)->wasUsed) {
3833                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3834                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3835                   pic16_regWithIdx(i)->wasUsed = 1;
3836                 }
3837               }
3838             }
3839           } else {
3840             
3841             /* xinst */
3842             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3843             for(i=0;i<sym->regsUsed->size;i++) {
3844               if(bitVectBitValue(sym->regsUsed, i)) {
3845                 _G.nRegsSaved++;
3846               }
3847             }
3848                         
3849 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3850           }
3851
3852           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3853
3854         }
3855     }
3856         
3857     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3858 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3859 }
3860
3861 /*-----------------------------------------------------------------*/
3862 /* genEndFunction - generates epilogue for functions               */
3863 /*-----------------------------------------------------------------*/
3864 static void genEndFunction (iCode *ic)
3865 {
3866   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3867
3868     FENTRY;
3869
3870     if(IFFUNC_ISNAKED(sym->type)) {
3871       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3872       return;
3873     }
3874
3875     _G.stack_lat = 0;
3876
3877     /* add code for ISCRITICAL */
3878     if(IFFUNC_ISCRITICAL(sym->type)) {
3879       /* if critical function, turn on interrupts */
3880       
3881       /* TODO: add code here -- VR */
3882     }
3883     
3884 //    sym->regsUsed = _G.fregsUsed;
3885     
3886     /* now we need to restore the registers */
3887     /* if any registers used */
3888
3889     /* first restore registers that might be used for stack access */
3890     if(_G.sregsAllocSet) {
3891     regs *sr;
3892     
3893       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3894       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3895         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3896       }
3897     }
3898
3899     if (strcmp(sym->name, "main") && sym->regsUsed) {
3900       int i;
3901
3902         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3903         /* restore registers used */
3904         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3905         for ( i = sym->regsUsed->size; i >= 0; i--) {
3906           if (bitVectBitValue(sym->regsUsed,i)) {
3907             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3908             _G.nRegsSaved--;
3909           }
3910         }
3911         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3912     }
3913
3914       
3915
3916     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3917           && sym->stack) {
3918       if (sym->stack == 1) {
3919         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3920         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3921       } else {
3922         // we have to add more than one...
3923         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3924         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3925         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3926         emitSKPNC;
3927         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3928         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3929         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3930       }
3931     }
3932
3933     if(strcmp(sym->name, "main")) {
3934       if(0
3935         || !options.ommitFramePtr
3936 //        || sym->regsUsed
3937         || IFFUNC_ARGS(sym->type)
3938         || FUNC_HASSTACKPARM(sym->etype)
3939         ) {
3940         /* restore stack frame */
3941         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3942         if(STACK_MODEL_LARGE)
3943           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3944       }
3945     }
3946
3947     _G.useWreg = 0;
3948
3949     if (IFFUNC_ISISR(sym->type)) {
3950       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3951       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3952       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3953       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3954       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3955       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3956
3957       if(!FUNC_ISSHADOWREGS(sym->type)) {
3958         /* do not restore interrupt vector for WREG,STATUS,BSR
3959          * for high priority interrupt, see genFunction */
3960         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3961         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3962         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3963       }
3964 //      _G.interruptvector = 0;         /* sanity check */
3965
3966
3967       /* if debug then send end of function */
3968 /*      if (options.debug && currFunc)  */
3969       if (currFunc) {
3970         debugFile->writeEndFunction (currFunc, ic, 1);
3971       }
3972         
3973       if(_G.usefastretfie)
3974         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3975       else
3976         pic16_emitpcodeNULLop(POC_RETFIE);
3977
3978       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3979       
3980       _G.usefastretfie = 0;
3981       return;
3982     }
3983
3984     if (IFFUNC_ISCRITICAL(sym->type)) {
3985       pic16_emitcode("setb","ea");
3986     }
3987
3988     /* if debug then send end of function */
3989     if (currFunc) {
3990       debugFile->writeEndFunction (currFunc, ic, 1);
3991     }
3992
3993     /* insert code to restore stack frame, if user enabled it
3994      * and function is not main() */
3995          
3996
3997     pic16_emitpcodeNULLop(POC_RETURN);
3998
3999     /* Mark the end of a function */
4000     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
4001 }
4002
4003
4004 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
4005 {
4006   unsigned long lit=1;
4007   operand *op;
4008   
4009     op = IC_LEFT(ic);
4010   
4011     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4012     if(AOP_TYPE(op) == AOP_LIT) {
4013       if(!IS_FLOAT(operandType( op ))) {
4014         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4015       } else {
4016         union {
4017           unsigned long lit_int;
4018           float lit_float;
4019         } info;
4020         
4021         /* take care if literal is a float */
4022         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4023         lit = info.lit_int;
4024       }
4025     }
4026
4027     if (AOP_TYPE(op) == AOP_LIT) {
4028       /* FIXME: broken for
4029        *   char __at(0x456) foo;
4030        *   return &foo;
4031        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4032       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4033     } else if (AOP_TYPE(op) == AOP_PCODE
4034                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4035       /* char *s= "aaa"; return s; */
4036       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4037        *      that the generic pointer is interpreted correctly
4038        *      as referring to __code space, but this is fragile! */
4039       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4040       /* XXX: should check that dest != WREG */
4041       pic16_emitpcode(POC_MOVWF, dest);
4042     } else {
4043       if(dest->type == PO_WREG && (offset == 0)) {
4044         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4045         return;
4046       }
4047       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4048     }
4049 }
4050
4051 /*-----------------------------------------------------------------*/
4052 /* genRet - generate code for return statement                     */
4053 /*-----------------------------------------------------------------*/
4054 static void genRet (iCode *ic)
4055 {
4056   int size;
4057   operand *left;
4058
4059     FENTRY;
4060         /* if we have no return value then
4061          * just generate the "ret" */
4062         
4063         if (!IC_LEFT(ic)) 
4064                 goto jumpret;       
4065     
4066         /* we have something to return then
4067          * move the return value into place */
4068         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4069         size = AOP_SIZE(IC_LEFT(ic));
4070
4071         if(size <= 4) {
4072           if(size>3)
4073             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4074           
4075           if(size>2)
4076             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4077
4078           if(size>1)
4079             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4080           
4081           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4082
4083         } else {
4084                 /* >32-bits, setup stack and FSR0 */
4085                 while (size--) {
4086 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4087 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4088
4089                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4090
4091 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4092                         GpsuedoStkPtr++;
4093                 }
4094                         
4095                 /* setup FSR0 */
4096                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4097                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4098
4099                 if(STACK_MODEL_LARGE) {
4100                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4101                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4102                 } else {
4103                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4104                 }
4105         }
4106                                 
4107 #if 0
4108         /* old code, left here for reference -- VR */    
4109         while (size--) {
4110           char *l ;
4111
4112                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4113                         /* #NOCHANGE */
4114                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4115                         pic16_emitpcomment("push %s",l);
4116                         pushed++;
4117                 } else {
4118                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4119                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4120                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4121                         
4122                         if (strcmp(fReturn[offset],l)) {
4123                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4124                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4125                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4126                                 } else {
4127                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4128                                 }
4129                                 
4130                                 if(size) {
4131                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4132                                 }
4133                                 offset++;
4134                         }
4135                 }
4136         }    
4137
4138         if (pushed) {
4139                 while(pushed) {
4140                         pushed--;
4141                         if (strcmp(fReturn[pushed],"a"))
4142                                 pic16_emitcode("pop",fReturn[pushed]);
4143                         else
4144                                 pic16_emitcode("pop","acc");
4145                 }
4146         }
4147 #endif
4148
4149
4150         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4151     
4152 jumpret:
4153         /* generate a jump to the return label
4154          * if the next is not the return statement */
4155         if (!(ic->next && ic->next->op == LABEL
4156                 && IC_LABEL(ic->next) == returnLabel)) {
4157         
4158                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4159                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4160         }
4161 }
4162
4163 /*-----------------------------------------------------------------*/
4164 /* genLabel - generates a label                                    */
4165 /*-----------------------------------------------------------------*/
4166 static void genLabel (iCode *ic)
4167 {
4168   FENTRY;
4169
4170   /* special case never generate */
4171   if (IC_LABEL(ic) == entryLabel)
4172     return ;
4173
4174   pic16_emitpLabel(IC_LABEL(ic)->key);
4175 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4176 }
4177
4178 /*-----------------------------------------------------------------*/
4179 /* genGoto - generates a goto                                      */
4180 /*-----------------------------------------------------------------*/
4181 //tsd
4182 static void genGoto (iCode *ic)
4183 {
4184   FENTRY;
4185   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4186 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4187 }
4188
4189
4190 /*-----------------------------------------------------------------*/
4191 /* genMultbits :- multiplication of bits                           */
4192 /*-----------------------------------------------------------------*/
4193 static void genMultbits (operand *left, 
4194                          operand *right, 
4195                          operand *result)
4196 {
4197   FENTRY;
4198
4199   if(!pic16_sameRegs(AOP(result),AOP(right)))
4200     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4201
4202   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4203   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4204   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4205
4206 }
4207
4208
4209 /*-----------------------------------------------------------------*/
4210 /* genMultOneByte : 8 bit multiplication & division                */
4211 /*-----------------------------------------------------------------*/
4212 static void genMultOneByte (operand *left,
4213                             operand *right,
4214                             operand *result)
4215 {
4216
4217   FENTRY;
4218   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4219   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4220
4221   /* (if two literals, the value is computed before) */
4222   /* if one literal, literal on the right */
4223   if (AOP_TYPE(left) == AOP_LIT){
4224     operand *t = right;
4225     right = left;
4226     left = t;
4227   }
4228
4229         /* size is already checked in genMult == 1 */
4230 //      size = AOP_SIZE(result);
4231
4232         if (AOP_TYPE(right) == AOP_LIT){
4233                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4234                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4235                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4236                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4237         } else {
4238                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4239                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4240                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4241                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4242         }
4243         
4244         pic16_genMult8X8_n (left, right,result);
4245 }
4246
4247 #if 0
4248 /*-----------------------------------------------------------------*/
4249 /* genMultOneWord : 16 bit multiplication                          */
4250 /*-----------------------------------------------------------------*/
4251 static void genMultOneWord (operand *left,
4252                             operand *right,
4253                             operand *result)
4254 {
4255   FENTRY;
4256   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4257   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4258
4259   /* (if two literals, the value is computed before)
4260    * if one literal, literal on the right */
4261   if (AOP_TYPE(left) == AOP_LIT){
4262     operand *t = right;
4263     right = left;
4264     left = t;
4265   }
4266
4267   /* size is checked already == 2 */
4268 //  size = AOP_SIZE(result);
4269
4270   if (AOP_TYPE(right) == AOP_LIT) {
4271     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4272       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4273       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4274       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4275   } else {
4276     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4277       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4278       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4279       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4280   }
4281         
4282   pic16_genMult16X16_16(left, right,result);
4283 }
4284 #endif
4285
4286 #if 0
4287 /*-----------------------------------------------------------------*/
4288 /* genMultOneLong : 32 bit multiplication                          */
4289 /*-----------------------------------------------------------------*/
4290 static void genMultOneLong (operand *left,
4291                             operand *right,
4292                             operand *result)
4293 {
4294   FENTRY;
4295   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4296   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4297
4298   /* (if two literals, the value is computed before)
4299    * if one literal, literal on the right */
4300   if (AOP_TYPE(left) == AOP_LIT){
4301     operand *t = right;
4302     right = left;
4303     left = t;
4304   }
4305
4306   /* size is checked already == 4 */
4307 //  size = AOP_SIZE(result);
4308
4309   if (AOP_TYPE(right) == AOP_LIT) {
4310     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4311         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4312         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4313         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4314   } else {
4315     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4316         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4317         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4318         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4319   }
4320         
4321   pic16_genMult32X32_32(left, right,result);
4322 }
4323 #endif
4324
4325
4326
4327 /*-----------------------------------------------------------------*/
4328 /* genMult - generates code for multiplication                     */
4329 /*-----------------------------------------------------------------*/
4330 static void genMult (iCode *ic)
4331 {
4332   operand *left = IC_LEFT(ic);
4333   operand *right = IC_RIGHT(ic);
4334   operand *result= IC_RESULT(ic);   
4335
4336     FENTRY;
4337         /* assign the amsops */
4338         pic16_aopOp (left,ic,FALSE);
4339         pic16_aopOp (right,ic,FALSE);
4340         pic16_aopOp (result,ic,TRUE);
4341
4342         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4343
4344         /* special cases first *
4345         * both are bits */
4346         if (AOP_TYPE(left) == AOP_CRY
4347                 && AOP_TYPE(right)== AOP_CRY) {
4348                 genMultbits(left,right,result);
4349           goto release ;
4350         }
4351
4352         /* if both are of size == 1 */
4353         if(AOP_SIZE(left) == 1
4354                 && AOP_SIZE(right) == 1) {
4355                 genMultOneByte(left,right,result);
4356           goto release ;
4357         }
4358
4359 #if 0
4360         /* if both are of size == 2 */
4361         if(AOP_SIZE(left) == 2
4362                 && AOP_SIZE(right) == 2) {
4363                 genMultOneWord(left, right, result);
4364           goto release;
4365         }
4366         
4367         /* if both are of size == 4 */
4368         if(AOP_SIZE(left) == 4
4369                 && AOP_SIZE(right) == 4) {
4370                 genMultOneLong(left, right, result);
4371           goto release;
4372         }
4373 #endif
4374
4375         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4376         assert( !"Multiplication should have been transformed into function call!" );
4377
4378         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4379
4380
4381         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4382         /* should have been converted to function call */
4383         assert(0) ;
4384
4385 release :
4386         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4387         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4388         pic16_freeAsmop(result,NULL,ic,TRUE); 
4389 }
4390
4391 #if 0
4392 /*-----------------------------------------------------------------*/
4393 /* genDivbits :- division of bits                                  */
4394 /*-----------------------------------------------------------------*/
4395 static void genDivbits (operand *left, 
4396                         operand *right, 
4397                         operand *result)
4398 {
4399   char *l;
4400
4401     FENTRY;
4402     /* the result must be bit */    
4403     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4404     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4405
4406     MOVA(l);    
4407
4408     pic16_emitcode("div","ab");
4409     pic16_emitcode("rrc","a");
4410     pic16_aopPut(AOP(result),"c",0);
4411 }
4412
4413 /*-----------------------------------------------------------------*/
4414 /* genDivOneByte : 8 bit division                                  */
4415 /*-----------------------------------------------------------------*/
4416 static void genDivOneByte (operand *left,
4417                            operand *right,
4418                            operand *result)
4419 {
4420   sym_link *opetype = operandType(result);
4421   char *l ;
4422   symbol *lbl ;
4423   int size,offset;
4424
4425         /* result = divident / divisor
4426          * - divident may be a register or a literal,
4427          * - divisor may be a register or a literal,
4428          * so there are 3 cases (literal / literal is optimized
4429          * by the front-end) to handle.
4430          * In addition we must handle signed and unsigned, which
4431          * result in 6 final different cases -- VR */
4432
4433     FENTRY;
4434     
4435     size = AOP_SIZE(result) - 1;
4436     offset = 1;
4437     /* signed or unsigned */
4438     if (SPEC_USIGN(opetype)) {
4439       pCodeOp *pct1,    /* count */
4440                 *pct2,  /* reste */
4441                 *pct3;  /* temp */
4442       symbol *label1, *label2, *label3;;
4443
4444
4445         /* unsigned is easy */
4446
4447         pct1 = pic16_popGetTempReg(1);
4448         pct2 = pic16_popGetTempReg(1);
4449         pct3 = pic16_popGetTempReg(1);
4450         
4451         label1 = newiTempLabel(NULL);
4452         label2 = newiTempLabel(NULL);
4453         label3 = newiTempLabel(NULL);
4454
4455         /* the following algorithm is extracted from divuint.c */
4456
4457         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4458         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4459         
4460         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4461
4462         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4463         
4464         pic16_emitpLabel(label1->key);
4465         
4466         emitCLRC;
4467         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4468
4469
4470         emitCLRC;
4471         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4472         
4473
4474         emitSKPNC;
4475         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4476         
4477         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4478         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4479         
4480         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4481         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4482         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4483         
4484         pic16_emitpLabel( label3->key );
4485         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4486         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4487         
4488         
4489
4490         pic16_emitpLabel(label2->key);
4491         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4492         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4493         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4494         
4495         /* result is in wreg */
4496         if(AOP_TYPE(result) != AOP_ACC)
4497                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4498
4499         pic16_popReleaseTempReg( pct3, 1);
4500         pic16_popReleaseTempReg( pct2, 1);
4501         pic16_popReleaseTempReg( pct1, 1);
4502
4503         return ;
4504     }
4505
4506     /* signed is a little bit more difficult */
4507
4508     /* save the signs of the operands */
4509     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4510     MOVA(l);    
4511     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4512     pic16_emitcode("push","acc"); /* save it on the stack */
4513
4514     /* now sign adjust for both left & right */
4515     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4516     MOVA(l);       
4517     lbl = newiTempLabel(NULL);
4518     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4519     pic16_emitcode("cpl","a");   
4520     pic16_emitcode("inc","a");
4521     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4522     pic16_emitcode("mov","b,a");
4523
4524     /* sign adjust left side */
4525     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4526     MOVA(l);
4527
4528     lbl = newiTempLabel(NULL);
4529     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4530     pic16_emitcode("cpl","a");
4531     pic16_emitcode("inc","a");
4532     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4533
4534     /* now the division */
4535     pic16_emitcode("div","ab");
4536     /* we are interested in the lower order
4537     only */
4538     pic16_emitcode("mov","b,a");
4539     lbl = newiTempLabel(NULL);
4540     pic16_emitcode("pop","acc");   
4541     /* if there was an over flow we don't 
4542     adjust the sign of the result */
4543     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4544     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4545     CLRC;
4546     pic16_emitcode("clr","a");
4547     pic16_emitcode("subb","a,b");
4548     pic16_emitcode("mov","b,a");
4549     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4550
4551     /* now we are done */
4552     pic16_aopPut(AOP(result),"b",0);
4553     if(size > 0){
4554         pic16_emitcode("mov","c,b.7");
4555         pic16_emitcode("subb","a,acc");   
4556     }
4557     while (size--)
4558         pic16_aopPut(AOP(result),"a",offset++);
4559
4560 }
4561 #endif
4562
4563 /*-----------------------------------------------------------------*/
4564 /* genDiv - generates code for division                            */
4565 /*-----------------------------------------------------------------*/
4566 static void genDiv (iCode *ic)
4567 {
4568     operand *left = IC_LEFT(ic);
4569     operand *right = IC_RIGHT(ic);
4570     operand *result= IC_RESULT(ic);   
4571     int negated = 0;
4572     int leftVal = 0, rightVal = 0;
4573     int signedLits = 0;
4574     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4575     int op = 0;
4576     
4577         /* Division is a very lengthy algorithm, so it is better
4578          * to call support routines than inlining algorithm.
4579          * Division functions written here just in case someone
4580          * wants to inline and not use the support libraries -- VR */
4581
4582     FENTRY;
4583     
4584     /* assign the amsops */
4585     pic16_aopOp (left,ic,FALSE);
4586     pic16_aopOp (right,ic,FALSE);
4587     pic16_aopOp (result,ic,TRUE);
4588
4589     if (ic->op == '/')
4590       op = 0;
4591     else if (ic->op == '%')
4592       op = 1;
4593     else
4594       assert( !"invalid operation requested in genDivMod" );
4595
4596     /* get literal values */
4597     if (IS_VALOP(left)) {
4598       leftVal = (int)floatFromVal( OP_VALUE(left) );
4599       assert( leftVal >= -128 && leftVal < 256 );
4600       if (leftVal < 0) { signedLits++; }
4601     }
4602     if (IS_VALOP(right)) {
4603       rightVal = (int)floatFromVal( OP_VALUE(right) );
4604       assert( rightVal >= -128 && rightVal < 256 );
4605       if (rightVal < 0) { signedLits++; }
4606     }
4607
4608     /* We should only come here to convert all
4609      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4610      * with exactly one operand being s8_t into
4611      * u8_t x u8_t -> u8_t. All other cases should have been
4612      * turned into calls to support routines beforehand... */
4613     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4614         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4615     {
4616       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4617           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4618       {
4619         /* Both operands are signed or negative, use _divschar
4620          * instead of _divuchar */
4621         pushaop(AOP(right), 0);
4622         pushaop(AOP(left), 0);
4623
4624         /* call _divschar */
4625         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4626
4627         {
4628           symbol *sym;
4629           sym = newSymbol( functions[op][0], 0 );
4630           sym->used++;
4631           strcpy(sym->rname, functions[op][0]);
4632           checkAddSym(&externs, sym);
4633         }
4634
4635         /* assign result */
4636         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4637         if (AOP_SIZE(result) > 1)
4638         {
4639           pic16_emitpcode(POC_MOVFF,
4640               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4641                 pic16_popGet(AOP(result), 1)));
4642           /* sign extend */
4643           pic16_addSign(result, 2, 1);
4644         }
4645
4646         /* clean up stack */
4647         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4648         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4649
4650         goto release;
4651       }
4652       
4653       /* push right operand */
4654       if (IS_VALOP(right)) {
4655         if (rightVal < 0) {
4656           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4657           negated++;
4658         } else {
4659           pushaop(AOP(right), 0);
4660         }
4661       } else if (!IS_UNSIGNED(operandType(right))) {
4662         pic16_mov2w(AOP(right), 0);
4663         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4664         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4665         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4666         negated++;
4667       } else {
4668         pushaop(AOP(right), 0);
4669       }
4670
4671       /* push left operand */
4672       if (IS_VALOP(left)) {
4673         if (leftVal < 0) {
4674           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4675           negated++;
4676         } else {
4677           pushaop(AOP(left), 0);
4678         }
4679       } else if (!IS_UNSIGNED(operandType(left))) {
4680         pic16_mov2w(AOP(left),0);
4681         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4682         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4683         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4684         negated++;
4685       } else {
4686         pushaop(AOP(left), 0);
4687       }
4688       
4689       /* call _divuchar */
4690       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4691
4692       {
4693         symbol *sym;
4694         sym = newSymbol( functions[op][1], 0 );
4695         sym->used++;
4696         strcpy(sym->rname, functions[op][1]);
4697         checkAddSym(&externs, sym);
4698       }
4699
4700       /* Revert negation(s) from above.
4701        * This is inefficient: if both operands are negative, this
4702        * should not touch WREG. However, determining that exactly
4703        * one operand was negated costs at least 3 instructions,
4704        * so there is nothing to be gained here, is there?
4705        *
4706        * I negate WREG because either operand might share registers with
4707        * result, so assigning first might destroy an operand. */
4708       
4709       /* For the modulus operator, (a/b)*b == a shall hold.
4710        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4711        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
4712        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
4713        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
4714        * Only invert the result if the left operand is negative (sigh).
4715        */
4716       if (AOP_SIZE(result) <= 1 || !negated)
4717       {
4718         if (ic->op == '/')
4719         {
4720           if (IS_VALOP(right)) {
4721             if (rightVal < 0) {
4722               /* we negated this operand above */
4723               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4724             }
4725           } else if (!IS_UNSIGNED(operandType(right))) {
4726             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4727             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4728           }
4729         }
4730
4731         if (IS_VALOP(left)) {
4732           if (leftVal < 0) {
4733             /* we negated this operand above */
4734             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4735           }
4736         } else if (!IS_UNSIGNED(operandType(left))) {
4737           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4738           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4739         }
4740
4741         /* Move result to destination. */
4742         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4743
4744         /* Zero-extend:  no operand was signed (or result is just a byte). */
4745         pic16_addSign(result, 1, 0);
4746       } else {
4747         assert( AOP_SIZE(result) > 1 );
4748         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4749         if (ic->op == '/')
4750         {
4751           if (IS_VALOP(right)) {
4752             if (rightVal < 0) {
4753               /* we negated this operand above */
4754               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4755             }
4756           } else if (!IS_UNSIGNED(operandType(right))) {
4757             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4758             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4759           }
4760         }
4761
4762         if (IS_VALOP(left)) {
4763           if (leftVal < 0) {
4764             /* we negated this operand above */
4765             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4766           }
4767         } else if (!IS_UNSIGNED(operandType(left))) {
4768           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4769           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4770         }
4771
4772         /* Move result to destination. */
4773         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4774
4775         /* Negate result if required. */
4776         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4777         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4778
4779         /* Sign-extend. */
4780         pic16_addSign(result, 2, 1);
4781       }
4782
4783       /* clean up stack */
4784       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4785       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4786       goto release;
4787     }
4788
4789 #if 0
4790     /* special cases first */
4791     /* both are bits */
4792     if (AOP_TYPE(left) == AOP_CRY &&
4793         AOP_TYPE(right)== AOP_CRY) {
4794         genDivbits(left,right,result);
4795         goto release ;
4796     }
4797
4798     /* if both are of size == 1 */
4799     if (AOP_SIZE(left) == 1 &&
4800         AOP_SIZE(right) == 1 ) {
4801         genDivOneByte(left,right,result);
4802         goto release ;
4803     }
4804 #endif
4805
4806     /* should have been converted to function call */
4807     assert(0);
4808 release :
4809     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4810     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4811     pic16_freeAsmop(result,NULL,ic,TRUE); 
4812 }
4813
4814 #if 0
4815 /*-----------------------------------------------------------------*/
4816 /* genModbits :- modulus of bits                                   */
4817 /*-----------------------------------------------------------------*/
4818 static void genModbits (operand *left, 
4819                         operand *right, 
4820                         operand *result)
4821 {
4822   char *l;
4823
4824     FENTRY;  
4825     
4826     werror(W_POSSBUG2, __FILE__, __LINE__);
4827     /* the result must be bit */    
4828     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4829     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4830
4831     MOVA(l);       
4832
4833     pic16_emitcode("div","ab");
4834     pic16_emitcode("mov","a,b");
4835     pic16_emitcode("rrc","a");
4836     pic16_aopPut(AOP(result),"c",0);
4837 }
4838
4839 /*-----------------------------------------------------------------*/
4840 /* genModOneByte : 8 bit modulus                                   */
4841 /*-----------------------------------------------------------------*/
4842 static void genModOneByte (operand *left,
4843                            operand *right,
4844                            operand *result)
4845 {
4846   sym_link *opetype = operandType(result);
4847   char *l ;
4848   symbol *lbl ;
4849
4850     FENTRY;
4851     werror(W_POSSBUG2, __FILE__, __LINE__);
4852
4853     /* signed or unsigned */
4854     if (SPEC_USIGN(opetype)) {
4855         /* unsigned is easy */
4856         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4857         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4858         MOVA(l);    
4859         pic16_emitcode("div","ab");
4860         pic16_aopPut(AOP(result),"b",0);
4861         return ;
4862     }
4863
4864     /* signed is a little bit more difficult */
4865
4866     /* save the signs of the operands */
4867     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4868     MOVA(l);
4869
4870     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4871     pic16_emitcode("push","acc"); /* save it on the stack */
4872
4873     /* now sign adjust for both left & right */
4874     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4875     MOVA(l);
4876
4877     lbl = newiTempLabel(NULL);
4878     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4879     pic16_emitcode("cpl","a");   
4880     pic16_emitcode("inc","a");
4881     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4882     pic16_emitcode("mov","b,a"); 
4883
4884     /* sign adjust left side */
4885     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4886     MOVA(l);
4887
4888     lbl = newiTempLabel(NULL);
4889     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4890     pic16_emitcode("cpl","a");   
4891     pic16_emitcode("inc","a");
4892     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4893
4894     /* now the multiplication */
4895     pic16_emitcode("div","ab");
4896     /* we are interested in the lower order
4897     only */
4898     lbl = newiTempLabel(NULL);
4899     pic16_emitcode("pop","acc");   
4900     /* if there was an over flow we don't 
4901     adjust the sign of the result */
4902     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4903     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4904     CLRC ;
4905     pic16_emitcode("clr","a");
4906     pic16_emitcode("subb","a,b");
4907     pic16_emitcode("mov","b,a");
4908     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4909
4910     /* now we are done */
4911     pic16_aopPut(AOP(result),"b",0);
4912
4913 }
4914 #endif
4915
4916 /*-----------------------------------------------------------------*/
4917 /* genMod - generates code for division                            */
4918 /*-----------------------------------------------------------------*/
4919 static void genMod (iCode *ic)
4920 {
4921   /* Task deferred to genDiv */
4922   genDiv(ic);
4923 #if 0
4924   operand *left = IC_LEFT(ic);
4925   operand *right = IC_RIGHT(ic);
4926   operand *result= IC_RESULT(ic);  
4927
4928     FENTRY;
4929     
4930     /* assign the amsops */
4931     pic16_aopOp (left,ic,FALSE);
4932     pic16_aopOp (right,ic,FALSE);
4933     pic16_aopOp (result,ic,TRUE);
4934
4935     /* special cases first */
4936     /* both are bits */
4937     if (AOP_TYPE(left) == AOP_CRY &&
4938         AOP_TYPE(right)== AOP_CRY) {
4939         genModbits(left,right,result);
4940         goto release ;
4941     }
4942
4943     /* if both are of size == 1 */
4944     if (AOP_SIZE(left) == 1 &&
4945         AOP_SIZE(right) == 1 ) {
4946         genModOneByte(left,right,result);
4947         goto release ;
4948     }
4949
4950     /* should have been converted to function call */
4951     assert(0);
4952
4953 release :
4954     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4955     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4956     pic16_freeAsmop(result,NULL,ic,TRUE); 
4957 #endif
4958 }
4959
4960 /*-----------------------------------------------------------------*/
4961 /* genIfxJump :- will create a jump depending on the ifx           */
4962 /*-----------------------------------------------------------------*/
4963 /*
4964   note: May need to add parameter to indicate when a variable is in bit space.
4965 */
4966 static void genIfxJump (iCode *ic, char *jval)
4967 {
4968   FENTRY;
4969   
4970     /* if true label then we jump if condition
4971     supplied is true */
4972     if ( IC_TRUE(ic) ) {
4973
4974         if(strcmp(jval,"a") == 0)
4975           emitSKPZ;
4976         else if (strcmp(jval,"c") == 0)
4977           emitSKPNC;
4978         else {
4979           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4980           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4981         }
4982
4983         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4984         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4985
4986     }
4987     else {
4988         /* false label is present */
4989         if(strcmp(jval,"a") == 0)
4990           emitSKPNZ;
4991         else if (strcmp(jval,"c") == 0)
4992           emitSKPC;
4993         else {
4994           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4995           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4996         }
4997
4998         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4999         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5000
5001     }
5002
5003
5004     /* mark the icode as generated */
5005     ic->generated = 1;
5006 }
5007
5008 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5009 {
5010   FENTRY;
5011   
5012     /* if true label then we jump if condition
5013     supplied is true */
5014     if ( IC_TRUE(ic) ) {
5015       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
5016       pic16_emitpcode(POC_BTFSC, jop);
5017
5018       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5019       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5020
5021     } else {
5022       /* false label is present */
5023       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5024       pic16_emitpcode(POC_BTFSS, jop);
5025           
5026       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5027       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5028     }
5029
5030
5031     /* mark the icode as generated */
5032     ic->generated = 1;
5033 }
5034
5035 #if 0
5036 // not needed ATM
5037
5038 /*-----------------------------------------------------------------*/
5039 /* genSkip                                                         */
5040 /*-----------------------------------------------------------------*/
5041 static void genSkip(iCode *ifx,int status_bit)
5042 {
5043   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5044   if(!ifx)
5045     return;
5046
5047   if ( IC_TRUE(ifx) ) {
5048     switch(status_bit) {
5049     case 'z':
5050       emitSKPNZ;
5051       break;
5052
5053     case 'c':
5054       emitSKPNC;
5055       break;
5056
5057     case 'd':
5058       emitSKPDC;
5059       break;
5060
5061     }
5062
5063     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5064     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5065
5066   } else {
5067
5068     switch(status_bit) {
5069
5070     case 'z':
5071       emitSKPZ;
5072       break;
5073
5074     case 'c':
5075       emitSKPC;
5076       break;
5077
5078     case 'd':
5079       emitSKPDC;
5080       break;
5081     }
5082     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5083     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5084
5085   }
5086
5087 }
5088 #endif
5089
5090 /*-----------------------------------------------------------------*/
5091 /* genSkipc                                                        */
5092 /*-----------------------------------------------------------------*/
5093 static void genSkipc(resolvedIfx *rifx)
5094 {
5095   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5096   
5097   if(!rifx)
5098     return;
5099
5100   if(rifx->condition)
5101     emitSKPNC;
5102   else
5103     emitSKPC;
5104
5105   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5106   rifx->generated = 1;
5107 }
5108
5109 #if !(USE_SIMPLE_GENCMP)
5110 /*-----------------------------------------------------------------*/
5111 /* genSkipz2                                                       */
5112 /*-----------------------------------------------------------------*/
5113 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5114 {
5115   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5116   
5117   if(!rifx)
5118     return;
5119
5120   if( (rifx->condition ^ invert_condition) & 1)
5121     emitSKPZ;
5122   else
5123     emitSKPNZ;
5124
5125   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5126   rifx->generated = 1;
5127 }
5128 #endif
5129
5130 #if 0
5131 /*-----------------------------------------------------------------*/
5132 /* genSkipz                                                        */
5133 /*-----------------------------------------------------------------*/
5134 static void genSkipz(iCode *ifx, int condition)
5135 {
5136   if(!ifx)
5137     return;
5138
5139   if(condition)
5140     emitSKPNZ;
5141   else
5142     emitSKPZ;
5143
5144   if ( IC_TRUE(ifx) )
5145     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5146   else
5147     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5148
5149   if ( IC_TRUE(ifx) )
5150     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5151   else
5152     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5153
5154 }
5155 #endif
5156
5157 #if !(USE_SIMPLE_GENCMP)
5158 /*-----------------------------------------------------------------*/
5159 /* genSkipCond                                                     */
5160 /*-----------------------------------------------------------------*/
5161 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5162 {
5163   if(!rifx)
5164     return;
5165
5166   if(rifx->condition)
5167     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5168   else
5169     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5170
5171
5172   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5173   rifx->generated = 1;
5174 }
5175 #endif
5176
5177 #if 0
5178 /*-----------------------------------------------------------------*/
5179 /* genChkZeroes :- greater or less than comparison                 */
5180 /*     For each byte in a literal that is zero, inclusive or the   */
5181 /*     the corresponding byte in the operand with W                */
5182 /*     returns true if any of the bytes are zero                   */
5183 /*-----------------------------------------------------------------*/
5184 static int genChkZeroes(operand *op, int lit,  int size)
5185 {
5186
5187   int i;
5188   int flag =1;
5189
5190   while(size--) {
5191     i = (lit >> (size*8)) & 0xff;
5192
5193     if(i==0) {
5194       if(flag) 
5195         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5196       else
5197         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5198       flag = 0;
5199     }
5200   }
5201
5202   return (flag==0);
5203 }
5204 #endif
5205
5206
5207 /*-----------------------------------------------------------------*/
5208 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
5209 /*                  aop (if it's NOT a literal) or from lit (if    */
5210 /*                  aop is a literal)                              */
5211 /*-----------------------------------------------------------------*/
5212 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5213   if (aop->type == AOP_LIT) {
5214     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5215   } else {
5216     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5217   }
5218 }
5219
5220 /*-----------------------------------------------------------------*/
5221 /* genCmp :- greater or less than comparison                       */
5222 /*-----------------------------------------------------------------*/
5223
5224 #if USE_SIMPLE_GENCMP           /* { */
5225
5226 /* genCmp performs a left < right comparison, stores
5227  * the outcome in result (if != NULL) and generates
5228  * control flow code for the ifx (if != NULL).
5229  *
5230  * This version leaves in sequences like
5231  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5232  * which should be optmized by the peephole
5233  * optimizer - RN 2005-01-01 */
5234 static void genCmp (operand *left,operand *right,
5235                     operand *result, iCode *ifx, int sign)
5236 {
5237   resolvedIfx rIfx;
5238   int size;
5239   int offs;
5240   symbol *templbl;
5241   operand *dummy;
5242   unsigned long lit;
5243   unsigned long mask;
5244   int performedLt;
5245
5246   FENTRY;
5247   
5248   assert (left && right);
5249   assert (AOP_SIZE(left) == AOP_SIZE(right));
5250
5251   size = AOP_SIZE(right) - 1;
5252   mask = (0x100UL << (size*8)) - 1;
5253   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5254   performedLt = 1;
5255   templbl = NULL;
5256   lit = 0;
5257   
5258   resolveIfx (&rIfx, ifx);
5259
5260   /* handle for special cases */
5261   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5262       return;
5263
5264   /**********************************************************************
5265    * handle bits - bit compares are promoted to int compares seemingly! *
5266    **********************************************************************/
5267 #if 0
5268   // THIS IS COMPLETELY UNTESTED!
5269   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5270     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5271     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5272     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5273
5274     emitSETC;
5275     // 1 < {0,1} is false --> clear C by skipping the next instruction
5276     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5277     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5278     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5279     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5280     emitCLRC; // only skipped for left=0 && right=1
5281
5282     goto correct_result_in_carry;
5283   } // if
5284 #endif
5285
5286   /*************************************************
5287    * make sure that left is register (or the like) *
5288    *************************************************/
5289   if (!isAOP_REGlike(left)) {
5290     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5291     assert (isAOP_LIT(left));
5292     assert (isAOP_REGlike(right));
5293     // swap left and right
5294     // left < right <==> right > left <==> (right >= left + 1)
5295     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5296
5297     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5298       // MAXVALUE < right? always false
5299       if (performedLt) emitCLRC; else emitSETC;
5300       goto correct_result_in_carry;
5301     } // if
5302
5303     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5304     // that's why we handled it above.
5305     lit++;
5306
5307     dummy = left;
5308     left = right;
5309     right = dummy;
5310
5311     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5312   } else if (isAOP_LIT(right)) {
5313     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5314   } // if
5315
5316   assert (isAOP_REGlike(left)); // left must be register or the like
5317   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5318
5319   /*************************************************
5320    * special cases go here                         *
5321    *************************************************/
5322
5323   if (isAOP_LIT(right)) {
5324     if (!sign) {
5325       // unsigned comparison to a literal
5326       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5327       if (lit == 0) {
5328         // unsigned left < 0? always false
5329         if (performedLt) emitCLRC; else emitSETC;
5330         goto correct_result_in_carry;
5331       }
5332     } else {
5333       // signed comparison to a literal
5334       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5335       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5336         // signed left < 0x80000000? always false
5337         if (performedLt) emitCLRC; else emitSETC;
5338         goto correct_result_in_carry;
5339       } else if (lit == 0) {
5340         // compare left < 0; set CARRY if SIGNBIT(left) is set
5341         if (performedLt) emitSETC; else emitCLRC;
5342         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5343         if (performedLt) emitCLRC; else emitSETC;
5344         goto correct_result_in_carry;
5345       }
5346     } // if (!sign)
5347   } // right is literal
5348
5349   /*************************************************
5350    * perform a general case comparison             *
5351    * make sure we get CARRY==1 <==> left >= right  *
5352    *************************************************/
5353   // compare most significant bytes
5354   //DEBUGpc ("comparing bytes at offset %d", size);
5355   if (!sign) {
5356     // unsigned comparison
5357     mov2w_regOrLit (AOP(right), lit, size);
5358     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5359   } else {
5360     // signed comparison
5361     // (add 2^n to both operands then perform an unsigned comparison)
5362     if (isAOP_LIT(right)) {
5363       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5364       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5365
5366       if (litbyte == 0x80) {
5367         // left >= 0x80 -- always true, but more bytes to come
5368         pic16_mov2w (AOP(left), size);
5369         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5370         emitSETC;
5371       } else {
5372         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5373         pic16_mov2w (AOP(left), size);
5374         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5375         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5376       } // if
5377     } else {
5378       /* using PRODL as a temporary register here */
5379       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5380       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5381       pic16_mov2w (AOP(left), size);
5382       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5383       pic16_emitpcode (POC_MOVWF, pctemp);
5384       pic16_mov2w (AOP(right), size);
5385       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5386       pic16_emitpcode (POC_SUBFW, pctemp);
5387       //pic16_popReleaseTempReg(pctemp, 1);
5388     }
5389   } // if (!sign)
5390
5391   // compare remaining bytes (treat as unsigned case from above)
5392   templbl = newiTempLabel ( NULL );
5393   offs = size;
5394   while (offs--) {
5395     //DEBUGpc ("comparing bytes at offset %d", offs);
5396     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5397     mov2w_regOrLit (AOP(right), lit, offs);
5398     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5399   } // while (offs)
5400   pic16_emitpLabel (templbl->key);
5401   goto result_in_carry;
5402
5403 result_in_carry:
5404   
5405   /****************************************************
5406    * now CARRY contains the result of the comparison: *
5407    * SUBWF sets CARRY iff                             *
5408    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5409    * (F=left, W=right)                                *
5410    ****************************************************/
5411
5412   if (performedLt) {
5413     if (result && AOP_TYPE(result) != AOP_CRY) {
5414       // value will be stored
5415       emitTOGC;
5416     } else {
5417       // value wil only be used in the following genSkipc()
5418       rIfx.condition ^= 1;
5419     }
5420   } // if
5421
5422 correct_result_in_carry:
5423
5424   // assign result to variable (if neccessary)
5425   if (result && AOP_TYPE(result) != AOP_CRY) {
5426     //DEBUGpc ("assign result");
5427     size = AOP_SIZE(result);
5428     while (size--) {
5429       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5430     } // while
5431     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5432   } // if (result)
5433
5434   // perform conditional jump
5435   if (ifx) {
5436     //DEBUGpc ("generate control flow");
5437     genSkipc (&rIfx);
5438     ifx->generated = 1;
5439   } // if
5440 }
5441
5442 #elif 1         /* } */
5443                 /* { */
5444       /* original code */
5445 static void genCmp (operand *left,operand *right,
5446                     operand *result, iCode *ifx, int sign)
5447 {
5448   int size; //, offset = 0 ;
5449   unsigned long lit = 0L,i = 0;
5450   resolvedIfx rFalseIfx;
5451   //  resolvedIfx rTrueIfx;
5452   symbol *truelbl;
5453   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5454 /*
5455   if(ifx) {
5456     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5457     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5458   }
5459 */
5460
5461   FENTRY;
5462   
5463   resolveIfx(&rFalseIfx,ifx);
5464   truelbl  = newiTempLabel(NULL);
5465   size = max(AOP_SIZE(left),AOP_SIZE(right));
5466
5467   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5468
5469 #define _swapp
5470
5471   /* if literal is on the right then swap with left */
5472   if ((AOP_TYPE(right) == AOP_LIT)) {
5473     operand *tmp = right ;
5474     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5475     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5476 #ifdef _swapp
5477
5478     lit = (lit - 1) & mask;
5479     right = left;
5480     left = tmp;
5481     rFalseIfx.condition ^= 1;
5482 #endif
5483
5484   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5485     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5486   }
5487
5488
5489   //if(IC_TRUE(ifx) == NULL)
5490   /* if left & right are bit variables */
5491   if (AOP_TYPE(left) == AOP_CRY &&
5492       AOP_TYPE(right) == AOP_CRY ) {
5493     assert (0 && "bit variables used in genCmp");
5494     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5495     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5496   } else {
5497     /* subtract right from left if at the
5498        end the carry flag is set then we know that
5499        left is greater than right */
5500
5501     symbol *lbl  = newiTempLabel(NULL);
5502
5503 #if 0
5504         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5505                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5506 #endif
5507
5508 #ifndef _swapp
5509     if(AOP_TYPE(right) == AOP_LIT) {
5510
5511       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5512
5513       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5514
5515       /* special cases */
5516
5517       if(lit == 0) {
5518
5519         if(sign != 0) 
5520           genSkipCond(&rFalseIfx,left,size-1,7);
5521         else 
5522           /* no need to compare to 0...*/
5523           /* NOTE: this is a de-generate compare that most certainly 
5524            *       creates some dead code. */
5525           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5526
5527         if(ifx) ifx->generated = 1;
5528         return;
5529
5530       }
5531       size--;
5532
5533       if(size == 0) {
5534         //i = (lit >> (size*8)) & 0xff;
5535         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5536         
5537         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5538
5539         i = ((0-lit) & 0xff);
5540         if(sign) {
5541           if( i == 0x81) { 
5542             /* lit is 0x7f, all signed chars are less than
5543              * this except for 0x7f itself */
5544             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5545             genSkipz2(&rFalseIfx,0);
5546           } else {
5547             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5548             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5549             genSkipc(&rFalseIfx);
5550           }
5551
5552         } else {
5553           if(lit == 1) {
5554             genSkipz2(&rFalseIfx,1);
5555           } else {
5556             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5557             genSkipc(&rFalseIfx);
5558           }
5559         }
5560
5561         if(ifx) ifx->generated = 1;
5562         return;
5563       }
5564
5565       /* chars are out of the way. now do ints and longs */
5566
5567
5568       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5569         
5570       /* special cases */
5571
5572       if(sign) {
5573
5574         if(lit == 0) {
5575           genSkipCond(&rFalseIfx,left,size,7);
5576           if(ifx) ifx->generated = 1;
5577           return;
5578         }
5579
5580         if(lit <0x100) {
5581           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5582
5583           //rFalseIfx.condition ^= 1;
5584           //genSkipCond(&rFalseIfx,left,size,7);
5585           //rFalseIfx.condition ^= 1;
5586
5587           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5588           if(rFalseIfx.condition)
5589             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5590           else
5591             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5592
5593           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5594           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5595           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5596
5597           while(size > 1)
5598             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5599
5600           if(rFalseIfx.condition) {
5601             emitSKPZ;
5602             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5603
5604           } else {
5605             emitSKPNZ;
5606           }
5607
5608           genSkipc(&rFalseIfx);
5609           pic16_emitpLabel(truelbl->key);
5610           if(ifx) ifx->generated = 1;
5611           return;
5612
5613         }
5614
5615         if(size == 1) {
5616
5617           if( (lit & 0xff) == 0) {
5618             /* lower byte is zero */
5619             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5620             i = ((lit >> 8) & 0xff) ^0x80;
5621             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5622             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5623             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5624             genSkipc(&rFalseIfx);
5625
5626
5627             if(ifx) ifx->generated = 1;
5628             return;
5629
5630           }
5631         } else {
5632           /* Special cases for signed longs */
5633           if( (lit & 0xffffff) == 0) {
5634             /* lower byte is zero */
5635             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5636             i = ((lit >> 8*3) & 0xff) ^0x80;
5637             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5638             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5639             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5640             genSkipc(&rFalseIfx);
5641
5642
5643             if(ifx) ifx->generated = 1;
5644             return;
5645
5646           }
5647
5648         }
5649
5650
5651         if(lit & (0x80 << (size*8))) {
5652           /* lit is negative */
5653           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5654
5655           //genSkipCond(&rFalseIfx,left,size,7);
5656
5657           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5658
5659           if(rFalseIfx.condition)
5660             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5661           else
5662             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5663
5664
5665         } else {
5666           /* lit is positive */
5667           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5668           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5669           if(rFalseIfx.condition)
5670             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5671           else
5672             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5673
5674         }
5675
5676         /*
5677           This works, but is only good for ints.
5678           It also requires a "known zero" register.
5679           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5680           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5681           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5682           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5683           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5684           genSkipc(&rFalseIfx);
5685
5686           pic16_emitpLabel(truelbl->key);
5687           if(ifx) ifx->generated = 1;
5688           return;
5689         **/
5690           
5691         /* There are no more special cases, so perform a general compare */
5692   
5693         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5694         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5695
5696         while(size--) {
5697
5698           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5699           emitSKPNZ;
5700           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5701         }
5702         //rFalseIfx.condition ^= 1;
5703         genSkipc(&rFalseIfx);
5704
5705         pic16_emitpLabel(truelbl->key);
5706
5707         if(ifx) ifx->generated = 1;
5708         return;
5709
5710
5711       }
5712
5713
5714       /* sign is out of the way. So now do an unsigned compare */
5715       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5716
5717
5718       /* General case - compare to an unsigned literal on the right.*/
5719
5720       i = (lit >> (size*8)) & 0xff;
5721       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5722       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5723       while(size--) {
5724         i = (lit >> (size*8)) & 0xff;
5725
5726         if(i) {
5727           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5728           emitSKPNZ;
5729           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5730         } else {
5731           /* this byte of the lit is zero, 
5732            *if it's not the last then OR in the variable */
5733           if(size)
5734             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5735         }
5736       }
5737
5738
5739       pic16_emitpLabel(lbl->key);
5740 //      pic16_emitpLabel(truelbl->key);
5741       //if(emitFinalCheck)
5742       genSkipc(&rFalseIfx);
5743       if(sign)
5744         pic16_emitpLabel(truelbl->key);
5745
5746       if(ifx) ifx->generated = 1;
5747       return;
5748
5749
5750     }
5751 #endif  // _swapp
5752
5753     if(AOP_TYPE(left) == AOP_LIT) {
5754       //symbol *lbl = newiTempLabel(NULL);
5755
5756       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5757
5758
5759       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5760
5761       /* Special cases */
5762       if((lit == 0) && (sign == 0)){
5763
5764         size--;
5765         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5766         while(size) 
5767           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5768
5769         genSkipz2(&rFalseIfx,0);
5770         if(ifx) ifx->generated = 1;
5771         return;
5772       }
5773
5774       if(size==1) {
5775         /* Special cases */
5776         lit &= 0xff;
5777         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5778           /* degenerate compare can never be true */
5779           if(rFalseIfx.condition == 0)
5780             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5781
5782           if(ifx) ifx->generated = 1;
5783           return;
5784         }
5785
5786         if(sign) {
5787           /* signed comparisons to a literal byte */
5788
5789           int lp1 = (lit+1) & 0xff;
5790
5791           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5792           switch (lp1) {
5793           case 0:
5794             rFalseIfx.condition ^= 1;
5795             genSkipCond(&rFalseIfx,right,0,7);
5796             break;
5797           case 0x7f:
5798             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5799             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5800             genSkipz2(&rFalseIfx,1);
5801             break;
5802           default:
5803             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5804             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5805             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5806             rFalseIfx.condition ^= 1;
5807             genSkipc(&rFalseIfx);
5808             break;
5809           }
5810         } else {
5811           /* unsigned comparisons to a literal byte */
5812
5813           switch(lit & 0xff ) {
5814           case 0:
5815             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5816             genSkipz2(&rFalseIfx,0);
5817             break;
5818           case 0x7f:
5819             rFalseIfx.condition ^= 1;
5820             genSkipCond(&rFalseIfx,right,0,7);
5821             break;
5822
5823           default:
5824             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5825             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5826             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5827             rFalseIfx.condition ^= 1;
5828             if (AOP_TYPE(result) == AOP_CRY)
5829               genSkipc(&rFalseIfx);
5830             else {
5831               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5832               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5833             }         
5834             break;
5835           }
5836         }
5837
5838         if(ifx) ifx->generated = 1;
5839         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5840                 goto check_carry;
5841         return;
5842
5843       } else {
5844
5845         /* Size is greater than 1 */
5846
5847         if(sign) {
5848           int lp1 = lit+1;
5849
5850           size--;
5851
5852           if(lp1 == 0) {
5853             /* this means lit = 0xffffffff, or -1 */
5854
5855
5856             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5857             rFalseIfx.condition ^= 1;
5858             genSkipCond(&rFalseIfx,right,size,7);
5859             if(ifx) ifx->generated = 1;
5860
5861             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5862               goto check_carry;
5863
5864             return;
5865           }
5866
5867           if(lit == 0) {
5868             int s = size;
5869
5870             if(rFalseIfx.condition) {
5871               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5872               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5873             }
5874
5875             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5876             while(size--)
5877               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5878
5879
5880             emitSKPZ;
5881             if(rFalseIfx.condition) {
5882               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5883               pic16_emitpLabel(truelbl->key);
5884             }else {
5885               rFalseIfx.condition ^= 1;
5886               genSkipCond(&rFalseIfx,right,s,7);
5887             }
5888
5889             if(ifx) ifx->generated = 1;
5890
5891             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5892               goto check_carry;
5893
5894             return;
5895           }
5896
5897           if((size == 1) &&  (0 == (lp1&0xff))) {
5898             /* lower byte of signed word is zero */
5899             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5900             i = ((lp1 >> 8) & 0xff) ^0x80;
5901             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5902             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5903             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5904
5905             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5906               emitTOGC;
5907               if(ifx) ifx->generated = 1;
5908               goto check_carry;
5909             } else {
5910               rFalseIfx.condition ^= 1;
5911               genSkipc(&rFalseIfx);
5912               if(ifx) ifx->generated = 1;
5913             }
5914
5915             return;
5916           }
5917
5918           if(lit & (0x80 << (size*8))) {
5919             /* Lit is less than zero */
5920             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5921             //rFalseIfx.condition ^= 1;
5922             //genSkipCond(&rFalseIfx,left,size,7);
5923             //rFalseIfx.condition ^= 1;
5924             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5925             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5926
5927             if(rFalseIfx.condition)
5928               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5929             else
5930               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5931
5932
5933           } else {
5934             /* Lit is greater than or equal to zero */
5935             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5936             //rFalseIfx.condition ^= 1;
5937             //genSkipCond(&rFalseIfx,right,size,7);
5938             //rFalseIfx.condition ^= 1;
5939
5940             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5941             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5942
5943             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5944             if(rFalseIfx.condition)
5945               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5946             else
5947               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5948
5949           }
5950
5951           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5952           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5953
5954           while(size--) {
5955
5956             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5957             emitSKPNZ;
5958             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5959           }
5960           rFalseIfx.condition ^= 1;
5961           //rFalseIfx.condition = 1;
5962           genSkipc(&rFalseIfx);
5963
5964           pic16_emitpLabel(truelbl->key);
5965
5966           if(ifx) ifx->generated = 1;
5967
5968
5969           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5970             goto check_carry;
5971
5972           return;
5973           // end of if (sign)
5974         } else {
5975
5976           /* compare word or long to an unsigned literal on the right.*/
5977
5978
5979           size--;
5980           if(lit < 0xff) {
5981             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5982             switch (lit) {
5983             case 0:
5984               break; /* handled above */
5985 /*
5986             case 0xff:
5987               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5988               while(size--)
5989                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5990               genSkipz2(&rFalseIfx,0);
5991               break;
5992 */
5993             default:
5994               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5995               while(--size)
5996                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5997
5998               emitSKPZ;
5999               if(rFalseIfx.condition)
6000                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6001               else
6002                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6003
6004
6005               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6006               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6007
6008               rFalseIfx.condition ^= 1;
6009               genSkipc(&rFalseIfx);
6010             }
6011
6012             pic16_emitpLabel(truelbl->key);
6013
6014             if(ifx) ifx->generated = 1;
6015
6016             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6017               goto check_carry;
6018
6019             return;
6020           }
6021
6022
6023           lit++;
6024           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6025           i = (lit >> (size*8)) & 0xff;
6026
6027           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6028           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6029
6030           while(size--) {
6031             i = (lit >> (size*8)) & 0xff;
6032
6033             if(i) {
6034               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6035               emitSKPNZ;
6036               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6037             } else {
6038               /* this byte of the lit is zero, 
6039                * if it's not the last then OR in the variable */
6040               if(size)
6041                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6042             }
6043           }
6044
6045
6046           pic16_emitpLabel(lbl->key);
6047
6048           rFalseIfx.condition ^= 1;
6049
6050           genSkipc(&rFalseIfx);
6051         }
6052
6053         if(sign)
6054           pic16_emitpLabel(truelbl->key);
6055         if(ifx) ifx->generated = 1;
6056
6057             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6058               goto check_carry;
6059
6060         return;
6061       }
6062     }
6063     /* Compare two variables */
6064
6065     DEBUGpic16_emitcode(";sign","%d",sign);
6066
6067     size--;
6068     if(sign) {
6069       /* Sigh. thus sucks... */
6070       if(size) {
6071         pCodeOp *pctemp;
6072         
6073         pctemp = pic16_popGetTempReg(1);
6074         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6075         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6076         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6077         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6078         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6079         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6080         pic16_popReleaseTempReg(pctemp, 1);
6081       } else {
6082         /* Signed char comparison */
6083         /* Special thanks to Nikolai Golovchenko for this snippet */
6084         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6085         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6086         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6087         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6088         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6089         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6090
6091         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6092         genSkipc(&rFalseIfx);
6093           
6094         if(ifx) ifx->generated = 1;
6095
6096             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6097               goto check_carry;
6098
6099         return;
6100       }
6101
6102     } else {
6103
6104       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6105       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6106     }
6107
6108
6109     /* The rest of the bytes of a multi-byte compare */
6110     while (size) {
6111
6112       emitSKPZ;
6113       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6114       size--;
6115
6116       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6117       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6118
6119
6120     }
6121
6122     pic16_emitpLabel(lbl->key);
6123
6124     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6125     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6126         (AOP_TYPE(result) == AOP_REG)) {
6127       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6128       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6129     } else {
6130       genSkipc(&rFalseIfx);
6131     }         
6132     //genSkipc(&rFalseIfx);
6133     if(ifx) ifx->generated = 1;
6134
6135
6136             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6137               goto check_carry;
6138
6139     return;
6140
6141   }
6142
6143 check_carry:
6144   if ((AOP_TYPE(result) != AOP_CRY) 
6145         && AOP_SIZE(result)) {
6146     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6147
6148     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6149
6150     pic16_outBitC(result);
6151   } else {
6152     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6153     /* if the result is used in the next
6154        ifx conditional branch then generate
6155        code a little differently */
6156     if (ifx )
6157       genIfxJump (ifx,"c");
6158     else
6159       pic16_outBitC(result);
6160     /* leave the result in acc */
6161   }
6162
6163 }
6164
6165 #elif 0 /* VR version of genCmp() */    /* } else { */
6166
6167 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6168 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6169         operand *result, int offset, int invert_op)
6170 {
6171   /* add code here */
6172   
6173   /* check condition, > or < ?? */
6174   if(rIfx->condition != 0)invert_op ^= 1;
6175   
6176   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6177
6178   if(!ifx)invert_op ^= 1;
6179
6180   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6181       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6182   
6183   /* do selection */
6184   if(!invert_op)return POC_CPFSGT;
6185   else return POC_CPFSLT;
6186 }
6187
6188 static int compareAopfirstpass=1;
6189
6190 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6191             operand *oper, int offset, operand *result,
6192             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6193             symbol *tlbl)
6194 {
6195   int op;
6196   symbol *truelbl;
6197
6198   /* invert if there is a result to be loaded, in order to fit,
6199    * SETC/CLRC sequence */
6200   if(AOP_SIZE(result))invert_op ^= 1;
6201
6202 //  if(sign && !offset)invert_op ^= 1;
6203   
6204 //  if(sign)invert_op ^= 1;
6205   
6206   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6207
6208   if(AOP_SIZE(result) && compareAopfirstpass) {
6209     if(!ifx) {
6210       if(pcop2)
6211         pic16_emitpcode(POC_SETF, pcop2);
6212       else
6213         emitSETC;
6214     } else {
6215       if(pcop2)
6216         pic16_emitpcode(POC_CLRF, pcop2);
6217       else
6218         emitCLRC;
6219     }
6220   }
6221
6222   compareAopfirstpass = 0;
6223
6224       /* there is a bug when comparing operands with size > 1,
6225        * because higher bytes can be equal and test should be performed
6226        * to the next lower byte, current algorithm, considers operands
6227        * inequal in these cases! -- VR 20041107 */
6228
6229     
6230   if(pcop)
6231     pic16_emitpcode(op, pcop);
6232   else
6233     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6234
6235
6236   if((!sign || !offset) && AOP_SIZE(result)) {
6237     if(!ifx) {
6238       if(pcop2)
6239         pic16_emitpcode(POC_CLRF, pcop2);
6240         else
6241         emitCLRC;
6242     } else {
6243       if(pcop2)
6244         pic16_emitpcode(POC_SETF, pcop2);
6245       else
6246         emitSETC;
6247     }
6248     
6249     /* don't emit final branch (offset == 0) */
6250     if(offset) {
6251
6252       if(pcop2)
6253         pic16_emitpcode(POC_RRCF, pcop2);
6254
6255       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6256     }
6257   } else {
6258     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6259       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6260             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6261
6262       truelbl = newiTempLabel( NULL );
6263       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6264       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6265         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6266       else
6267         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6268       pic16_emitpLabel(truelbl->key);
6269     } else {
6270       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6271     }
6272   }
6273 }
6274
6275 static void genCmp (operand *left, operand *right,
6276                     operand *result, iCode *ifx, int sign)
6277 {
6278   int size, cmpop=1;
6279   long lit = 0L;
6280   resolvedIfx rFalseIfx;
6281   symbol *falselbl, *tlbl;
6282
6283     FENTRY;
6284     
6285     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6286
6287     resolveIfx(&rFalseIfx, ifx);
6288     size = max(AOP_SIZE(left), AOP_SIZE(right));
6289     
6290     /* if left & right are bit variables */
6291     if(AOP_TYPE(left) == AOP_CRY
6292       && AOP_TYPE(right) == AOP_CRY ) {
6293
6294         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6295         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6296         
6297         werror(W_POSSBUG2, __FILE__, __LINE__);
6298         exit(EXIT_FAILURE);
6299     }
6300     
6301     /* if literal is on the right then swap with left */
6302     if((AOP_TYPE(right) == AOP_LIT)) {
6303       operand *tmp = right ;
6304 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6305
6306         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6307
6308 //      lit = (lit - 1) & mask;
6309         right = left;
6310         left = tmp;
6311         rFalseIfx.condition ^= 1;               /* reverse compare */
6312     } else
6313     if ((AOP_TYPE(left) == AOP_LIT)) {
6314       /* float compares are handled by support functions */
6315       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6316     }
6317
6318     /* actual comparing algorithm */
6319 //    size = AOP_SIZE( right );
6320
6321     falselbl = newiTempLabel( NULL );
6322     if(AOP_TYPE(left) == AOP_LIT) {
6323       /* compare to literal */
6324       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6325       
6326       if(sign) {
6327         pCodeOp *pct, *pct2;
6328         symbol *tlbl1;
6329
6330         /* signed compare */
6331         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6332
6333         /* using PRODL:PRODH as a temporary register here */
6334         pct = pic16_popCopyReg(&pic16_pc_prodl);
6335         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6336         tlbl = newiTempLabel( NULL );
6337         
6338         /* first compare signs:
6339          *  a. if both are positive, compare just like unsigned
6340          *  b. if both are negative, invert cmpop, compare just like unsigned
6341          *  c. if different signs, determine the result directly */
6342
6343         size--;
6344
6345 #if 1
6346         /* { */
6347         tlbl1 = newiTempLabel( NULL );
6348 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6349
6350         if(lit > 0) {
6351
6352           /* literal is zero or positive:
6353            *  a. if carry is zero, too, continue compare,
6354            *  b. if carry is set, then continue depending on cmpop ^ condition:
6355            *    1. '<' return false (literal < variable),
6356            *    2. '>' return true (literal > variable) */
6357 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6358           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6359           
6360           
6361           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6362           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6363         } else 
6364         if(lit < 0) {
6365           
6366           /* literal is negative:
6367            *  a. if carry is set, too, continue compare,
6368            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6369            *    1. '<' return true (literal < variable),
6370            *    2. '>' return false (literal > variable) */
6371 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6372           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6373           
6374           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6375           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6376         }
6377 #if 1
6378         else {
6379           /* lit == 0 */
6380           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6381           
6382           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6383           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6384         }
6385 #endif
6386         
6387         
6388         pic16_emitpLabel( tlbl1->key );
6389 #endif  /* } */
6390
6391         compareAopfirstpass=1;
6392 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6393 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6394 //        pic16_emitpcode(POC_MOVWF, pct);
6395
6396 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6397         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6398 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6399         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6400
6401         /* generic case */        
6402           while( size-- ) {
6403 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6404 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6405 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6406 //            pic16_emitpcode(POC_MOVWF, pct);
6407
6408 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6409             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6410             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6411 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6412 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6413           }
6414         
6415         if(ifx)ifx->generated = 1;
6416
6417         if(AOP_SIZE(result)) {
6418           pic16_emitpLabel(tlbl->key);
6419           pic16_emitpLabel(falselbl->key);
6420           pic16_outBitOp( result, pct2 );
6421         } else {
6422           pic16_emitpLabel(tlbl->key);
6423         }
6424       } else {
6425
6426         /* unsigned compare */      
6427         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6428     
6429         compareAopfirstpass=1;
6430         while(size--) {
6431           
6432           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6433           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6434
6435         }
6436         if(ifx)ifx->generated = 1;
6437
6438         if(AOP_SIZE(result)) {
6439           pic16_emitpLabel(falselbl->key);
6440           pic16_outBitC( result );
6441         }
6442
6443       }
6444     } else {
6445       /* compare registers */
6446       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6447
6448
6449       if(sign) {
6450         pCodeOp *pct, *pct2;
6451         
6452         /* signed compare */
6453         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6454
6455         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6456         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6457         tlbl = newiTempLabel( NULL );
6458         
6459         compareAopfirstpass=1;
6460
6461         size--;
6462         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6463 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6464         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6465         pic16_emitpcode(POC_MOVWF, pct);
6466
6467         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6468 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6469         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6470
6471         /* WREG already holds left + 0x80 */
6472         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6473         
6474         while( size-- ) {
6475           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6476 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6477           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6478           pic16_emitpcode(POC_MOVWF, pct);
6479                 
6480           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6481 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6482           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6483
6484           /* WREG already holds left + 0x80 */
6485           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6486 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6487         }
6488         
6489         if(ifx)ifx->generated = 1;
6490
6491         if(AOP_SIZE(result)) {
6492           pic16_emitpLabel(tlbl->key);
6493           pic16_emitpLabel(falselbl->key);
6494           pic16_outBitOp( result, pct2 );
6495         } else {
6496           pic16_emitpLabel(tlbl->key);
6497         }
6498
6499       } else {
6500         /* unsigned compare */      
6501         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6502
6503         compareAopfirstpass=1;
6504         while(size--) {
6505           
6506           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6507           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6508
6509         }
6510
6511         if(ifx)ifx->generated = 1;
6512         if(AOP_SIZE(result)) {
6513
6514           pic16_emitpLabel(falselbl->key);
6515           pic16_outBitC( result );
6516         }
6517
6518       }
6519     }
6520 }
6521
6522 #endif  /* } */
6523
6524
6525
6526 /*-----------------------------------------------------------------*/
6527 /* genCmpGt :- greater than comparison                             */
6528 /*-----------------------------------------------------------------*/
6529 static void genCmpGt (iCode *ic, iCode *ifx)
6530 {
6531   operand *left, *right, *result;
6532   sym_link *letype , *retype;
6533   int sign ;
6534
6535     FENTRY;
6536     
6537     left = IC_LEFT(ic);
6538     right= IC_RIGHT(ic);
6539     result = IC_RESULT(ic);
6540
6541     letype = getSpec(operandType(left));
6542     retype =getSpec(operandType(right));
6543     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6544     /* assign the amsops */
6545     pic16_aopOp (left,ic,FALSE);
6546     pic16_aopOp (right,ic,FALSE);
6547     pic16_aopOp (result,ic,TRUE);
6548
6549     genCmp(right, left, result, ifx, sign);
6550
6551     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6552     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6553     pic16_freeAsmop(result,NULL,ic,TRUE); 
6554 }
6555
6556 /*-----------------------------------------------------------------*/
6557 /* genCmpLt - less than comparisons                                */
6558 /*-----------------------------------------------------------------*/
6559 static void genCmpLt (iCode *ic, iCode *ifx)
6560 {
6561   operand *left, *right, *result;
6562   sym_link *letype , *retype;
6563   int sign ;
6564
6565     FENTRY;
6566
6567     left = IC_LEFT(ic);
6568     right= IC_RIGHT(ic);
6569     result = IC_RESULT(ic);
6570
6571     letype = getSpec(operandType(left));
6572     retype =getSpec(operandType(right));
6573     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6574
6575     /* assign the amsops */
6576     pic16_aopOp (left,ic,FALSE);
6577     pic16_aopOp (right,ic,FALSE);
6578     pic16_aopOp (result,ic,TRUE);
6579
6580     genCmp(left, right, result, ifx, sign);
6581
6582     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6583     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6584     pic16_freeAsmop(result,NULL,ic,TRUE); 
6585 }
6586
6587 #if 0
6588 // not needed ATM
6589 // FIXME reenable literal optimisation when the pic16 port is stable
6590
6591 /*-----------------------------------------------------------------*/
6592 /* genc16bit2lit - compare a 16 bit value to a literal             */
6593 /*-----------------------------------------------------------------*/
6594 static void genc16bit2lit(operand *op, int lit, int offset)
6595 {
6596   int i;
6597
6598   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6599   if( (lit&0xff) == 0) 
6600     i=1;
6601   else
6602     i=0;
6603
6604   switch( BYTEofLONG(lit,i)) { 
6605   case 0:
6606     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6607     break;
6608   case 1:
6609     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6610     break;
6611   case 0xff:
6612     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6613     break;
6614   default:
6615     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6616     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6617   }
6618
6619   i ^= 1;
6620
6621   switch( BYTEofLONG(lit,i)) { 
6622   case 0:
6623     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6624     break;
6625   case 1:
6626     emitSKPNZ;
6627     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6628     break;
6629   case 0xff:
6630     emitSKPNZ;
6631     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6632     break;
6633   default:
6634     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6635     emitSKPNZ;
6636     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6637
6638   }
6639
6640 }
6641 #endif
6642
6643 #if 0
6644 // not needed ATM
6645 /*-----------------------------------------------------------------*/
6646 /* gencjneshort - compare and jump if not equal                    */
6647 /*-----------------------------------------------------------------*/
6648 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6649 {
6650   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6651   int offset = 0;
6652   int res_offset = 0;  /* the result may be a different size then left or right */
6653   int res_size = AOP_SIZE(result);
6654   resolvedIfx rIfx;
6655   symbol *lbl, *lbl_done;
6656
6657   unsigned long lit = 0L;
6658   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6659
6660   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6661   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6662   if(result)
6663     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6664   resolveIfx(&rIfx,ifx);
6665   lbl =  newiTempLabel(NULL);
6666   lbl_done =  newiTempLabel(NULL);
6667
6668
6669   /* if the left side is a literal or 
6670      if the right is in a pointer register and left 
6671      is not */
6672   if ((AOP_TYPE(left) == AOP_LIT) || 
6673       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6674     operand *t = right;
6675     right = left;
6676     left = t;
6677   }
6678   if(AOP_TYPE(right) == AOP_LIT)
6679     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6680
6681   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6682     preserve_result = 1;
6683
6684   if(result && !preserve_result)
6685     {
6686       int i;
6687       for(i = 0; i < AOP_SIZE(result); i++)
6688         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6689     }
6690
6691
6692   /* if the right side is a literal then anything goes */
6693   if (AOP_TYPE(right) == AOP_LIT &&
6694       AOP_TYPE(left) != AOP_DIR ) {
6695     switch(size) {
6696     case 2:
6697       genc16bit2lit(left, lit, 0);
6698       emitSKPZ;
6699       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6700       break;
6701     default:
6702       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6703       while (size--) {
6704         if(lit & 0xff) {
6705           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6706           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6707         } else {
6708           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6709         }
6710
6711         emitSKPZ;
6712         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6713         offset++;
6714         if(res_offset < res_size-1)
6715           res_offset++;
6716         lit >>= 8;
6717       }
6718       break;
6719     }
6720   }
6721
6722   /* if the right side is in a register or in direct space or
6723      if the left is a pointer register & right is not */    
6724   else if (AOP_TYPE(right) == AOP_REG ||
6725            AOP_TYPE(right) == AOP_DIR || 
6726            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6727            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6728     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6729     int lbl_key = lbl->key;
6730
6731     if(result) {
6732       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6733       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6734     }else {
6735       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6736       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6737               __FUNCTION__,__LINE__);
6738       return;
6739     }
6740    
6741 /*     switch(size) { */
6742 /*     case 2: */
6743 /*       genc16bit2lit(left, lit, 0); */
6744 /*       emitSKPNZ; */
6745 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6746 /*       break; */
6747 /*     default: */
6748     while (size--) {
6749       int emit_skip=1;
6750       if((AOP_TYPE(left) == AOP_DIR) && 
6751          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6752
6753         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6754         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6755
6756       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6757             
6758         switch (lit & 0xff) {
6759         case 0:
6760           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6761           break;
6762         case 1:
6763           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6764           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6765           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6766           emit_skip=0;
6767           break;
6768         case 0xff:
6769           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6770           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6771           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6772           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6773           emit_skip=0;
6774           break;
6775         default:
6776           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6777           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6778         }
6779         lit >>= 8;
6780
6781       } else {
6782         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6783       }
6784       if(emit_skip) {
6785         if(AOP_TYPE(result) == AOP_CRY) {
6786           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6787           if(rIfx.condition)
6788             emitSKPNZ;
6789           else
6790             emitSKPZ;
6791           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6792         } else {
6793           /* fix me. probably need to check result size too */
6794           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6795           if(rIfx.condition)
6796             emitSKPZ;
6797           else
6798             emitSKPNZ;
6799           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6800           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6801         }
6802         if(ifx)
6803           ifx->generated=1;
6804       }
6805       emit_skip++;
6806       offset++;
6807       if(res_offset < res_size-1)
6808         res_offset++;
6809     }
6810 /*       break; */
6811 /*     } */
6812   } else if(AOP_TYPE(right) == AOP_REG &&
6813             AOP_TYPE(left) != AOP_DIR){
6814
6815     while(size--) {
6816       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6817       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6818       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6819       if(rIfx.condition)
6820         emitSKPNZ;
6821       else
6822         emitSKPZ;
6823       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6824       offset++;
6825       if(res_offset < res_size-1)
6826         res_offset++;
6827     }
6828       
6829   }else{
6830     /* right is a pointer reg need both a & b */
6831     while(size--) {
6832       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6833       if(strcmp(l,"b"))
6834         pic16_emitcode("mov","b,%s",l);
6835       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6836       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6837       offset++;
6838     }
6839   }
6840
6841   if(result && preserve_result)
6842     {
6843       int i;
6844       for(i = 0; i < AOP_SIZE(result); i++)
6845         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6846     }
6847
6848   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6849
6850   if(result && preserve_result)
6851     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6852
6853   if(!rIfx.condition)
6854     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6855
6856   pic16_emitpLabel(lbl->key);
6857
6858   if(result && preserve_result)
6859     {
6860       int i;
6861       for(i = 0; i < AOP_SIZE(result); i++)
6862         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6863
6864       pic16_emitpLabel(lbl_done->key);
6865    }
6866
6867   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6868
6869   if(ifx)
6870     ifx->generated = 1;
6871 }
6872 #endif
6873
6874 #if 0
6875 /*-----------------------------------------------------------------*/
6876 /* gencjne - compare and jump if not equal                         */
6877 /*-----------------------------------------------------------------*/
6878 static void gencjne(operand *left, operand *right, iCode *ifx)
6879 {
6880     symbol *tlbl  = newiTempLabel(NULL);
6881
6882     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6883     gencjneshort(left, right, lbl);
6884
6885     pic16_emitcode("mov","a,%s",one);
6886     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6887     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6888     pic16_emitcode("clr","a");
6889     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6890
6891     pic16_emitpLabel(lbl->key);
6892     pic16_emitpLabel(tlbl->key);
6893
6894 }
6895 #endif
6896
6897
6898 /*-----------------------------------------------------------------*/
6899 /* is_LitOp - check if operand has to be treated as literal        */
6900 /*-----------------------------------------------------------------*/
6901 static bool is_LitOp(operand *op)
6902 {
6903   return ((AOP_TYPE(op) == AOP_LIT)
6904       || ( (AOP_TYPE(op) == AOP_PCODE)
6905           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6906               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6907 }
6908
6909 /*-----------------------------------------------------------------*/
6910 /* is_LitAOp - check if operand has to be treated as literal        */
6911 /*-----------------------------------------------------------------*/
6912 static bool is_LitAOp(asmop *aop)
6913 {
6914   return ((aop->type == AOP_LIT)
6915       || ( (aop->type == AOP_PCODE)
6916           && ( (aop->aopu.pcop->type == PO_LITERAL)
6917               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6918 }
6919
6920
6921
6922 /*-----------------------------------------------------------------*/
6923 /* genCmpEq - generates code for equal to                          */
6924 /*-----------------------------------------------------------------*/
6925 static void genCmpEq (iCode *ic, iCode *ifx)
6926 {
6927   operand *left, *right, *result;
6928   symbol *falselbl = newiTempLabel(NULL);
6929   symbol *donelbl = newiTempLabel(NULL);
6930
6931   int preserve_result = 0;
6932   int generate_result = 0;
6933   int i=0;
6934   unsigned long lit = -1;
6935
6936   FENTRY;
6937   
6938   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6939   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6940   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6941  
6942   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6943
6944   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6945     {
6946       werror(W_POSSBUG2, __FILE__, __LINE__);
6947       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6948       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6949       goto release;
6950     }
6951
6952   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6953     {
6954       operand *tmp = right ;
6955       right = left;
6956       left = tmp;
6957     }
6958
6959   if (AOP_TYPE(right) == AOP_LIT) {
6960     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6961   }
6962
6963   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6964     preserve_result = 1;
6965
6966   if(result && AOP_SIZE(result))
6967     generate_result = 1;
6968
6969   if(generate_result && !preserve_result)
6970     {
6971       for(i = 0; i < AOP_SIZE(result); i++)
6972         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6973     }
6974
6975   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6976   for(i=0; i < AOP_SIZE(left); i++)
6977     {
6978       if(AOP_TYPE(left) != AOP_ACC)
6979         {
6980           if(is_LitOp(left))
6981             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6982           else
6983             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6984         }
6985       if(is_LitOp(right)) {
6986         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6987           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6988         }
6989       } else
6990         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6991
6992       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6993     }
6994
6995   // result == true
6996
6997   if(generate_result && preserve_result)
6998     {
6999       for(i = 0; i < AOP_SIZE(result); i++)
7000         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7001     }
7002
7003   if(generate_result)
7004     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7005
7006   if(generate_result && preserve_result)
7007     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7008
7009   if(ifx && IC_TRUE(ifx))
7010     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7011
7012   if(ifx && IC_FALSE(ifx))
7013     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7014
7015   pic16_emitpLabel(falselbl->key);
7016
7017   // result == false
7018
7019   if(ifx && IC_FALSE(ifx))
7020     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7021
7022   if(generate_result && preserve_result)
7023     {
7024       for(i = 0; i < AOP_SIZE(result); i++)
7025         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7026     }
7027
7028   pic16_emitpLabel(donelbl->key);
7029
7030   if(ifx)
7031     ifx->generated = 1;
7032
7033 release:
7034   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7035   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7036   pic16_freeAsmop(result,NULL,ic,TRUE);
7037
7038 }
7039
7040
7041 #if 0
7042 // old version kept for reference
7043
7044 /*-----------------------------------------------------------------*/
7045 /* genCmpEq - generates code for equal to                          */
7046 /*-----------------------------------------------------------------*/
7047 static void genCmpEq (iCode *ic, iCode *ifx)
7048 {
7049     operand *left, *right, *result;
7050     unsigned long lit = 0L;
7051     int size,offset=0;
7052     symbol *falselbl  = newiTempLabel(NULL);
7053
7054
7055     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7056
7057     if(ifx)
7058       DEBUGpic16_emitcode ("; ifx is non-null","");
7059     else
7060       DEBUGpic16_emitcode ("; ifx is null","");
7061
7062     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7063     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7064     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7065
7066     size = max(AOP_SIZE(left),AOP_SIZE(right));
7067
7068     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7069
7070     /* if literal, literal on the right or 
7071     if the right is in a pointer register and left 
7072     is not */
7073     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7074         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7075       operand *tmp = right ;
7076       right = left;
7077       left = tmp;
7078     }
7079
7080
7081     if(ifx && !AOP_SIZE(result)){
7082         symbol *tlbl;
7083         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7084         /* if they are both bit variables */
7085         if (AOP_TYPE(left) == AOP_CRY &&
7086             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7087                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7088             if(AOP_TYPE(right) == AOP_LIT){
7089                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7090                 if(lit == 0L){
7091                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7092                     pic16_emitcode("cpl","c");
7093                 } else if(lit == 1L) {
7094                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7095                 } else {
7096                     pic16_emitcode("clr","c");
7097                 }
7098                 /* AOP_TYPE(right) == AOP_CRY */
7099             } else {
7100                 symbol *lbl = newiTempLabel(NULL);
7101                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7102                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7103                 pic16_emitcode("cpl","c");
7104                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7105             }
7106             /* if true label then we jump if condition
7107             supplied is true */
7108             tlbl = newiTempLabel(NULL);
7109             if ( IC_TRUE(ifx) ) {
7110                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7111                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7112             } else {
7113                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7114                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7115             }
7116             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7117
7118                 {
7119                 /* left and right are both bit variables, result is carry */
7120                         resolvedIfx rIfx;
7121               
7122                         resolveIfx(&rIfx,ifx);
7123
7124                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7125                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7126                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7127                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7128                         genSkipz2(&rIfx,0);
7129                 }
7130         } else {
7131
7132                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7133
7134                         /* They're not both bit variables. Is the right a literal? */
7135                         if(AOP_TYPE(right) == AOP_LIT) {
7136                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7137             
7138                         switch(size) {
7139
7140                                 case 1:
7141                                         switch(lit & 0xff) {
7142                                                 case 1:
7143                                                                 if ( IC_TRUE(ifx) ) {
7144                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7145                                                                         emitSKPNZ;
7146                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7147                                                                 } else {
7148                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7149                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7150                                                                 }
7151                                                                 break;
7152                                                 case 0xff:
7153                                                                 if ( IC_TRUE(ifx) ) {
7154                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7155                                                                         emitSKPNZ;
7156                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7157                                                                 } else {
7158                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7159                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7160                                                                 }
7161                                                                 break;
7162                                                 default:
7163                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7164                                                                 if(lit)
7165                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7166                                                                 genSkip(ifx,'z');
7167                                         } // switch lit
7168
7169
7170                                         /* end of size == 1 */
7171                                         break;
7172               
7173                                 case 2:
7174                                         genc16bit2lit(left,lit,offset);
7175                                         genSkip(ifx,'z');
7176                                         break;
7177                                         /* end of size == 2 */
7178
7179                                 default:
7180                                         /* size is 4 */
7181                                         if(lit==0) {
7182                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7183                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7184                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7185                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7186                                                 genSkip(ifx,'z');
7187                                         } else {
7188                                                 /* search for patterns that can be optimized */
7189
7190                                                 genc16bit2lit(left,lit,0);
7191                                                 lit >>= 16;
7192                                                 if(lit) {
7193                                                                 if(IC_TRUE(ifx))
7194                                                                 emitSKPZ; // if hi word unequal
7195                                                                 else
7196                                                                 emitSKPNZ; // if hi word equal
7197                                                                 // fail early
7198                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7199                                                         genc16bit2lit(left,lit,2);
7200                                                         genSkip(ifx,'z');
7201                                                 } else {
7202                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7203                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7204                                                         genSkip(ifx,'z');
7205                                                 }
7206                                         }
7207                                                 pic16_emitpLabel(falselbl->key);
7208                                                 break;
7209
7210                         } // switch size
7211           
7212                         ifx->generated = 1;
7213                         goto release ;
7214             
7215
7216           } else if(AOP_TYPE(right) == AOP_CRY ) {
7217             /* we know the left is not a bit, but that the right is */
7218             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7219             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7220                       pic16_popGet(AOP(right),offset));
7221             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7222
7223             /* if the two are equal, then W will be 0 and the Z bit is set
7224              * we could test Z now, or go ahead and check the high order bytes if
7225              * the variable we're comparing is larger than a byte. */
7226
7227             while(--size)
7228               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7229
7230             if ( IC_TRUE(ifx) ) {
7231               emitSKPNZ;
7232               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7233               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7234             } else {
7235               emitSKPZ;
7236               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7237               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7238             }
7239
7240           } else {
7241             /* They're both variables that are larger than bits */
7242             int s = size;
7243
7244             tlbl = newiTempLabel(NULL);
7245
7246             while(size--) {
7247               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7248               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7249
7250               if ( IC_TRUE(ifx) ) {
7251                 if(size) {
7252                   emitSKPZ;
7253                 
7254                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7255
7256                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7257                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7258                 } else {
7259                   emitSKPNZ;
7260
7261                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7262
7263
7264                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7265                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7266                 }
7267               } else {
7268                 emitSKPZ;
7269
7270                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7271
7272                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7273                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7274               }
7275               offset++;
7276             }
7277             if(s>1 && IC_TRUE(ifx)) {
7278               pic16_emitpLabel(tlbl->key);
7279               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7280             }
7281           }
7282         }
7283         /* mark the icode as generated */
7284         ifx->generated = 1;
7285         goto release ;
7286     }
7287
7288     /* if they are both bit variables */
7289     if (AOP_TYPE(left) == AOP_CRY &&
7290         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7291         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7292         if(AOP_TYPE(right) == AOP_LIT){
7293             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7294             if(lit == 0L){
7295                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7296                 pic16_emitcode("cpl","c");
7297             } else if(lit == 1L) {
7298                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7299             } else {
7300                 pic16_emitcode("clr","c");
7301             }
7302             /* AOP_TYPE(right) == AOP_CRY */
7303         } else {
7304             symbol *lbl = newiTempLabel(NULL);
7305             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7306             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7307             pic16_emitcode("cpl","c");
7308             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7309         }
7310         /* c = 1 if egal */
7311         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7312             pic16_outBitC(result);
7313             goto release ;
7314         }
7315         if (ifx) {
7316             genIfxJump (ifx,"c");
7317             goto release ;
7318         }
7319         /* if the result is used in an arithmetic operation
7320         then put the result in place */
7321         pic16_outBitC(result);
7322     } else {
7323       
7324       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7325       gencjne(left,right,result,ifx);
7326 /*
7327       if(ifx) 
7328         gencjne(left,right,newiTempLabel(NULL));
7329       else {
7330         if(IC_TRUE(ifx)->key)
7331           gencjne(left,right,IC_TRUE(ifx)->key);
7332         else
7333           gencjne(left,right,IC_FALSE(ifx)->key);
7334         ifx->generated = 1;
7335         goto release ;
7336       }
7337       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7338         pic16_aopPut(AOP(result),"a",0);
7339         goto release ;
7340       }
7341
7342       if (ifx) {
7343         genIfxJump (ifx,"a");
7344         goto release ;
7345       }
7346 */
7347       /* if the result is used in an arithmetic operation
7348          then put the result in place */
7349 /*
7350       if (AOP_TYPE(result) != AOP_CRY) 
7351         pic16_outAcc(result);
7352 */
7353       /* leave the result in acc */
7354     }
7355
7356 release:
7357     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7358     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7359     pic16_freeAsmop(result,NULL,ic,TRUE);
7360 }
7361 #endif
7362
7363 /*-----------------------------------------------------------------*/
7364 /* ifxForOp - returns the icode containing the ifx for operand     */
7365 /*-----------------------------------------------------------------*/
7366 static iCode *ifxForOp ( operand *op, iCode *ic )
7367 {
7368   FENTRY2;
7369
7370     /* if true symbol then needs to be assigned */
7371     if (IS_TRUE_SYMOP(op))
7372         return NULL ;
7373
7374     /* if this has register type condition and
7375     the next instruction is ifx with the same operand
7376     and live to of the operand is upto the ifx only then */
7377     if (ic->next
7378         && ic->next->op == IFX
7379         && IC_COND(ic->next)->key == op->key
7380         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7381         ) {
7382                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7383           return ic->next;
7384     }
7385
7386     /*
7387     if (ic->next &&
7388         ic->next->op == IFX &&
7389         IC_COND(ic->next)->key == op->key) {
7390       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7391       return ic->next;
7392     }
7393     */
7394
7395     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7396     if (ic->next &&
7397         ic->next->op == IFX)
7398       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7399
7400     if (ic->next &&
7401         ic->next->op == IFX &&
7402         IC_COND(ic->next)->key == op->key) {
7403       DEBUGpic16_emitcode ("; "," key is okay");
7404       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7405                            OP_SYMBOL(op)->liveTo,
7406                            ic->next->seq);
7407     }
7408
7409 #if 0
7410     /* the code below is completely untested
7411      * it just allows ulong2fs.c compile -- VR */
7412          
7413     ic = ic->next;
7414     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7415                                         __FILE__, __FUNCTION__, __LINE__);
7416         
7417     /* if this has register type condition and
7418     the next instruction is ifx with the same operand
7419     and live to of the operand is upto the ifx only then */
7420     if (ic->next &&
7421         ic->next->op == IFX &&
7422         IC_COND(ic->next)->key == op->key &&
7423         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7424         return ic->next;
7425
7426     if (ic->next &&
7427         ic->next->op == IFX &&
7428         IC_COND(ic->next)->key == op->key) {
7429       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7430       return ic->next;
7431     }
7432
7433     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7434                                         __FILE__, __FUNCTION__, __LINE__);
7435
7436 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7437 #endif
7438
7439     return NULL;
7440 }
7441 /*-----------------------------------------------------------------*/
7442 /* genAndOp - for && operation                                     */
7443 /*-----------------------------------------------------------------*/
7444 static void genAndOp (iCode *ic)
7445 {
7446   operand *left,*right, *result;
7447 /*     symbol *tlbl; */
7448
7449     FENTRY;
7450
7451     /* note here that && operations that are in an
7452     if statement are taken away by backPatchLabels
7453     only those used in arthmetic operations remain */
7454     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7455     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7456     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7457
7458     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7459
7460     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7461     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7462     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7463
7464     /* if both are bit variables */
7465 /*     if (AOP_TYPE(left) == AOP_CRY && */
7466 /*         AOP_TYPE(right) == AOP_CRY ) { */
7467 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7468 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7469 /*         pic16_outBitC(result); */
7470 /*     } else { */
7471 /*         tlbl = newiTempLabel(NULL); */
7472 /*         pic16_toBoolean(left);     */
7473 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7474 /*         pic16_toBoolean(right); */
7475 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7476 /*         pic16_outBitAcc(result); */
7477 /*     } */
7478
7479     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7480     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7481     pic16_freeAsmop(result,NULL,ic,TRUE);
7482 }
7483
7484
7485 /*-----------------------------------------------------------------*/
7486 /* genOrOp - for || operation                                      */
7487 /*-----------------------------------------------------------------*/
7488 /*
7489   tsd pic port -
7490   modified this code, but it doesn't appear to ever get called
7491 */
7492
7493 static void genOrOp (iCode *ic)
7494 {
7495   operand *left,*right, *result;
7496   symbol *tlbl;
7497
7498     FENTRY;  
7499
7500   /* note here that || operations that are in an
7501     if statement are taken away by backPatchLabels
7502     only those used in arthmetic operations remain */
7503     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7504     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7505     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7506
7507     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7508
7509     /* if both are bit variables */
7510     if (AOP_TYPE(left) == AOP_CRY &&
7511         AOP_TYPE(right) == AOP_CRY ) {
7512       pic16_emitcode("clrc","");
7513       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7514                AOP(left)->aopu.aop_dir,
7515                AOP(left)->aopu.aop_dir);
7516       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7517                AOP(right)->aopu.aop_dir,
7518                AOP(right)->aopu.aop_dir);
7519       pic16_emitcode("setc","");
7520
7521     } else {
7522         tlbl = newiTempLabel(NULL);
7523         pic16_toBoolean(left);
7524         emitSKPZ;
7525         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7526         pic16_toBoolean(right);
7527         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7528
7529         pic16_outBitAcc(result);
7530     }
7531
7532     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7533     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7534     pic16_freeAsmop(result,NULL,ic,TRUE);            
7535 }
7536
7537 /*-----------------------------------------------------------------*/
7538 /* isLiteralBit - test if lit == 2^n                               */
7539 /*-----------------------------------------------------------------*/
7540 static int isLiteralBit(unsigned long lit)
7541 {
7542     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7543     0x100L,0x200L,0x400L,0x800L,
7544     0x1000L,0x2000L,0x4000L,0x8000L,
7545     0x10000L,0x20000L,0x40000L,0x80000L,
7546     0x100000L,0x200000L,0x400000L,0x800000L,
7547     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7548     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7549     int idx;
7550     
7551     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7552     for(idx = 0; idx < 32; idx++)
7553         if(lit == pw[idx])
7554             return idx+1;
7555     return 0;
7556 }
7557
7558 /*-----------------------------------------------------------------*/
7559 /* continueIfTrue -                                                */
7560 /*-----------------------------------------------------------------*/
7561 static void continueIfTrue (iCode *ic)
7562 {
7563   FENTRY;
7564   if(IC_TRUE(ic))
7565     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7566   ic->generated = 1;
7567 }
7568
7569 /*-----------------------------------------------------------------*/
7570 /* jmpIfTrue -                                                     */
7571 /*-----------------------------------------------------------------*/
7572 static void jumpIfTrue (iCode *ic)
7573 {
7574   FENTRY;
7575   if(!IC_TRUE(ic))
7576     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7577   ic->generated = 1;
7578 }
7579
7580 /*-----------------------------------------------------------------*/
7581 /* jmpTrueOrFalse -                                                */
7582 /*-----------------------------------------------------------------*/
7583 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7584 {
7585   // ugly but optimized by peephole
7586   FENTRY;
7587   if(IC_TRUE(ic)){
7588     symbol *nlbl = newiTempLabel(NULL);
7589       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7590       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7591       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7592       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7593   } else {
7594     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7595     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7596   }
7597   ic->generated = 1;
7598 }
7599
7600 /*-----------------------------------------------------------------*/
7601 /* genAnd  - code for and                                          */
7602 /*-----------------------------------------------------------------*/
7603 static void genAnd (iCode *ic, iCode *ifx)
7604 {
7605   operand *left, *right, *result;
7606   int size, offset=0;  
7607   unsigned long lit = 0L;
7608   int bytelit = 0;
7609   resolvedIfx rIfx;
7610
7611     FENTRY;
7612     
7613   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7614   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7615   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7616
7617   resolveIfx(&rIfx,ifx);
7618
7619   /* if left is a literal & right is not then exchange them */
7620   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7621       AOP_NEEDSACC(left)) {
7622     operand *tmp = right ;
7623     right = left;
7624     left = tmp;
7625   }
7626
7627   /* if result = right then exchange them */
7628   if(pic16_sameRegs(AOP(result),AOP(right))){
7629     operand *tmp = right ;
7630     right = left;
7631     left = tmp;
7632   }
7633
7634   /* if right is bit then exchange them */
7635   if (AOP_TYPE(right) == AOP_CRY &&
7636       AOP_TYPE(left) != AOP_CRY){
7637     operand *tmp = right ;
7638     right = left;
7639     left = tmp;
7640   }
7641   if(AOP_TYPE(right) == AOP_LIT)
7642     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7643
7644   size = AOP_SIZE(result);
7645
7646   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7647
7648   // if(bit & yy)
7649   // result = bit & yy;
7650   if (AOP_TYPE(left) == AOP_CRY){
7651     // c = bit & literal;
7652     if(AOP_TYPE(right) == AOP_LIT){
7653       if(lit & 1) {
7654         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7655           // no change
7656           goto release;
7657         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7658       } else {
7659         // bit(result) = 0;
7660         if(size && (AOP_TYPE(result) == AOP_CRY)){
7661           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7662           goto release;
7663         }
7664         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7665           jumpIfTrue(ifx);
7666           goto release;
7667         }
7668         pic16_emitcode("clr","c");
7669       }
7670     } else {
7671       if (AOP_TYPE(right) == AOP_CRY){
7672         // c = bit & bit;
7673         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7674         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7675       } else {
7676         // c = bit & val;
7677         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7678         // c = lsb
7679         pic16_emitcode("rrc","a");
7680         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7681       }
7682     }
7683     // bit = c
7684     // val = c
7685     if(size)
7686       pic16_outBitC(result);
7687     // if(bit & ...)
7688     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7689       genIfxJump(ifx, "c");           
7690     goto release ;
7691   }
7692
7693   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7694   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7695   if((AOP_TYPE(right) == AOP_LIT) &&
7696      (AOP_TYPE(result) == AOP_CRY) &&
7697      (AOP_TYPE(left) != AOP_CRY)){
7698     int posbit = isLiteralBit(lit);
7699     /* left &  2^n */
7700     if(posbit){
7701       posbit--;
7702       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7703       // bit = left & 2^n
7704       if(size)
7705         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7706       // if(left &  2^n)
7707       else{
7708         if(ifx){
7709 /*
7710           if(IC_TRUE(ifx)) {
7711             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7712             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7713           } else {
7714             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7715             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7716           }
7717 */
7718         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7719         size = AOP_SIZE(left);
7720
7721         {
7722           int bp = posbit, ofs=0;
7723           
7724             while(bp > 7) {
7725               bp -= 8;
7726               ofs++;
7727             }
7728
7729           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7730                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7731
7732         }
7733 /*
7734           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7735                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7736 */
7737           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7738           
7739           ifx->generated = 1;
7740         }
7741         goto release;
7742       }
7743     } else {
7744       symbol *tlbl = newiTempLabel(NULL);
7745       int sizel = AOP_SIZE(left);
7746
7747       if(size)
7748         emitSETC;
7749
7750       while(sizel--) {
7751         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7752
7753           /* patch provided by Aaron Colwell */
7754           if((posbit = isLiteralBit(bytelit)) != 0) {
7755               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7756                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7757                                                 (posbit-1),0, PO_GPR_REGISTER));
7758
7759               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7760 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7761           } else {
7762               if (bytelit == 0xff) {
7763                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7764                    * a peephole could optimize it out -- VR */
7765                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7766               } else {
7767                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7768                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7769               }
7770
7771               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7772                             pic16_popGetLabel(tlbl->key));
7773           }
7774         
7775 #if 0
7776           /* old code, left here for reference -- VR 09/2004 */
7777           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7778           // byte ==  2^n ?
7779           if((posbit = isLiteralBit(bytelit)) != 0)
7780             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7781           else{
7782             if(bytelit != 0x0FFL)
7783               pic16_emitcode("anl","a,%s",
7784                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7785             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7786           }
7787 #endif
7788         }
7789         offset++;
7790       }
7791       // bit = left & literal
7792       if(size) {
7793         emitCLRC;
7794         pic16_emitpLabel(tlbl->key);
7795       }
7796       // if(left & literal)
7797       else {
7798         if(ifx) {
7799           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7800           ifx->generated = 1;
7801         }
7802         pic16_emitpLabel(tlbl->key);
7803         goto release;
7804       }
7805     }
7806
7807     pic16_outBitC(result);
7808     goto release ;
7809   }
7810
7811   /* if left is same as result */
7812   if(pic16_sameRegs(AOP(result),AOP(left))){
7813     int know_W = -1;
7814     for(;size--; offset++,lit>>=8) {
7815       if(AOP_TYPE(right) == AOP_LIT){
7816         switch(lit & 0xff) {
7817         case 0x00:
7818           /*  and'ing with 0 has clears the result */
7819 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7820           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7821           break;
7822         case 0xff:
7823           /* and'ing with 0xff is a nop when the result and left are the same */
7824           break;
7825
7826         default:
7827           {
7828             int p = pic16_my_powof2( (~lit) & 0xff );
7829             if(p>=0) {
7830               /* only one bit is set in the literal, so use a bcf instruction */
7831 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7832               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7833
7834             } else {
7835               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7836               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7837               if(know_W != (lit&0xff))
7838                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7839               know_W = lit &0xff;
7840               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7841             }
7842           }    
7843         }
7844       } else {
7845         if (AOP_TYPE(left) == AOP_ACC) {
7846           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7847         } else {                    
7848           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7849           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7850
7851         }
7852       }
7853     }
7854
7855   } else {
7856     // left & result in different registers
7857     if(AOP_TYPE(result) == AOP_CRY){
7858       // result = bit
7859       // if(size), result in bit
7860       // if(!size && ifx), conditional oper: if(left & right)
7861       symbol *tlbl = newiTempLabel(NULL);
7862       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7863       if(size)
7864         pic16_emitcode("setb","c");
7865       while(sizer--){
7866         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7867         pic16_emitcode("anl","a,%s",
7868                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7869         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7870         offset++;
7871       }
7872       if(size){
7873         CLRC;
7874         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7875         pic16_outBitC(result);
7876       } else if(ifx)
7877         jmpTrueOrFalse(ifx, tlbl);
7878     } else {
7879       for(;(size--);offset++) {
7880         // normal case
7881         // result = left & right
7882         if(AOP_TYPE(right) == AOP_LIT){
7883           int t = (lit >> (offset*8)) & 0x0FFL;
7884           switch(t) { 
7885           case 0x00:
7886             pic16_emitcode("clrf","%s",
7887                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7888             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7889             break;
7890           case 0xff:
7891             pic16_emitcode("movf","%s,w",
7892                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7893             pic16_emitcode("movwf","%s",
7894                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7895             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7896             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7897             break;
7898           default:
7899             pic16_emitcode("movlw","0x%x",t);
7900             pic16_emitcode("andwf","%s,w",
7901                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7902             pic16_emitcode("movwf","%s",
7903                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7904               
7905             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7906             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7907             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7908           }
7909           continue;
7910         }
7911
7912         if (AOP_TYPE(left) == AOP_ACC) {
7913           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7914           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7915         } else {
7916           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7917           pic16_emitcode("andwf","%s,w",
7918                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7919           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7920           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7921         }
7922         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7923         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7924       }
7925     }
7926   }
7927
7928   release :
7929     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7930   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7931   pic16_freeAsmop(result,NULL,ic,TRUE);     
7932 }
7933
7934 /*-----------------------------------------------------------------*/
7935 /* genOr  - code for or                                            */
7936 /*-----------------------------------------------------------------*/
7937 static void genOr (iCode *ic, iCode *ifx)
7938 {
7939     operand *left, *right, *result;
7940     int size, offset=0;
7941     unsigned long lit = 0L;
7942
7943     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7944     FENTRY;
7945
7946     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7947     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7948     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7949
7950     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7951
7952     /* if left is a literal & right is not then exchange them */
7953     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7954         AOP_NEEDSACC(left)) {
7955         operand *tmp = right ;
7956         right = left;
7957         left = tmp;
7958     }
7959
7960     /* if result = right then exchange them */
7961     if(pic16_sameRegs(AOP(result),AOP(right))){
7962         operand *tmp = right ;
7963         right = left;
7964         left = tmp;
7965     }
7966
7967     /* if right is bit then exchange them */
7968     if (AOP_TYPE(right) == AOP_CRY &&
7969         AOP_TYPE(left) != AOP_CRY){
7970         operand *tmp = right ;
7971         right = left;
7972         left = tmp;
7973     }
7974
7975     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7976
7977     if(AOP_TYPE(right) == AOP_LIT)
7978         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7979
7980     size = AOP_SIZE(result);
7981
7982     // if(bit | yy)
7983     // xx = bit | yy;
7984     if (AOP_TYPE(left) == AOP_CRY){
7985         if(AOP_TYPE(right) == AOP_LIT){
7986             // c = bit & literal;
7987             if(lit){
7988                 // lit != 0 => result = 1
7989                 if(AOP_TYPE(result) == AOP_CRY){
7990                   if(size)
7991                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7992                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7993                   //     AOP(result)->aopu.aop_dir,
7994                   //     AOP(result)->aopu.aop_dir);
7995                     else if(ifx)
7996                         continueIfTrue(ifx);
7997                     goto release;
7998                 }
7999             } else {
8000                 // lit == 0 => result = left
8001                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8002                     goto release;
8003                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8004             }
8005         } else {
8006             if (AOP_TYPE(right) == AOP_CRY){
8007               if(pic16_sameRegs(AOP(result),AOP(left))){
8008                 // c = bit | bit;
8009                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8010                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8011                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8012
8013                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8014                          AOP(result)->aopu.aop_dir,
8015                          AOP(result)->aopu.aop_dir);
8016                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8017                          AOP(right)->aopu.aop_dir,
8018                          AOP(right)->aopu.aop_dir);
8019                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8020                          AOP(result)->aopu.aop_dir,
8021                          AOP(result)->aopu.aop_dir);
8022               } else {
8023                 if( AOP_TYPE(result) == AOP_ACC) {
8024                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8025                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8026                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8027                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8028
8029                 } else {
8030
8031                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8032                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8033                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8034                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8035
8036                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8037                                  AOP(result)->aopu.aop_dir,
8038                                  AOP(result)->aopu.aop_dir);
8039                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8040                                  AOP(right)->aopu.aop_dir,
8041                                  AOP(right)->aopu.aop_dir);
8042                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8043                                  AOP(left)->aopu.aop_dir,
8044                                  AOP(left)->aopu.aop_dir);
8045                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8046                                  AOP(result)->aopu.aop_dir,
8047                                  AOP(result)->aopu.aop_dir);
8048                 }
8049               }
8050             } else {
8051                 // c = bit | val;
8052                 symbol *tlbl = newiTempLabel(NULL);
8053                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8054
8055
8056                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8057                 if( AOP_TYPE(right) == AOP_ACC) {
8058                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8059                   emitSKPNZ;
8060                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8061                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8062                 }
8063
8064
8065
8066                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8067                     pic16_emitcode(";XXX setb","c");
8068                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8069                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8070                 pic16_toBoolean(right);
8071                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8072                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8073                     jmpTrueOrFalse(ifx, tlbl);
8074                     goto release;
8075                 } else {
8076                     CLRC;
8077                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8078                 }
8079             }
8080         }
8081         // bit = c
8082         // val = c
8083         if(size)
8084             pic16_outBitC(result);
8085         // if(bit | ...)
8086         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8087             genIfxJump(ifx, "c");           
8088         goto release ;
8089     }
8090
8091     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8092     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8093     if((AOP_TYPE(right) == AOP_LIT) &&
8094        (AOP_TYPE(result) == AOP_CRY) &&
8095        (AOP_TYPE(left) != AOP_CRY)){
8096         if(lit){
8097           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8098             // result = 1
8099             if(size)
8100                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8101             else 
8102                 continueIfTrue(ifx);
8103             goto release;
8104         } else {
8105           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8106             // lit = 0, result = boolean(left)
8107             if(size)
8108                 pic16_emitcode(";XXX setb","c");
8109             pic16_toBoolean(right);
8110             if(size){
8111                 symbol *tlbl = newiTempLabel(NULL);
8112                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8113                 CLRC;
8114                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8115             } else {
8116                 genIfxJump (ifx,"a");
8117                 goto release;
8118             }
8119         }
8120         pic16_outBitC(result);
8121         goto release ;
8122     }
8123
8124     /* if left is same as result */
8125     if(pic16_sameRegs(AOP(result),AOP(left))){
8126       int know_W = -1;
8127       for(;size--; offset++,lit>>=8) {
8128         if(AOP_TYPE(right) == AOP_LIT){
8129           if((lit & 0xff) == 0)
8130             /*  or'ing with 0 has no effect */
8131             continue;
8132           else {
8133             int p = pic16_my_powof2(lit & 0xff);
8134             if(p>=0) {
8135               /* only one bit is set in the literal, so use a bsf instruction */
8136               pic16_emitpcode(POC_BSF,
8137                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8138             } else {
8139               if(know_W != (lit & 0xff))
8140                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8141               know_W = lit & 0xff;
8142               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8143             }
8144                     
8145           }
8146         } else {
8147           if (AOP_TYPE(left) == AOP_ACC) {
8148             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8149 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8150           } else {                  
8151             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8152             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8153
8154 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8155 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8156
8157           }
8158         }
8159       }
8160     } else {
8161         // left & result in different registers
8162         if(AOP_TYPE(result) == AOP_CRY){
8163             // result = bit
8164             // if(size), result in bit
8165             // if(!size && ifx), conditional oper: if(left | right)
8166             symbol *tlbl = newiTempLabel(NULL);
8167             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8168             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8169
8170
8171             if(size)
8172                 pic16_emitcode(";XXX setb","c");
8173             while(sizer--){
8174                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8175                 pic16_emitcode(";XXX orl","a,%s",
8176                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8177                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8178                 offset++;
8179             }
8180             if(size){
8181                 CLRC;
8182                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8183                 pic16_outBitC(result);
8184             } else if(ifx)
8185                 jmpTrueOrFalse(ifx, tlbl);
8186         } else for(;(size--);offset++){
8187           // normal case
8188           // result = left & right
8189           if(AOP_TYPE(right) == AOP_LIT){
8190             int t = (lit >> (offset*8)) & 0x0FFL;
8191             switch(t) { 
8192             case 0x00:
8193               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8194               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8195
8196 //            pic16_emitcode("movf","%s,w",
8197 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8198 //            pic16_emitcode("movwf","%s",
8199 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8200               break;
8201             default:
8202               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8203               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8204               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8205
8206 //            pic16_emitcode("movlw","0x%x",t);
8207 //            pic16_emitcode("iorwf","%s,w",
8208 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8209 //            pic16_emitcode("movwf","%s",
8210 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8211               
8212             }
8213             continue;
8214           }
8215
8216           // faster than result <- left, anl result,right
8217           // and better if result is SFR
8218           if (AOP_TYPE(left) == AOP_ACC) {
8219             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8220 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8221           } else {
8222             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8223             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8224
8225 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8226 //          pic16_emitcode("iorwf","%s,w",
8227 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8228           }
8229           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8230 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8231         }
8232     }
8233
8234 release :
8235     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8236     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8237     pic16_freeAsmop(result,NULL,ic,TRUE);     
8238 }
8239
8240 /*-----------------------------------------------------------------*/
8241 /* genXor - code for xclusive or                                   */
8242 /*-----------------------------------------------------------------*/
8243 static void genXor (iCode *ic, iCode *ifx)
8244 {
8245   operand *left, *right, *result;
8246   int size, offset=0;
8247   unsigned long lit = 0L;
8248
8249   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8250   FENTRY;
8251
8252   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8253   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8254   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8255
8256   /* if left is a literal & right is not ||
8257      if left needs acc & right does not */
8258   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8259       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8260     operand *tmp = right ;
8261     right = left;
8262     left = tmp;
8263   }
8264
8265   /* if result = right then exchange them */
8266   if(pic16_sameRegs(AOP(result),AOP(right))){
8267     operand *tmp = right ;
8268     right = left;
8269     left = tmp;
8270   }
8271
8272   /* if right is bit then exchange them */
8273   if (AOP_TYPE(right) == AOP_CRY &&
8274       AOP_TYPE(left) != AOP_CRY){
8275     operand *tmp = right ;
8276     right = left;
8277     left = tmp;
8278   }
8279   if(AOP_TYPE(right) == AOP_LIT)
8280     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8281
8282   size = AOP_SIZE(result);
8283
8284   // if(bit ^ yy)
8285   // xx = bit ^ yy;
8286   if (AOP_TYPE(left) == AOP_CRY){
8287     if(AOP_TYPE(right) == AOP_LIT){
8288       // c = bit & literal;
8289       if(lit>>1){
8290         // lit>>1  != 0 => result = 1
8291         if(AOP_TYPE(result) == AOP_CRY){
8292           if(size)
8293             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8294             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8295           else if(ifx)
8296             continueIfTrue(ifx);
8297           goto release;
8298         }
8299         pic16_emitcode("setb","c");
8300       } else{
8301         // lit == (0 or 1)
8302         if(lit == 0){
8303           // lit == 0, result = left
8304           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8305             goto release;
8306           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8307         } else{
8308           // lit == 1, result = not(left)
8309           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8310             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8311             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8312             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8313             goto release;
8314           } else {
8315             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8316             pic16_emitcode("cpl","c");
8317           }
8318         }
8319       }
8320
8321     } else {
8322       // right != literal
8323       symbol *tlbl = newiTempLabel(NULL);
8324       if (AOP_TYPE(right) == AOP_CRY){
8325         // c = bit ^ bit;
8326         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8327       }
8328       else{
8329         int sizer = AOP_SIZE(right);
8330         // c = bit ^ val
8331         // if val>>1 != 0, result = 1
8332         pic16_emitcode("setb","c");
8333         while(sizer){
8334           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8335           if(sizer == 1)
8336             // test the msb of the lsb
8337             pic16_emitcode("anl","a,#0xfe");
8338           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8339           sizer--;
8340         }
8341         // val = (0,1)
8342         pic16_emitcode("rrc","a");
8343       }
8344       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8345       pic16_emitcode("cpl","c");
8346       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8347     }
8348     // bit = c
8349     // val = c
8350     if(size)
8351       pic16_outBitC(result);
8352     // if(bit | ...)
8353     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8354       genIfxJump(ifx, "c");           
8355     goto release ;
8356   }
8357
8358   if(pic16_sameRegs(AOP(result),AOP(left))){
8359     /* if left is same as result */
8360     for(;size--; offset++) {
8361       if(AOP_TYPE(right) == AOP_LIT){
8362         int t  = (lit >> (offset*8)) & 0x0FFL;
8363         if(t == 0x00L)
8364           continue;
8365         else
8366           if (IS_AOP_PREG(left)) {
8367             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8368             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8369             pic16_aopPut(AOP(result),"a",offset);
8370           } else {
8371             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8372             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8373             pic16_emitcode("xrl","%s,%s",
8374                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8375                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8376           }
8377       } else {
8378         if (AOP_TYPE(left) == AOP_ACC)
8379           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8380         else {
8381           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8382           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8383 /*
8384           if (IS_AOP_PREG(left)) {
8385             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8386             pic16_aopPut(AOP(result),"a",offset);
8387           } else
8388             pic16_emitcode("xrl","%s,a",
8389                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8390 */
8391         }
8392       }
8393     }
8394   } else {
8395     // left & result in different registers
8396     if(AOP_TYPE(result) == AOP_CRY){
8397       // result = bit
8398       // if(size), result in bit
8399       // if(!size && ifx), conditional oper: if(left ^ right)
8400       symbol *tlbl = newiTempLabel(NULL);
8401       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8402       if(size)
8403         pic16_emitcode("setb","c");
8404       while(sizer--){
8405         if((AOP_TYPE(right) == AOP_LIT) &&
8406            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8407           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8408         } else {
8409           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8410           pic16_emitcode("xrl","a,%s",
8411                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8412         }
8413         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8414         offset++;
8415       }
8416       if(size){
8417         CLRC;
8418         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8419         pic16_outBitC(result);
8420       } else if(ifx)
8421         jmpTrueOrFalse(ifx, tlbl);
8422     } else for(;(size--);offset++){
8423       // normal case
8424       // result = left & right
8425       if(AOP_TYPE(right) == AOP_LIT){
8426         int t = (lit >> (offset*8)) & 0x0FFL;
8427         switch(t) { 
8428         case 0x00:
8429           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8430           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8431           pic16_emitcode("movf","%s,w",
8432                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8433           pic16_emitcode("movwf","%s",
8434                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8435           break;
8436         case 0xff:
8437           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8438           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8439           pic16_emitcode("comf","%s,w",
8440                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8441           pic16_emitcode("movwf","%s",
8442                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8443           break;
8444         default:
8445           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8446           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8447           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8448           pic16_emitcode("movlw","0x%x",t);
8449           pic16_emitcode("xorwf","%s,w",
8450                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8451           pic16_emitcode("movwf","%s",
8452                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8453
8454         }
8455         continue;
8456       }
8457
8458       // faster than result <- left, anl result,right
8459       // and better if result is SFR
8460       if (AOP_TYPE(left) == AOP_ACC) {
8461         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8462         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8463       } else {
8464         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8465         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8466         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8467         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8468       }
8469       if ( AOP_TYPE(result) != AOP_ACC){
8470         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8471         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8472       }
8473     }
8474   }
8475
8476   release :
8477     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8478   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8479   pic16_freeAsmop(result,NULL,ic,TRUE);     
8480 }
8481
8482 /*-----------------------------------------------------------------*/
8483 /* genInline - write the inline code out                           */
8484 /*-----------------------------------------------------------------*/
8485 static void genInline (iCode *ic)
8486 {
8487   char *buffer, *bp, *bp1;
8488     
8489         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8490
8491         _G.inLine += (!options.asmpeep);
8492
8493         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8494         strcpy(buffer,IC_INLINE(ic));
8495         
8496         while((bp1=strstr(bp, "\\n"))) {
8497           *bp1++ = '\n';
8498           *bp1++ = ' ';
8499           bp = bp1;
8500         }
8501         bp = bp1 = buffer;
8502
8503 #if 0
8504   /* This is an experimental code for #pragma inline
8505      and is temporarily disabled for 2.5.0 release */
8506         if(asmInlineMap)
8507         {
8508           symbol *sym;
8509           char *s;
8510           char *cbuf;
8511           int cblen;
8512
8513             cbuf = Safe_strdup(buffer);
8514             cblen = strlen(buffer)+1;
8515             memset(cbuf, 0, cblen);
8516
8517             bp = buffer;
8518             bp1 = cbuf;
8519             while(*bp) {
8520               if(*bp != '%')*bp1++ = *bp++;
8521               else {
8522                 int i;
8523
8524                   bp++;
8525                   i = *bp - '0';
8526                   if(i>elementsInSet(asmInlineMap))break;
8527                   
8528                   bp++;
8529                   s = indexSet(asmInlineMap, i);
8530                   DEBUGpc("searching symbol s = `%s'", s);
8531                   sym = findSym(SymbolTab, NULL, s);
8532
8533                   if(sym->reqv) {
8534                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8535                   } else {
8536                     strcat(bp1, sym->rname);
8537                   }
8538                   
8539                   while(*bp1)bp1++;
8540               }
8541               
8542               if(strlen(bp1) > cblen - 16) {
8543                 int i = strlen(cbuf);
8544                 cblen += 50;
8545                 cbuf = realloc(cbuf, cblen);
8546                 memset(cbuf+i, 0, 50);
8547                 bp1 = cbuf + i;
8548               }
8549             }
8550             
8551             free(buffer);
8552             buffer = Safe_strdup( cbuf );
8553             free(cbuf);
8554             
8555             bp = bp1 = buffer;
8556         }
8557 #endif  /* 0 */
8558
8559         /* emit each line as a code */
8560         while (*bp) {
8561                 if (*bp == '\n') {
8562                         *bp++ = '\0';
8563
8564                         if(*bp1)
8565                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8566                         bp1 = bp;
8567                 } else {
8568                         if (*bp == ':') {
8569                                 bp++;
8570                                 *bp = '\0';
8571                                 bp++;
8572
8573                                 /* print label, use this special format with NULL directive
8574                                  * to denote that the argument should not be indented with tab */
8575                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8576                                 bp1 = bp;
8577                         } if (*bp == ';') {
8578                                 /* advance to end of line (prevent splitting of comments at ':' */
8579                                 while (*bp && *bp != '\n') {
8580                                         bp++;
8581                                 } // while
8582                         } else
8583                                 bp++;
8584                 }
8585         }
8586
8587         if ((bp1 != bp) && *bp1)
8588                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8589
8590
8591     Safe_free(buffer);
8592
8593     _G.inLine -= (!options.asmpeep);
8594 }
8595
8596 /*-----------------------------------------------------------------*/
8597 /* genRRC - rotate right with carry                                */
8598 /*-----------------------------------------------------------------*/
8599 static void genRRC (iCode *ic)
8600 {
8601   operand *left , *result ;
8602   int size, offset = 0, same;
8603
8604   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8605
8606   /* rotate right with carry */
8607   left = IC_LEFT(ic);
8608   result=IC_RESULT(ic);
8609   pic16_aopOp (left,ic,FALSE);
8610   pic16_aopOp (result,ic,TRUE);
8611
8612   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8613
8614   same = pic16_sameRegs(AOP(result),AOP(left));
8615
8616   size = AOP_SIZE(result);    
8617
8618   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8619
8620   /* get the lsb and put it into the carry */
8621   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8622
8623   offset = 0 ;
8624
8625   while(size--) {
8626
8627     if(same) {
8628       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8629     } else {
8630       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8631       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8632     }
8633
8634     offset++;
8635   }
8636
8637   pic16_freeAsmop(left,NULL,ic,TRUE);
8638   pic16_freeAsmop(result,NULL,ic,TRUE);
8639 }
8640
8641 /*-----------------------------------------------------------------*/
8642 /* genRLC - generate code for rotate left with carry               */
8643 /*-----------------------------------------------------------------*/
8644 static void genRLC (iCode *ic)
8645 {    
8646   operand *left , *result ;
8647   int size, offset = 0;
8648   int same;
8649
8650   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8651   /* rotate right with carry */
8652   left = IC_LEFT(ic);
8653   result=IC_RESULT(ic);
8654   pic16_aopOp (left,ic,FALSE);
8655   pic16_aopOp (result,ic,TRUE);
8656
8657   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8658
8659   same = pic16_sameRegs(AOP(result),AOP(left));
8660
8661   /* move it to the result */
8662   size = AOP_SIZE(result);    
8663
8664   /* get the msb and put it into the carry */
8665   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8666
8667   offset = 0 ;
8668
8669   while(size--) {
8670
8671     if(same) {
8672       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8673     } else {
8674       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8675       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8676     }
8677
8678     offset++;
8679   }
8680
8681
8682   pic16_freeAsmop(left,NULL,ic,TRUE);
8683   pic16_freeAsmop(result,NULL,ic,TRUE);
8684 }
8685
8686
8687 /* gpasm can get the highest order bit with HIGH/UPPER
8688  * so the following probably is not needed -- VR */
8689  
8690 /*-----------------------------------------------------------------*/
8691 /* genGetHbit - generates code get highest order bit               */
8692 /*-----------------------------------------------------------------*/
8693 static void genGetHbit (iCode *ic)
8694 {
8695     operand *left, *result;
8696     left = IC_LEFT(ic);
8697     result=IC_RESULT(ic);
8698     pic16_aopOp (left,ic,FALSE);
8699     pic16_aopOp (result,ic,FALSE);
8700
8701     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8702     /* get the highest order byte into a */
8703     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8704     if(AOP_TYPE(result) == AOP_CRY){
8705         pic16_emitcode("rlc","a");
8706         pic16_outBitC(result);
8707     }
8708     else{
8709         pic16_emitcode("rl","a");
8710         pic16_emitcode("anl","a,#0x01");
8711         pic16_outAcc(result);
8712     }
8713
8714
8715     pic16_freeAsmop(left,NULL,ic,TRUE);
8716     pic16_freeAsmop(result,NULL,ic,TRUE);
8717 }
8718
8719 #if 0
8720 /*-----------------------------------------------------------------*/
8721 /* AccRol - rotate left accumulator by known count                 */
8722 /*-----------------------------------------------------------------*/
8723 static void AccRol (int shCount)
8724 {
8725     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8726     shCount &= 0x0007;              // shCount : 0..7
8727     switch(shCount){
8728         case 0 :
8729             break;
8730         case 1 :
8731             pic16_emitcode("rl","a");
8732             break;
8733         case 2 :
8734             pic16_emitcode("rl","a");
8735             pic16_emitcode("rl","a");
8736             break;
8737         case 3 :
8738             pic16_emitcode("swap","a");
8739             pic16_emitcode("rr","a");
8740             break;
8741         case 4 :
8742             pic16_emitcode("swap","a");
8743             break;
8744         case 5 :
8745             pic16_emitcode("swap","a");
8746             pic16_emitcode("rl","a");
8747             break;
8748         case 6 :
8749             pic16_emitcode("rr","a");
8750             pic16_emitcode("rr","a");
8751             break;
8752         case 7 :
8753             pic16_emitcode("rr","a");
8754             break;
8755     }
8756 }
8757 #endif
8758
8759 /*-----------------------------------------------------------------*/
8760 /* AccLsh - left shift accumulator by known count                  */
8761 /*-----------------------------------------------------------------*/
8762 static void AccLsh (int shCount, int doMask)
8763 {
8764         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8765         switch(shCount){
8766                 case 0 :
8767                         return;
8768                         break;
8769                 case 1 :
8770                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8771                         break;
8772                 case 2 :
8773                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8774                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8775                         break;
8776                 case 3 :
8777                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8778                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8779                         break;
8780                 case 4 :
8781                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8782                         break;
8783                 case 5 :
8784                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8785                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8786                         break;
8787                 case 6 :
8788                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8789                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8790                         break;
8791                 case 7 :
8792                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8793                         break;
8794         }
8795         if (doMask) {
8796                 /* no masking is required in genPackBits */
8797                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8798         }
8799 }
8800
8801 /*-----------------------------------------------------------------*/
8802 /* AccRsh - right shift accumulator by known count                 */
8803 /*-----------------------------------------------------------------*/
8804 static void AccRsh (int shCount, int andmask)
8805 {
8806         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8807         switch(shCount){
8808                 case 0 :
8809                         return; break;
8810                 case 1 :
8811                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8812                         break;
8813                 case 2 :
8814                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8815                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8816                         break;
8817                 case 3 :
8818                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8819                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8820                         break;
8821                 case 4 :
8822                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8823                         break;
8824                 case 5 :
8825                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8826                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8827                         break;
8828                 case 6 :
8829                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8830                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8831                         break;
8832                 case 7 :
8833                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8834                         break;
8835         }
8836         
8837         if(andmask)
8838                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8839         else
8840                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8841 }
8842
8843 #if 0
8844 /*-----------------------------------------------------------------*/
8845 /* AccSRsh - signed right shift accumulator by known count                 */
8846 /*-----------------------------------------------------------------*/
8847 static void AccSRsh (int shCount)
8848 {
8849     symbol *tlbl ;
8850     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8851     if(shCount != 0){
8852         if(shCount == 1){
8853             pic16_emitcode("mov","c,acc.7");
8854             pic16_emitcode("rrc","a");
8855         } else if(shCount == 2){
8856             pic16_emitcode("mov","c,acc.7");
8857             pic16_emitcode("rrc","a");
8858             pic16_emitcode("mov","c,acc.7");
8859             pic16_emitcode("rrc","a");
8860         } else {
8861             tlbl = newiTempLabel(NULL);
8862             /* rotate right accumulator */
8863             AccRol(8 - shCount);
8864             /* and kill the higher order bits */
8865             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8866             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8867             pic16_emitcode("orl","a,#0x%02x",
8868                      (unsigned char)~SRMask[shCount]);
8869             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8870         }
8871     }
8872 }
8873 #endif
8874
8875 /*-----------------------------------------------------------------*/
8876 /* shiftR1Left2Result - shift right one byte from left to result   */
8877 /*-----------------------------------------------------------------*/
8878 static void shiftR1Left2ResultSigned (operand *left, int offl,
8879                                 operand *result, int offr,
8880                                 int shCount)
8881 {
8882   int same;
8883
8884   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8885
8886   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8887
8888   switch(shCount) {
8889   case 1:
8890     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8891     if(same) 
8892       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8893     else {
8894       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8895       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8896     }
8897
8898     break;
8899   case 2:
8900
8901     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8902     if(same) 
8903       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8904     else {
8905       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8906       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8907     }
8908     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8909     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8910
8911     break;
8912
8913   case 3:
8914     if(same)
8915       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8916     else {
8917       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8918       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8919     }
8920
8921     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8922     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8923     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8924
8925     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8926     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8927
8928     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8929     break;
8930
8931   case 4:
8932     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8933     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8934     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8935     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8936     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8937     break;
8938   case 5:
8939     if(same) {
8940       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8941     } else {
8942       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8943       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8944     }
8945     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8946     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8947     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8948     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8949     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8950     break;
8951
8952   case 6:
8953     if(same) {
8954       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8955       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8956       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8957       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8958       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8959       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8960     } else {
8961       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8962       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8963       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8964       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8965       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8966     }
8967     break;
8968
8969   case 7:
8970     if(same) {
8971       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8972       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8973       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8974       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8975     } else {
8976       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8977       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8978       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8979     }
8980
8981   default:
8982     break;
8983   }
8984 }
8985
8986 /*-----------------------------------------------------------------*/
8987 /* shiftR1Left2Result - shift right one byte from left to result   */
8988 /*-----------------------------------------------------------------*/
8989 static void shiftR1Left2Result (operand *left, int offl,
8990                                 operand *result, int offr,
8991                                 int shCount, int sign)
8992 {
8993   int same;
8994
8995   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8996
8997   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8998
8999   /* Copy the msb into the carry if signed. */
9000   if(sign) {
9001     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9002     return;
9003   }
9004
9005
9006
9007   switch(shCount) {
9008   case 1:
9009     emitCLRC;
9010     if(same) 
9011       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9012     else {
9013       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9014       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9015     }
9016     break;
9017   case 2:
9018     emitCLRC;
9019     if(same) {
9020       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9021     } else {
9022       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9023       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9024     }
9025     emitCLRC;
9026     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9027
9028     break;
9029   case 3:
9030     if(same)
9031       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9032     else {
9033       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9034       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9035     }
9036
9037     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9038     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9039     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9040     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9041     break;
9042       
9043   case 4:
9044     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9045     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9046     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9047     break;
9048
9049   case 5:
9050     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9051     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9052     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9053     //emitCLRC;
9054     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9055
9056     break;
9057   case 6:
9058
9059     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9060     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9061     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9062     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9063     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9064     break;
9065
9066   case 7:
9067
9068     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9069     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9070     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9071
9072     break;
9073
9074   default:
9075     break;
9076   }
9077 }
9078
9079 /*-----------------------------------------------------------------*/
9080 /* shiftL1Left2Result - shift left one byte from left to result    */
9081 /*-----------------------------------------------------------------*/
9082 static void shiftL1Left2Result (operand *left, int offl,
9083                                 operand *result, int offr, int shCount)
9084 {
9085   int same;
9086
9087   //    char *l;
9088   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9089
9090   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9091   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9092     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9093     //    MOVA(l);
9094     /* shift left accumulator */
9095     //AccLsh(shCount, 1); // don't comment out just yet...
9096   //    pic16_aopPut(AOP(result),"a",offr);
9097
9098   switch(shCount) {
9099   case 1:
9100     /* Shift left 1 bit position */
9101     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9102     if(same) {
9103       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9104     } else {
9105       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9106       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9107     }
9108     break;
9109   case 2:
9110     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9111     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9112     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9113     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9114     break;
9115   case 3:
9116     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9117     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9118     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9119     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9120     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9121     break;
9122   case 4:
9123     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9124     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9125     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9126     break;
9127   case 5:
9128     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9129     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9130     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9131     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9132     break;
9133   case 6:
9134     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9135     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9136     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9137     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9138     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9139     break;
9140   case 7:
9141     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9142     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9143     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9144     break;
9145
9146   default:
9147     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9148   }
9149
9150 }
9151
9152 /*-----------------------------------------------------------------*/
9153 /* movLeft2Result - move byte from left to result                  */
9154 /*-----------------------------------------------------------------*/
9155 static void movLeft2Result (operand *left, int offl,
9156                             operand *result, int offr)
9157 {
9158   char *l;
9159   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9160   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9161     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9162
9163     if (*l == '@' && (IS_AOP_PREG(result))) {
9164       pic16_emitcode("mov","a,%s",l);
9165       pic16_aopPut(AOP(result),"a",offr);
9166     } else {
9167       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9168       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9169     }
9170   }
9171 }
9172
9173 /*-----------------------------------------------------------------*/
9174 /* shiftL2Left2Result - shift left two bytes from left to result   */
9175 /*-----------------------------------------------------------------*/
9176 static void shiftL2Left2Result (operand *left, int offl,
9177                                 operand *result, int offr, int shCount)
9178 {
9179   int same = pic16_sameRegs(AOP(result), AOP(left));
9180   int i;
9181
9182   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9183
9184   if (same && (offl != offr)) { // shift bytes
9185     if (offr > offl) {
9186        for(i=1;i>-1;i--) {
9187          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9188          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9189        }
9190     } else { // just treat as different later on
9191                 same = 0;
9192     }
9193   }
9194
9195   if(same) {
9196     switch(shCount) {
9197     case 0:
9198       break;
9199     case 1:
9200     case 2:
9201     case 3:
9202
9203       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9204       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9205       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9206
9207       while(--shCount) {
9208                 emitCLRC;
9209                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9210                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9211       }
9212
9213       break;
9214     case 4:
9215     case 5:
9216       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9217       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9218       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9219       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9220       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9221       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9222       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9223       if(shCount >=5) {
9224                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9225                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9226       }
9227       break;
9228     case 6:
9229       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9230       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9231       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9232       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9233       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9234       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9235       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9236       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9237       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9238       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9239       break;
9240     case 7:
9241       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9242       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9243       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9244       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9245       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9246     }
9247
9248   } else {
9249     switch(shCount) {
9250     case 0:
9251       break;
9252     case 1:
9253     case 2:
9254     case 3:
9255       /* note, use a mov/add for the shift since the mov has a
9256          chance of getting optimized out */
9257       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9258       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9259       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9260       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9261       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9262
9263       while(--shCount) {
9264                 emitCLRC;
9265                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9266                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9267       }
9268       break;
9269
9270     case 4:
9271     case 5:
9272       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9273       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9274       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9275       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9276       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9277       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9278       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9279       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9280
9281
9282       if(shCount == 5) {
9283                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9284                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9285       }
9286       break;
9287     case 6:
9288       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9289       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9290       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9291       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9292
9293       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9294       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9295       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9296       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9297       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9298       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9299       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9300       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9301       break;
9302     case 7:
9303       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9304       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9305       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9306       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9307       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9308     }
9309   }
9310
9311 }
9312 /*-----------------------------------------------------------------*/
9313 /* shiftR2Left2Result - shift right two bytes from left to result  */
9314 /*-----------------------------------------------------------------*/
9315 static void shiftR2Left2Result (operand *left, int offl,
9316                                 operand *result, int offr,
9317                                 int shCount, int sign)
9318 {
9319   int same = pic16_sameRegs(AOP(result), AOP(left));
9320   int i;
9321   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9322
9323   if (same && (offl != offr)) { // shift right bytes
9324     if (offr < offl) {
9325        for(i=0;i<2;i++) {
9326          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9327          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9328        }
9329     } else { // just treat as different later on
9330                 same = 0;
9331     }
9332   }
9333
9334   switch(shCount) {
9335   case 0:
9336     break;
9337   case 1:
9338   case 2:
9339   case 3:
9340     /* obtain sign from left operand */
9341     if(sign)
9342       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9343     else
9344       emitCLRC;
9345
9346     if(same) {
9347       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9348       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9349     } else {
9350       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9351       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9352       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9353       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9354     }
9355
9356     while(--shCount) {
9357       if(sign)
9358         /* now get sign from already assigned result (avoid BANKSEL) */
9359         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9360       else
9361         emitCLRC;
9362       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9363       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9364     }
9365     break;
9366   case 4:
9367   case 5:
9368     if(same) {
9369
9370       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9371       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9372       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9373
9374       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9375       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9376       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9377       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9378     } else {
9379       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9380       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9381       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9382
9383       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9384       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9385       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9386       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9387       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9388     }
9389
9390     if(shCount >=5) {
9391       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9392       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9393     }
9394
9395     if(sign) {
9396       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9397       pic16_emitpcode(POC_BTFSC, 
9398                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9399       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9400     }
9401
9402     break;
9403
9404   case 6:
9405     if(same) {
9406
9407       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9408       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9409
9410       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9411       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9412       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9413       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9414       if(sign) {
9415         pic16_emitpcode(POC_BTFSC, 
9416                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9417         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9418       }
9419       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9420       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9421       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9422       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9423     } else {
9424       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9425       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9426       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9427       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9428       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9429       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9430       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9431       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9432       if(sign) {
9433         pic16_emitpcode(POC_BTFSC, 
9434                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9435         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9436       }
9437       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9438       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9439
9440         
9441     }
9442
9443     break;
9444   case 7:
9445     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9446     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9447     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9448     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9449     if(sign) {
9450       emitSKPNC;
9451       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9452     } else 
9453       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9454   }
9455 }
9456
9457
9458 /*-----------------------------------------------------------------*/
9459 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9460 /*-----------------------------------------------------------------*/
9461 static void shiftLLeftOrResult (operand *left, int offl,
9462                                 operand *result, int offr, int shCount)
9463 {
9464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9465
9466     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9467     /* shift left accumulator */
9468     AccLsh(shCount, 1);
9469     /* or with result */
9470     /* back to result */
9471     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9472 }
9473
9474 /*-----------------------------------------------------------------*/
9475 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9476 /*-----------------------------------------------------------------*/
9477 static void shiftRLeftOrResult (operand *left, int offl,
9478                                 operand *result, int offr, int shCount)
9479 {
9480     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9481     
9482     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9483     /* shift right accumulator */
9484     AccRsh(shCount, 1);
9485     /* or with result */
9486     /* back to result */
9487     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9488 }
9489
9490 /*-----------------------------------------------------------------*/
9491 /* genlshOne - left shift a one byte quantity by known count       */
9492 /*-----------------------------------------------------------------*/
9493 static void genlshOne (operand *result, operand *left, int shCount)
9494 {       
9495     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9496     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9497 }
9498
9499 /*-----------------------------------------------------------------*/
9500 /* genlshTwo - left shift two bytes by known amount != 0           */
9501 /*-----------------------------------------------------------------*/
9502 static void genlshTwo (operand *result,operand *left, int shCount)
9503 {
9504     int size;
9505     
9506     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9507     size = pic16_getDataSize(result);
9508
9509     /* if shCount >= 8 */
9510     if (shCount >= 8) {
9511         shCount -= 8 ;
9512
9513         if (size > 1){
9514             if (shCount)
9515                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9516             else 
9517                 movLeft2Result(left, LSB, result, MSB16);
9518         }
9519         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9520     }
9521
9522     /*  1 <= shCount <= 7 */
9523     else {  
9524         if(size == 1)
9525             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9526         else 
9527             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9528     }
9529 }
9530
9531 /*-----------------------------------------------------------------*/
9532 /* shiftLLong - shift left one long from left to result            */
9533 /* offr = LSB or MSB16                                             */
9534 /*-----------------------------------------------------------------*/
9535 static void shiftLLong (operand *left, operand *result, int offr )
9536 {
9537     int size = AOP_SIZE(result);
9538     int same = pic16_sameRegs(AOP(left),AOP(result));
9539         int i;
9540
9541     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9542
9543         if (same && (offr == MSB16)) { //shift one byte
9544                 for(i=size-1;i>=MSB16;i--) {
9545                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9546                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9547                 }
9548         } else {
9549                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9550         }
9551         
9552     if (size > LSB+offr ){
9553                 if (same) {
9554                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9555                 } else {
9556                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9557                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9558                 }
9559          }
9560
9561     if(size > MSB16+offr){
9562                 if (same) {
9563                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9564                 } else {
9565                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9566                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9567                 }
9568     }
9569
9570     if(size > MSB24+offr){
9571                 if (same) {
9572                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9573                 } else {
9574                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9575                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9576                 }
9577     }
9578
9579     if(size > MSB32+offr){
9580                 if (same) {
9581                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9582                 } else {
9583                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9584                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9585                 }
9586     }
9587     if(offr != LSB)
9588                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9589
9590 }
9591
9592 /*-----------------------------------------------------------------*/
9593 /* genlshFour - shift four byte by a known amount != 0             */
9594 /*-----------------------------------------------------------------*/
9595 static void genlshFour (operand *result, operand *left, int shCount)
9596 {
9597     int size;
9598
9599     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9600     size = AOP_SIZE(result);
9601
9602     /* if shifting more that 3 bytes */
9603     if (shCount >= 24 ) {
9604         shCount -= 24;
9605         if (shCount)
9606             /* lowest order of left goes to the highest
9607             order of the destination */
9608             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9609         else
9610             movLeft2Result(left, LSB, result, MSB32);
9611
9612                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9613                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9614                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9615
9616         return;
9617     }
9618
9619     /* more than two bytes */
9620     else if ( shCount >= 16 ) {
9621         /* lower order two bytes goes to higher order two bytes */
9622         shCount -= 16;
9623         /* if some more remaining */
9624         if (shCount)
9625             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9626         else {
9627             movLeft2Result(left, MSB16, result, MSB32);
9628             movLeft2Result(left, LSB, result, MSB24);
9629         }
9630                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9631                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9632         return;
9633     }    
9634
9635     /* if more than 1 byte */
9636     else if ( shCount >= 8 ) {
9637         /* lower order three bytes goes to higher order  three bytes */
9638         shCount -= 8;
9639         if(size == 2){
9640             if(shCount)
9641                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9642             else
9643                 movLeft2Result(left, LSB, result, MSB16);
9644         }
9645         else{   /* size = 4 */
9646             if(shCount == 0){
9647                 movLeft2Result(left, MSB24, result, MSB32);
9648                 movLeft2Result(left, MSB16, result, MSB24);
9649                 movLeft2Result(left, LSB, result, MSB16);
9650                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9651             }
9652             else if(shCount == 1)
9653                 shiftLLong(left, result, MSB16);
9654             else{
9655                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9656                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9657                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9658                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9659             }
9660         }
9661     }
9662
9663     /* 1 <= shCount <= 7 */
9664     else if(shCount <= 3)
9665     { 
9666         shiftLLong(left, result, LSB);
9667         while(--shCount >= 1)
9668             shiftLLong(result, result, LSB);
9669     }
9670     /* 3 <= shCount <= 7, optimize */
9671     else{
9672         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9673         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9674         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9675     }
9676 }
9677
9678 /*-----------------------------------------------------------------*/
9679 /* genLeftShiftLiteral - left shifting by known count              */
9680 /*-----------------------------------------------------------------*/
9681 void pic16_genLeftShiftLiteral (operand *left,
9682                                  operand *right,
9683                                  operand *result,
9684                                  iCode *ic)
9685 {    
9686     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9687     int size;
9688
9689     FENTRY;
9690     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9691     pic16_freeAsmop(right,NULL,ic,TRUE);
9692
9693     pic16_aopOp(left,ic,FALSE);
9694     pic16_aopOp(result,ic,TRUE);
9695
9696     size = getSize(operandType(result));
9697
9698 #if VIEW_SIZE
9699     pic16_emitcode("; shift left ","result %d, left %d",size,
9700              AOP_SIZE(left));
9701 #endif
9702
9703     /* I suppose that the left size >= result size */
9704     if(shCount == 0){
9705         while(size--){
9706             movLeft2Result(left, size, result, size);
9707         }
9708     }
9709
9710     else if(shCount >= (size * 8))
9711         while(size--)
9712             pic16_aopPut(AOP(result),zero,size);
9713     else{
9714         switch (size) {
9715             case 1:
9716                 genlshOne (result,left,shCount);
9717                 break;
9718
9719             case 2:
9720             case 3:
9721                 genlshTwo (result,left,shCount);
9722                 break;
9723
9724             case 4:
9725                 genlshFour (result,left,shCount);
9726                 break;
9727         }
9728     }
9729     pic16_freeAsmop(left,NULL,ic,TRUE);
9730     pic16_freeAsmop(result,NULL,ic,TRUE);
9731 }
9732
9733 /*-----------------------------------------------------------------*
9734  * genMultiAsm - repeat assembly instruction for size of register.
9735  * if endian == 1, then the high byte (i.e base address + size of 
9736  * register) is used first else the low byte is used first;
9737  *-----------------------------------------------------------------*/
9738 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9739 {
9740
9741   int offset = 0;
9742
9743   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9744
9745   if(!reg)
9746     return;
9747
9748   if(!endian) {
9749     endian = 1;
9750   } else {
9751     endian = -1;
9752     offset = size-1;
9753   }
9754
9755   while(size--) {
9756     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9757     offset += endian;
9758   }
9759
9760 }
9761
9762 #if !(USE_GENERIC_SIGNED_SHIFT)
9763 /*-----------------------------------------------------------------*/
9764 /* genLeftShift - generates code for left shifting                 */
9765 /*-----------------------------------------------------------------*/
9766 static void genLeftShift (iCode *ic)
9767 {
9768   operand *left,*right, *result;
9769   int size, offset;
9770 //  char *l;
9771   symbol *tlbl , *tlbl1;
9772   pCodeOp *pctemp;
9773
9774   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9775
9776   right = IC_RIGHT(ic);
9777   left  = IC_LEFT(ic);
9778   result = IC_RESULT(ic);
9779
9780   pic16_aopOp(right,ic,FALSE);
9781
9782   /* if the shift count is known then do it 
9783      as efficiently as possible */
9784   if (AOP_TYPE(right) == AOP_LIT) {
9785     pic16_genLeftShiftLiteral (left,right,result,ic);
9786     return ;
9787   }
9788
9789   /* shift count is unknown then we have to form
9790    * a loop. Get the loop count in WREG : Note: we take
9791    * only the lower order byte since shifting
9792    * more than 32 bits make no sense anyway, ( the
9793    * largest size of an object can be only 32 bits ) */
9794   
9795   pic16_aopOp(left,ic,FALSE);
9796   pic16_aopOp(result,ic,FALSE);
9797
9798   /* now move the left to the result if they are not the
9799    * same, and if size > 1,
9800    * and if right is not same to result (!!!) -- VR */
9801   if (!pic16_sameRegs(AOP(left),AOP(result))
9802       && (AOP_SIZE(result) > 1)) {
9803
9804     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9805
9806     size = AOP_SIZE(result);
9807     offset=0;
9808     while (size--) {
9809
9810 #if 0
9811       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9812       if (*l == '@' && (IS_AOP_PREG(result))) {
9813
9814           pic16_emitcode("mov","a,%s",l);
9815           pic16_aopPut(AOP(result),"a",offset);
9816       } else
9817 #endif
9818       {
9819         /* we don't know if left is a literal or a register, take care -- VR */
9820         pic16_mov2f(AOP(result), AOP(left), offset);
9821       }
9822       offset++;
9823     }
9824   }
9825
9826   size = AOP_SIZE(result);
9827
9828   /* if it is only one byte then */
9829   if (size == 1) {
9830     if(optimized_for_speed) {
9831       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9832       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9833       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9834       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9835       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9836       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9837       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9838       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9839       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9840       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9841       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9842       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9843     } else {
9844
9845       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9846
9847       tlbl = newiTempLabel(NULL);
9848
9849 #if 1
9850       /* this is already done, why change it? */
9851       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9852                 pic16_mov2f(AOP(result), AOP(left), 0);
9853       }
9854 #endif
9855
9856       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9857       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9858       pic16_emitpLabel(tlbl->key);
9859       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9860       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9861       emitSKPC;
9862       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9863     }
9864     goto release ;
9865   }
9866     
9867   if (pic16_sameRegs(AOP(left),AOP(result))) {
9868
9869     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9870     
9871     tlbl = newiTempLabel(NULL);
9872     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9873     genMultiAsm(POC_RRCF, result, size,1);
9874     pic16_emitpLabel(tlbl->key);
9875     genMultiAsm(POC_RLCF, result, size,0);
9876     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9877     emitSKPC;
9878     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9879     goto release;
9880   }
9881
9882   //tlbl = newiTempLabel(NULL);
9883   //offset = 0 ;   
9884   //tlbl1 = newiTempLabel(NULL);
9885
9886   //reAdjustPreg(AOP(result));    
9887     
9888   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9889   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9890   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9891   //MOVA(l);
9892   //pic16_emitcode("add","a,acc");         
9893   //pic16_aopPut(AOP(result),"a",offset++);
9894   //while (--size) {
9895   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9896   //  MOVA(l);
9897   //  pic16_emitcode("rlc","a");         
9898   //  pic16_aopPut(AOP(result),"a",offset++);
9899   //}
9900   //reAdjustPreg(AOP(result));
9901
9902   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9903   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9904
9905
9906   tlbl = newiTempLabel(NULL);
9907   tlbl1= newiTempLabel(NULL);
9908
9909   size = AOP_SIZE(result);
9910   offset = 1;
9911
9912   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9913
9914   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9915
9916   /* offset should be 0, 1 or 3 */
9917   
9918   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9919   emitSKPNZ;
9920   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9921
9922   pic16_emitpcode(POC_MOVWF, pctemp);
9923
9924
9925   pic16_emitpLabel(tlbl->key);
9926
9927   emitCLRC;
9928   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9929   while(--size)
9930     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9931
9932   pic16_emitpcode(POC_DECFSZ,  pctemp);
9933   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9934   pic16_emitpLabel(tlbl1->key);
9935
9936   pic16_popReleaseTempReg(pctemp,1);
9937
9938
9939  release:
9940   pic16_freeAsmop (right,NULL,ic,TRUE);
9941   pic16_freeAsmop(left,NULL,ic,TRUE);
9942   pic16_freeAsmop(result,NULL,ic,TRUE);
9943 }
9944 #endif
9945
9946
9947 #if 0
9948 #error old code (left here for reference)
9949 /*-----------------------------------------------------------------*/
9950 /* genLeftShift - generates code for left shifting                 */
9951 /*-----------------------------------------------------------------*/
9952 static void genLeftShift (iCode *ic)
9953 {
9954   operand *left,*right, *result;
9955   int size, offset;
9956   char *l;
9957   symbol *tlbl , *tlbl1;
9958   pCodeOp *pctemp;
9959
9960   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9961
9962   right = IC_RIGHT(ic);
9963   left  = IC_LEFT(ic);
9964   result = IC_RESULT(ic);
9965
9966   pic16_aopOp(right,ic,FALSE);
9967
9968   /* if the shift count is known then do it 
9969      as efficiently as possible */
9970   if (AOP_TYPE(right) == AOP_LIT) {
9971     pic16_genLeftShiftLiteral (left,right,result,ic);
9972     return ;
9973   }
9974
9975   /* shift count is unknown then we have to form 
9976      a loop get the loop count in B : Note: we take
9977      only the lower order byte since shifting
9978      more that 32 bits make no sense anyway, ( the
9979      largest size of an object can be only 32 bits ) */  
9980
9981     
9982   pic16_aopOp(left,ic,FALSE);
9983   pic16_aopOp(result,ic,FALSE);
9984
9985   /* now move the left to the result if they are not the
9986      same */
9987   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9988       AOP_SIZE(result) > 1) {
9989
9990     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9991
9992     size = AOP_SIZE(result);
9993     offset=0;
9994     while (size--) {
9995       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9996       if (*l == '@' && (IS_AOP_PREG(result))) {
9997
9998         pic16_emitcode("mov","a,%s",l);
9999         pic16_aopPut(AOP(result),"a",offset);
10000       } else {
10001
10002         /* we don't know if left is a literal or a register, take care -- VR */
10003         pic16_mov2f(AOP(result), AOP(left), offset);
10004       }
10005       offset++;
10006     }
10007   }
10008
10009   size = AOP_SIZE(result);
10010
10011   /* if it is only one byte then */
10012   if (size == 1) {
10013     if(optimized_for_speed) {
10014       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10015       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10016       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10017       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10018       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10019       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10020       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10021       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10022       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10023       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10024       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10025       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10026     } else {
10027
10028       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10029
10030       tlbl = newiTempLabel(NULL);
10031       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10032                 pic16_mov2f(AOP(result), AOP(left), 0);
10033                 
10034 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10035 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10036       }
10037
10038       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10039       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10040       pic16_emitpLabel(tlbl->key);
10041       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10042       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10043       emitSKPC;
10044       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10045     }
10046     goto release ;
10047   }
10048     
10049   if (pic16_sameRegs(AOP(left),AOP(result))) {
10050
10051     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10052     
10053     tlbl = newiTempLabel(NULL);
10054     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10055     genMultiAsm(POC_RRCF, result, size,1);
10056     pic16_emitpLabel(tlbl->key);
10057     genMultiAsm(POC_RLCF, result, size,0);
10058     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10059     emitSKPC;
10060     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10061     goto release;
10062   }
10063
10064   //tlbl = newiTempLabel(NULL);
10065   //offset = 0 ;   
10066   //tlbl1 = newiTempLabel(NULL);
10067
10068   //reAdjustPreg(AOP(result));    
10069     
10070   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10071   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10072   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10073   //MOVA(l);
10074   //pic16_emitcode("add","a,acc");         
10075   //pic16_aopPut(AOP(result),"a",offset++);
10076   //while (--size) {
10077   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10078   //  MOVA(l);
10079   //  pic16_emitcode("rlc","a");         
10080   //  pic16_aopPut(AOP(result),"a",offset++);
10081   //}
10082   //reAdjustPreg(AOP(result));
10083
10084   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10085   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10086
10087
10088   tlbl = newiTempLabel(NULL);
10089   tlbl1= newiTempLabel(NULL);
10090
10091   size = AOP_SIZE(result);
10092   offset = 1;
10093
10094   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10095
10096   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10097
10098   /* offset should be 0, 1 or 3 */
10099   
10100   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10101   emitSKPNZ;
10102   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10103
10104   pic16_emitpcode(POC_MOVWF, pctemp);
10105
10106
10107   pic16_emitpLabel(tlbl->key);
10108
10109   emitCLRC;
10110   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10111   while(--size)
10112     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10113
10114   pic16_emitpcode(POC_DECFSZ,  pctemp);
10115   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10116   pic16_emitpLabel(tlbl1->key);
10117
10118   pic16_popReleaseTempReg(pctemp,1);
10119
10120
10121  release:
10122   pic16_freeAsmop (right,NULL,ic,TRUE);
10123   pic16_freeAsmop(left,NULL,ic,TRUE);
10124   pic16_freeAsmop(result,NULL,ic,TRUE);
10125 }
10126 #endif
10127
10128 /*-----------------------------------------------------------------*/
10129 /* genrshOne - right shift a one byte quantity by known count      */
10130 /*-----------------------------------------------------------------*/
10131 static void genrshOne (operand *result, operand *left,
10132                        int shCount, int sign)
10133 {
10134     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10135     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10136 }
10137
10138 /*-----------------------------------------------------------------*/
10139 /* genrshTwo - right shift two bytes by known amount != 0          */
10140 /*-----------------------------------------------------------------*/
10141 static void genrshTwo (operand *result,operand *left,
10142                        int shCount, int sign)
10143 {
10144   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10145   /* if shCount >= 8 */
10146   if (shCount >= 8) {
10147     shCount -= 8 ;
10148     if (shCount)
10149       shiftR1Left2Result(left, MSB16, result, LSB,
10150                          shCount, sign);
10151     else
10152       movLeft2Result(left, MSB16, result, LSB);
10153
10154     pic16_addSign (result, 1, sign);
10155   }
10156
10157   /*  1 <= shCount <= 7 */
10158   else
10159     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10160 }
10161
10162 /*-----------------------------------------------------------------*/
10163 /* shiftRLong - shift right one long from left to result           */
10164 /* offl = LSB or MSB16                                             */
10165 /*-----------------------------------------------------------------*/
10166 static void shiftRLong (operand *left, int offl,
10167                         operand *result, int sign)
10168 {
10169     int size = AOP_SIZE(result);
10170     int same = pic16_sameRegs(AOP(left),AOP(result));
10171     int i;
10172     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10173
10174         if (same && (offl == MSB16)) { //shift one byte right
10175                 for(i=MSB16;i<size;i++) {
10176                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10177                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10178                 }
10179         }
10180
10181     if(sign)
10182                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10183         else
10184                 emitCLRC;
10185
10186         if (same) {
10187                 if (offl == LSB)
10188                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10189         } else {
10190         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10191         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10192         }
10193
10194     if(offl == MSB16) {
10195         /* add sign of "a" */
10196         pic16_addSign(result, MSB32, sign);
10197         }
10198
10199         if (same) {
10200         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10201         } else {
10202         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10203         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10204         }
10205         
10206         if (same) {
10207         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10208         } else {
10209         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10210         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10211         }
10212
10213         if (same) {
10214         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10215         } else {
10216         if(offl == LSB){
10217                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10218                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10219         }
10220         }
10221 }
10222
10223 /*-----------------------------------------------------------------*/
10224 /* genrshFour - shift four byte by a known amount != 0             */
10225 /*-----------------------------------------------------------------*/
10226 static void genrshFour (operand *result, operand *left,
10227                         int shCount, int sign)
10228 {
10229   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10230   /* if shifting more that 3 bytes */
10231   if(shCount >= 24 ) {
10232     shCount -= 24;
10233     if(shCount)
10234       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10235     else
10236       movLeft2Result(left, MSB32, result, LSB);
10237
10238     pic16_addSign(result, MSB16, sign);
10239   }
10240   else if(shCount >= 16){
10241     shCount -= 16;
10242     if(shCount)
10243       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10244     else{
10245       movLeft2Result(left, MSB24, result, LSB);
10246       movLeft2Result(left, MSB32, result, MSB16);
10247     }
10248     pic16_addSign(result, MSB24, sign);
10249   }
10250   else if(shCount >= 8){
10251     shCount -= 8;
10252     if(shCount == 1)
10253       shiftRLong(left, MSB16, result, sign);
10254     else if(shCount == 0){
10255       movLeft2Result(left, MSB16, result, LSB);
10256       movLeft2Result(left, MSB24, result, MSB16);
10257       movLeft2Result(left, MSB32, result, MSB24);
10258       pic16_addSign(result, MSB32, sign);
10259     }
10260     else{ //shcount >= 2
10261       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10262       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10263       /* the last shift is signed */
10264       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10265       pic16_addSign(result, MSB32, sign);
10266     }
10267   }
10268   else{   /* 1 <= shCount <= 7 */
10269     if(shCount <= 2){
10270       shiftRLong(left, LSB, result, sign);
10271       if(shCount == 2)
10272         shiftRLong(result, LSB, result, sign);
10273     }
10274     else{
10275       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10276       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10277       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10278     }
10279   }
10280 }
10281
10282 /*-----------------------------------------------------------------*/
10283 /* genRightShiftLiteral - right shifting by known count            */
10284 /*-----------------------------------------------------------------*/
10285 static void genRightShiftLiteral (operand *left,
10286                                   operand *right,
10287                                   operand *result,
10288                                   iCode *ic,
10289                                   int sign)
10290 {    
10291   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10292   int lsize,res_size;
10293
10294   pic16_freeAsmop(right,NULL,ic,TRUE);
10295
10296   pic16_aopOp(left,ic,FALSE);
10297   pic16_aopOp(result,ic,TRUE);
10298
10299   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10300
10301 #if VIEW_SIZE
10302   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10303                  AOP_SIZE(left));
10304 #endif
10305
10306   lsize = pic16_getDataSize(left);
10307   res_size = pic16_getDataSize(result);
10308   /* test the LEFT size !!! */
10309
10310   /* I suppose that the left size >= result size */
10311   if(shCount == 0){
10312     assert (res_size <= lsize);
10313     while (res_size--) {
10314       pic16_mov2f (AOP(result), AOP(left), res_size);
10315     } // for
10316   }
10317
10318   else if(shCount >= (lsize * 8)){
10319
10320     if(res_size == 1) {
10321       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10322       if(sign) {
10323         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10324         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10325       }
10326     } else {
10327
10328       if(sign) {
10329         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10330         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10331         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10332         while(res_size--)
10333           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10334
10335       } else {
10336
10337         while(res_size--)
10338           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10339       }
10340     }
10341   } else {
10342
10343     switch (res_size) {
10344     case 1:
10345       genrshOne (result,left,shCount,sign);
10346       break;
10347
10348     case 2:
10349       genrshTwo (result,left,shCount,sign);
10350       break;
10351
10352     case 4:
10353       genrshFour (result,left,shCount,sign);
10354       break;
10355     default :
10356       break;
10357     }
10358
10359   }
10360
10361   pic16_freeAsmop(left,NULL,ic,TRUE);
10362   pic16_freeAsmop(result,NULL,ic,TRUE);
10363 }
10364
10365 #if !(USE_GENERIC_SIGNED_SHIFT)
10366 /*-----------------------------------------------------------------*/
10367 /* genSignedRightShift - right shift of signed number              */
10368 /*-----------------------------------------------------------------*/
10369 static void genSignedRightShift (iCode *ic)
10370 {
10371   operand *right, *left, *result;
10372   int size, offset;
10373   //  char *l;
10374   symbol *tlbl, *tlbl1 ;
10375   pCodeOp *pctemp;
10376
10377   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10378
10379   /* we do it the hard way put the shift count in b
10380      and loop thru preserving the sign */
10381   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10382
10383   right = IC_RIGHT(ic);
10384   left  = IC_LEFT(ic);
10385   result = IC_RESULT(ic);
10386
10387   pic16_aopOp(right,ic,FALSE);  
10388   pic16_aopOp(left,ic,FALSE);
10389   pic16_aopOp(result,ic,FALSE);
10390
10391
10392   if ( AOP_TYPE(right) == AOP_LIT) {
10393     genRightShiftLiteral (left,right,result,ic,1);
10394     return ;
10395   }
10396   /* shift count is unknown then we have to form 
10397      a loop get the loop count in B : Note: we take
10398      only the lower order byte since shifting
10399      more that 32 bits make no sense anyway, ( the
10400      largest size of an object can be only 32 bits ) */  
10401
10402   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10403   //pic16_emitcode("inc","b");
10404   //pic16_freeAsmop (right,NULL,ic,TRUE);
10405   //pic16_aopOp(left,ic,FALSE);
10406   //pic16_aopOp(result,ic,FALSE);
10407
10408   /* now move the left to the result if they are not the
10409      same */
10410   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10411       AOP_SIZE(result) > 1) {
10412
10413     size = AOP_SIZE(result);
10414     offset=0;
10415     while (size--) { 
10416       /*
10417         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10418         if (*l == '@' && IS_AOP_PREG(result)) {
10419
10420         pic16_emitcode("mov","a,%s",l);
10421         pic16_aopPut(AOP(result),"a",offset);
10422         } else
10423         pic16_aopPut(AOP(result),l,offset);
10424       */
10425       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10426       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10427
10428       offset++;
10429     }
10430   }
10431
10432   /* mov the highest order bit to OVR */    
10433   tlbl = newiTempLabel(NULL);
10434   tlbl1= newiTempLabel(NULL);
10435
10436   size = AOP_SIZE(result);
10437   offset = size - 1;
10438
10439   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10440
10441   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10442
10443   /* offset should be 0, 1 or 3 */
10444   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10445   emitSKPNZ;
10446   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10447
10448   pic16_emitpcode(POC_MOVWF, pctemp);
10449
10450
10451   pic16_emitpLabel(tlbl->key);
10452
10453   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10454   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10455
10456   while(--size) {
10457     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10458   }
10459
10460   pic16_emitpcode(POC_DECFSZ,  pctemp);
10461   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10462   pic16_emitpLabel(tlbl1->key);
10463
10464   pic16_popReleaseTempReg(pctemp,1);
10465 #if 0
10466   size = AOP_SIZE(result);
10467   offset = size - 1;
10468   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10469   pic16_emitcode("rlc","a");
10470   pic16_emitcode("mov","ov,c");
10471   /* if it is only one byte then */
10472   if (size == 1) {
10473     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10474     MOVA(l);
10475     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10476     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10477     pic16_emitcode("mov","c,ov");
10478     pic16_emitcode("rrc","a");
10479     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10480     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10481     pic16_aopPut(AOP(result),"a",0);
10482     goto release ;
10483   }
10484
10485   reAdjustPreg(AOP(result));
10486   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10487   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10488   pic16_emitcode("mov","c,ov");
10489   while (size--) {
10490     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10491     MOVA(l);
10492     pic16_emitcode("rrc","a");         
10493     pic16_aopPut(AOP(result),"a",offset--);
10494   }
10495   reAdjustPreg(AOP(result));
10496   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10497   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10498
10499  release:
10500 #endif
10501
10502   pic16_freeAsmop(left,NULL,ic,TRUE);
10503   pic16_freeAsmop(result,NULL,ic,TRUE);
10504   pic16_freeAsmop(right,NULL,ic,TRUE);
10505 }
10506 #endif
10507
10508 #if !(USE_GENERIC_SIGNED_SHIFT)
10509 #warning This implementation of genRightShift() is incomplete!
10510 /*-----------------------------------------------------------------*/
10511 /* genRightShift - generate code for right shifting                */
10512 /*-----------------------------------------------------------------*/
10513 static void genRightShift (iCode *ic)
10514 {
10515     operand *right, *left, *result;
10516     sym_link *letype ;
10517     int size, offset;
10518     char *l;
10519     symbol *tlbl, *tlbl1 ;
10520
10521     /* if signed then we do it the hard way preserve the
10522     sign bit moving it inwards */
10523     letype = getSpec(operandType(IC_LEFT(ic)));
10524     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10525
10526     if (!SPEC_USIGN(letype)) {
10527         genSignedRightShift (ic);
10528         return ;
10529     }
10530
10531     /* signed & unsigned types are treated the same : i.e. the
10532     signed is NOT propagated inwards : quoting from the
10533     ANSI - standard : "for E1 >> E2, is equivalent to division
10534     by 2**E2 if unsigned or if it has a non-negative value,
10535     otherwise the result is implementation defined ", MY definition
10536     is that the sign does not get propagated */
10537
10538     right = IC_RIGHT(ic);
10539     left  = IC_LEFT(ic);
10540     result = IC_RESULT(ic);
10541
10542     pic16_aopOp(right,ic,FALSE);
10543
10544     /* if the shift count is known then do it 
10545     as efficiently as possible */
10546     if (AOP_TYPE(right) == AOP_LIT) {
10547         genRightShiftLiteral (left,right,result,ic, 0);
10548         return ;
10549     }
10550
10551     /* shift count is unknown then we have to form 
10552     a loop get the loop count in B : Note: we take
10553     only the lower order byte since shifting
10554     more that 32 bits make no sense anyway, ( the
10555     largest size of an object can be only 32 bits ) */  
10556
10557     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10558     pic16_emitcode("inc","b");
10559     pic16_aopOp(left,ic,FALSE);
10560     pic16_aopOp(result,ic,FALSE);
10561
10562     /* now move the left to the result if they are not the
10563     same */
10564     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10565         AOP_SIZE(result) > 1) {
10566
10567         size = AOP_SIZE(result);
10568         offset=0;
10569         while (size--) {
10570             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10571             if (*l == '@' && IS_AOP_PREG(result)) {
10572
10573                 pic16_emitcode("mov","a,%s",l);
10574                 pic16_aopPut(AOP(result),"a",offset);
10575             } else
10576                 pic16_aopPut(AOP(result),l,offset);
10577             offset++;
10578         }
10579     }
10580
10581     tlbl = newiTempLabel(NULL);
10582     tlbl1= newiTempLabel(NULL);
10583     size = AOP_SIZE(result);
10584     offset = size - 1;
10585
10586     /* if it is only one byte then */
10587     if (size == 1) {
10588
10589       tlbl = newiTempLabel(NULL);
10590       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10591         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10592         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10593       }
10594
10595       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10596       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10597       pic16_emitpLabel(tlbl->key);
10598       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10599       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10600       emitSKPC;
10601       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10602
10603       goto release ;
10604     }
10605
10606     reAdjustPreg(AOP(result));
10607     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10608     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10609     CLRC;
10610     while (size--) {
10611         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10612         MOVA(l);
10613         pic16_emitcode("rrc","a");         
10614         pic16_aopPut(AOP(result),"a",offset--);
10615     }
10616     reAdjustPreg(AOP(result));
10617
10618     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10619     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10620
10621 release:
10622     pic16_freeAsmop(left,NULL,ic,TRUE);
10623     pic16_freeAsmop (right,NULL,ic,TRUE);
10624     pic16_freeAsmop(result,NULL,ic,TRUE);
10625 }
10626 #endif
10627
10628 #if (USE_GENERIC_SIGNED_SHIFT)
10629 /*-----------------------------------------------------------------*/
10630 /* genGenericShift - generates code for left or right shifting     */
10631 /*-----------------------------------------------------------------*/
10632 static void genGenericShift (iCode *ic, int isShiftLeft) {
10633   operand *left,*right, *result;
10634   int offset;
10635   int sign, signedCount;
10636   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10637   PIC_OPCODE pos_shift, neg_shift;
10638
10639   FENTRY;
10640
10641   right = IC_RIGHT(ic);
10642   left  = IC_LEFT(ic);
10643   result = IC_RESULT(ic);
10644
10645   pic16_aopOp(right,ic,FALSE);
10646   pic16_aopOp(left,ic,FALSE);
10647   pic16_aopOp(result,ic,TRUE);
10648
10649   sign = !SPEC_USIGN(operandType (left));
10650   signedCount = !SPEC_USIGN(operandType (right));
10651
10652   /* if the shift count is known then do it 
10653      as efficiently as possible */
10654   if (AOP_TYPE(right) == AOP_LIT) {
10655     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10656     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10657     // we should modify right->aopu.aop_lit here!
10658     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10659     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10660     if (isShiftLeft)
10661       pic16_genLeftShiftLiteral (left,right,result,ic);
10662     else
10663       genRightShiftLiteral (left,right,result,ic, sign);
10664
10665     goto release;
10666   } // if (right is literal)
10667
10668   /* shift count is unknown then we have to form a loop.
10669    * Note: we take only the lower order byte since shifting
10670    * more than 32 bits make no sense anyway, ( the
10671    * largest size of an object can be only 32 bits )
10672    * Note: we perform arithmetic shifts if the left operand is
10673    * signed and we do an (effective) right shift, i. e. we
10674    * shift in the sign bit from the left. */
10675    
10676   label_complete = newiTempLabel ( NULL );
10677   label_loop_pos = newiTempLabel ( NULL );
10678   label_loop_neg = NULL;
10679   label_negative = NULL;
10680   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10681   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10682
10683   if (signedCount) {
10684     // additional labels needed
10685     label_loop_neg = newiTempLabel ( NULL );
10686     label_negative = newiTempLabel ( NULL );
10687   } // if
10688
10689   // copy source to result -- this will effectively truncate the left operand to the size of result!
10690   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10691   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10692   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10693     pic16_mov2f (AOP(result),AOP(left), offset);
10694   } // for
10695
10696   // if result is longer than left, fill with zeros (or sign)
10697   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10698     if (sign && AOP_SIZE(left) > 0) {
10699       // shift signed operand -- fill with sign
10700       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10701       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10702       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10703       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10704         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10705       } // for
10706     } else {
10707       // shift unsigned operand -- fill result with zeros
10708       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10709         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10710       } // for
10711     }
10712   } // if (size mismatch)
10713
10714   pic16_mov2w (AOP(right), 0);
10715   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10716   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10717   
10718 #if 0
10719   // perform a shift by one (shift count is positive)
10720   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10721   // 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])
10722   pic16_emitpLabel (label_loop_pos->key);
10723   emitCLRC;
10724   if (sign && (pos_shift == POC_RRCF)) {
10725     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10726     emitSETC;
10727   } // if
10728   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10729   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10730   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10731 #else
10732   // perform a shift by one (shift count is positive)
10733   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10734   // 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])
10735   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10736   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10737   emitCLRC;
10738   pic16_emitpLabel (label_loop_pos->key);
10739   if (sign && (pos_shift == POC_RRCF)) {
10740     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10741     emitSETC;
10742   } // if
10743   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10744   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10745   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10746   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10747 #endif
10748
10749   if (signedCount) {
10750     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10751
10752     pic16_emitpLabel (label_negative->key);
10753     // perform a shift by -1 (shift count is negative)
10754     // 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)
10755     emitCLRC;
10756     pic16_emitpLabel (label_loop_neg->key);
10757     if (sign && (neg_shift == POC_RRCF)) {
10758       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10759       emitSETC;
10760     } // if
10761     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10762     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10763     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10764     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10765   } // if (signedCount)
10766
10767   pic16_emitpLabel (label_complete->key);
10768
10769 release:
10770   pic16_freeAsmop (right,NULL,ic,TRUE);
10771   pic16_freeAsmop(left,NULL,ic,TRUE);
10772   pic16_freeAsmop(result,NULL,ic,TRUE);
10773 }
10774
10775 static void genLeftShift (iCode *ic) {
10776   genGenericShift (ic, 1);
10777 }
10778
10779 static void genRightShift (iCode *ic) {
10780   genGenericShift (ic, 0);
10781 }
10782 #endif
10783
10784
10785 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10786 void pic16_loadFSR0(operand *op, int lit)
10787 {
10788   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10789     if (AOP_TYPE(op) == AOP_LIT) {
10790       /* handle 12 bit integers correctly */
10791       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10792       if ((val & 0x0fff) != val) {
10793         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10794                 val, (val & 0x0fff) );
10795         val &= 0x0fff;
10796       }
10797       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10798     } else {
10799       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10800     }
10801   } else {
10802     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10803     // set up FSR0 with address of result
10804     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10805     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10806   }
10807 }
10808
10809 /*----------------------------------------------------------------*/
10810 /* pic16_derefPtr - move one byte from the location ptr points to */
10811 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10812 /*                  to the location ptr points to (doWrite != 0)   */
10813 /*----------------------------------------------------------------*/
10814 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10815 {
10816   if (!IS_PTR(operandType(ptr)))
10817   {
10818     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10819     else pic16_mov2w (AOP(ptr), 0);
10820     return;
10821   }
10822
10823   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10824   /* We might determine pointer type right here: */
10825   p_type = DCL_TYPE(operandType(ptr));
10826
10827   switch (p_type) {
10828     case FPOINTER:
10829     case POINTER:
10830       if (!fsr0_setup || !*fsr0_setup)
10831       {
10832         pic16_loadFSR0( ptr, 0 );
10833         if (fsr0_setup) *fsr0_setup = 1;
10834       }
10835       if (doWrite)
10836         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10837       else
10838         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10839       break;
10840
10841     case GPOINTER:
10842       if (AOP(ptr)->aopu.aop_reg[2]) {
10843         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10844         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10845         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10846         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10847         pic16_mov2w(AOP(ptr), 2);
10848         pic16_callGenericPointerRW(doWrite, 1);
10849       } else {
10850         // data pointer (just 2 byte given)
10851         if (!fsr0_setup || !*fsr0_setup)
10852         {
10853           pic16_loadFSR0( ptr, 0 );
10854           if (fsr0_setup) *fsr0_setup = 1;
10855         }
10856         if (doWrite)
10857           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10858         else
10859           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10860       }
10861       break;
10862
10863     default:
10864       assert (0 && "invalid pointer type specified");
10865       break;
10866   }
10867 }
10868
10869 /*-----------------------------------------------------------------*/
10870 /* genUnpackBits - generates code for unpacking bits               */
10871 /*-----------------------------------------------------------------*/
10872 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10873 {    
10874   int shCnt ;
10875   sym_link *etype, *letype;
10876   int blen=0, bstr=0;
10877   int lbstr;
10878   int same;
10879   pCodeOp *op;
10880
10881   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10882   etype = getSpec(operandType(result));
10883   letype = getSpec(operandType(left));
10884
10885   //    if(IS_BITFIELD(etype)) {
10886   blen = SPEC_BLEN(etype);
10887   bstr = SPEC_BSTR(etype);
10888   //    }
10889
10890   lbstr = SPEC_BSTR( letype );
10891
10892   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10893       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10894
10895 #if 1
10896   if((blen == 1) && (bstr < 8)
10897       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10898     /* it is a single bit, so use the appropriate bit instructions */
10899     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10900
10901     same = pic16_sameRegs(AOP(left),AOP(result));
10902     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10903     pic16_emitpcode(POC_CLRF, op);
10904
10905     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10906       /* workaround to reduce the extra lfsr instruction */
10907       pic16_emitpcode(POC_BTFSC,
10908           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10909     } else {
10910       assert (PIC_IS_DATA_PTR (operandType(left)));
10911       pic16_loadFSR0 (left, 0);
10912       pic16_emitpcode(POC_BTFSC,
10913           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10914     }
10915
10916     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10917       /* unsigned bitfields result in either 0 or 1 */
10918       pic16_emitpcode(POC_INCF, op);
10919     } else {
10920       /* signed bitfields result in either 0 or -1 */
10921       pic16_emitpcode(POC_DECF, op);
10922     }
10923     if (same) {
10924       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10925     }
10926
10927     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10928     return;
10929   }
10930
10931 #endif
10932
10933   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10934     // access symbol directly
10935     pic16_mov2w (AOP(left), 0);
10936   } else {
10937     pic16_derefPtr (left, ptype, 0, NULL);
10938   }
10939
10940   /* if we have bitdisplacement then it fits   */
10941   /* into this byte completely or if length is */
10942   /* less than a byte                          */
10943   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10944
10945     /* shift right acc */
10946     AccRsh(shCnt, 0);
10947
10948     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10949           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10950
10951     /* VR -- normally I would use the following, but since we use the hack,
10952      * to avoid the masking from AccRsh, why not mask it right now? */
10953
10954     /*
10955        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10956      */
10957
10958     /* extend signed bitfields to 8 bits */
10959     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10960     {
10961       assert (blen + bstr > 0);
10962       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10963       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10964     }
10965
10966     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10967
10968     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10969     return ;
10970   }
10971
10972   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10973   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10974   exit(EXIT_FAILURE);
10975
10976   return ;
10977 }
10978
10979
10980 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10981 {
10982   int size, offset = 0, leoffset=0 ;
10983
10984         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10985         pic16_aopOp(result, ic, TRUE);
10986
10987         FENTRY;
10988
10989         size = AOP_SIZE(result);
10990 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10991
10992
10993 #if 1
10994         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10995                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10996                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10997                 goto release;
10998         }
10999 #endif
11000
11001         if(AOP(left)->aopu.pcop->type == PO_DIR)
11002                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11003
11004         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11005
11006         while (size--) {
11007                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11008                 
11009 //              pic16_DumpOp("(result)",result);
11010                 if(is_LitAOp(AOP(result))) {
11011                         pic16_mov2w(AOP(left), offset); // patch 8
11012                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11013                 } else {
11014                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11015                                 pic16_popGet(AOP(left), offset), //patch 8
11016                                 pic16_popGet(AOP(result), offset)));
11017                 }
11018
11019                 offset++;
11020                 leoffset++;
11021         }
11022
11023 release:
11024     pic16_freeAsmop(result,NULL,ic,TRUE);
11025 }
11026
11027
11028
11029 /*-----------------------------------------------------------------*/
11030 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11031 /*-----------------------------------------------------------------*/
11032 static void genNearPointerGet (operand *left, 
11033                                operand *result, 
11034                                iCode *ic)
11035 {
11036 //  asmop *aop = NULL;
11037   //regs *preg = NULL ;
11038   sym_link *rtype, *retype;
11039   sym_link *ltype, *letype;
11040
11041     FENTRY;
11042     
11043     rtype = operandType(result);
11044     retype= getSpec(rtype);
11045     ltype = operandType(left);
11046     letype= getSpec(ltype);
11047     
11048     pic16_aopOp(left,ic,FALSE);
11049
11050 //    pic16_DumpOp("(left)",left);
11051 //    pic16_DumpOp("(result)",result);
11052
11053     /* if left is rematerialisable and
11054      * result is not bit variable type and
11055      * the left is pointer to data space i.e
11056      * lower 128 bytes of space */
11057     
11058     if (AOP_TYPE(left) == AOP_PCODE
11059       && !IS_BITFIELD(retype)
11060       && DCL_TYPE(ltype) == POINTER) {
11061
11062         genDataPointerGet (left,result,ic);
11063         pic16_freeAsmop(left, NULL, ic, TRUE);
11064         return ;
11065     }
11066     
11067     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11068     pic16_aopOp (result,ic,TRUE);
11069     
11070     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11071
11072 #if 1
11073     if(IS_BITFIELD( retype )
11074       && (SPEC_BLEN(operandType(result))==1)
11075     ) {
11076       iCode *nextic;
11077       pCodeOp *jop;
11078       int bitstrt, bytestrt;
11079
11080         /* if this is bitfield of size 1, see if we are checking the value
11081          * of a single bit in an if-statement,
11082          * if yes, then don't generate usual code, but execute the
11083          * genIfx directly -- VR */
11084
11085         nextic = ic->next;
11086
11087         /* CHECK: if next iCode is IFX
11088          * and current result operand is nextic's conditional operand
11089          * and current result operand live ranges ends at nextic's key number
11090          */
11091         if((nextic->op == IFX)
11092           && (result == IC_COND(nextic))
11093           && (OP_LIVETO(result) == nextic->seq)
11094           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
11095           ) {
11096             /* everything is ok then */
11097             /* find a way to optimize the genIfx iCode */
11098
11099             bytestrt = SPEC_BSTR(operandType(result))/8;
11100             bitstrt = SPEC_BSTR(operandType(result))%8;
11101             
11102             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11103
11104             genIfxpCOpJump(nextic, jop);
11105             
11106             pic16_freeAsmop(left, NULL, ic, TRUE);
11107             pic16_freeAsmop(result, NULL, ic, TRUE);
11108             return;
11109         }
11110     }
11111 #endif
11112
11113     /* if bitfield then unpack the bits */
11114     if (IS_BITFIELD(letype)) 
11115       genUnpackBits (result, left, NULL, POINTER);
11116     else {
11117       /* we have can just get the values */
11118       int size = AOP_SIZE(result);
11119       int offset = 0;   
11120         
11121       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11122
11123       pic16_loadFSR0( left, 0 );
11124
11125       while(size--) {
11126         if(size) {
11127           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11128                 pic16_popGet(AOP(result), offset++)));
11129         } else {
11130           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11131                 pic16_popGet(AOP(result), offset++)));
11132         }
11133       }
11134     }
11135
11136 #if 0
11137     /* now some housekeeping stuff */
11138     if (aop) {
11139       /* we had to allocate for this iCode */
11140       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11141       pic16_freeAsmop(NULL,aop,ic,TRUE);
11142     } else { 
11143       /* we did not allocate which means left
11144        * already in a pointer register, then
11145        * if size > 0 && this could be used again
11146        * we have to point it back to where it 
11147        * belongs */
11148       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11149       if (AOP_SIZE(result) > 1
11150         && !OP_SYMBOL(left)->remat
11151         && ( OP_SYMBOL(left)->liveTo > ic->seq
11152             || ic->depth )) {
11153 //        int size = AOP_SIZE(result) - 1;
11154 //        while (size--)
11155 //          pic16_emitcode("dec","%s",rname);
11156         }
11157     }
11158 #endif
11159
11160     /* done */
11161     pic16_freeAsmop(left,NULL,ic,TRUE);
11162     pic16_freeAsmop(result,NULL,ic,TRUE);
11163 }
11164
11165 /*-----------------------------------------------------------------*/
11166 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11167 /*-----------------------------------------------------------------*/
11168 static void genPagedPointerGet (operand *left, 
11169                                operand *result, 
11170                                iCode *ic)
11171 {
11172     asmop *aop = NULL;
11173     regs *preg = NULL ;
11174     char *rname ;
11175     sym_link *rtype, *retype;    
11176
11177     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11178
11179     rtype = operandType(result);
11180     retype= getSpec(rtype);
11181     
11182     pic16_aopOp(left,ic,FALSE);
11183
11184   /* if the value is already in a pointer register
11185        then don't need anything more */
11186     if (!AOP_INPREG(AOP(left))) {
11187         /* otherwise get a free pointer register */
11188         aop = newAsmop(0);
11189         preg = getFreePtr(ic,&aop,FALSE);
11190         pic16_emitcode("mov","%s,%s",
11191                 preg->name,
11192                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11193         rname = preg->name ;
11194     } else
11195         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11196     
11197     pic16_freeAsmop(left,NULL,ic,TRUE);
11198     pic16_aopOp (result,ic,TRUE);
11199
11200     /* if bitfield then unpack the bits */
11201     if (IS_BITFIELD(retype)) 
11202         genUnpackBits (result,left,rname,PPOINTER);
11203     else {
11204         /* we have can just get the values */
11205         int size = AOP_SIZE(result);
11206         int offset = 0 ;        
11207         
11208         while (size--) {
11209             
11210             pic16_emitcode("movx","a,@%s",rname);
11211             pic16_aopPut(AOP(result),"a",offset);
11212             
11213             offset++ ;
11214             
11215             if (size)
11216                 pic16_emitcode("inc","%s",rname);
11217         }
11218     }
11219
11220     /* now some housekeeping stuff */
11221     if (aop) {
11222         /* we had to allocate for this iCode */
11223         pic16_freeAsmop(NULL,aop,ic,TRUE);
11224     } else { 
11225         /* we did not allocate which means left
11226            already in a pointer register, then
11227            if size > 0 && this could be used again
11228            we have to point it back to where it 
11229            belongs */
11230         if (AOP_SIZE(result) > 1 &&
11231             !OP_SYMBOL(left)->remat &&
11232             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11233               ic->depth )) {
11234             int size = AOP_SIZE(result) - 1;
11235             while (size--)
11236                 pic16_emitcode("dec","%s",rname);
11237         }
11238     }
11239
11240     /* done */
11241     pic16_freeAsmop(result,NULL,ic,TRUE);
11242     
11243         
11244 }
11245
11246 #if 0
11247 /* This code is not adjusted to PIC16 and fails utterly.
11248  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11249
11250 /*-----------------------------------------------------------------*/
11251 /* genFarPointerGet - gget value from far space                    */
11252 /*-----------------------------------------------------------------*/
11253 static void genFarPointerGet (operand *left,
11254                               operand *result, iCode *ic)
11255 {
11256     int size, offset ;
11257     sym_link *retype = getSpec(operandType(result));
11258
11259     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11260
11261     pic16_aopOp(left,ic,FALSE);
11262
11263     /* if the operand is already in dptr 
11264     then we do nothing else we move the value to dptr */
11265     if (AOP_TYPE(left) != AOP_STR) {
11266         /* if this is remateriazable */
11267         if (AOP_TYPE(left) == AOP_IMMD)
11268             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11269         else { /* we need to get it byte by byte */
11270             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11271             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11272             if (options.model == MODEL_FLAT24)
11273             {
11274                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11275             }
11276         }
11277     }
11278     /* so dptr know contains the address */
11279     pic16_freeAsmop(left,NULL,ic,TRUE);
11280     pic16_aopOp(result,ic,TRUE);
11281
11282     /* if bit then unpack */
11283     if (IS_BITFIELD(retype)) 
11284         genUnpackBits(result,left,"dptr",FPOINTER);
11285     else {
11286         size = AOP_SIZE(result);
11287         offset = 0 ;
11288
11289         while (size--) {
11290             pic16_emitcode("movx","a,@dptr");
11291             pic16_aopPut(AOP(result),"a",offset++);
11292             if (size)
11293                 pic16_emitcode("inc","dptr");
11294         }
11295     }
11296
11297     pic16_freeAsmop(result,NULL,ic,TRUE);
11298 }
11299 #endif
11300
11301 #if 0
11302 /*-----------------------------------------------------------------*/
11303 /* genCodePointerGet - get value from code space                  */
11304 /*-----------------------------------------------------------------*/
11305 static void genCodePointerGet (operand *left,
11306                                 operand *result, iCode *ic)
11307 {
11308     int size, offset ;
11309     sym_link *retype = getSpec(operandType(result));
11310
11311     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11312
11313     pic16_aopOp(left,ic,FALSE);
11314
11315     /* if the operand is already in dptr 
11316     then we do nothing else we move the value to dptr */
11317     if (AOP_TYPE(left) != AOP_STR) {
11318         /* if this is remateriazable */
11319         if (AOP_TYPE(left) == AOP_IMMD)
11320             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11321         else { /* we need to get it byte by byte */
11322             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11323             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11324             if (options.model == MODEL_FLAT24)
11325             {
11326                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11327             }
11328         }
11329     }
11330     /* so dptr know contains the address */
11331     pic16_freeAsmop(left,NULL,ic,TRUE);
11332     pic16_aopOp(result,ic,FALSE);
11333
11334     /* if bit then unpack */
11335     if (IS_BITFIELD(retype)) 
11336         genUnpackBits(result,left,"dptr",CPOINTER);
11337     else {
11338         size = AOP_SIZE(result);
11339         offset = 0 ;
11340
11341         while (size--) {
11342             pic16_emitcode("clr","a");
11343             pic16_emitcode("movc","a,@a+dptr");
11344             pic16_aopPut(AOP(result),"a",offset++);
11345             if (size)
11346                 pic16_emitcode("inc","dptr");
11347         }
11348     }
11349
11350     pic16_freeAsmop(result,NULL,ic,TRUE);
11351 }
11352 #endif
11353
11354 #if 0
11355 /*-----------------------------------------------------------------*/
11356 /* genGenPointerGet - gget value from generic pointer space        */
11357 /*-----------------------------------------------------------------*/
11358 static void genGenPointerGet (operand *left,
11359                               operand *result, iCode *ic)
11360 {
11361   int size, offset, lit;
11362   sym_link *retype = getSpec(operandType(result));
11363
11364         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11365         pic16_aopOp(left,ic,FALSE);
11366         pic16_aopOp(result,ic,FALSE);
11367         size = AOP_SIZE(result);
11368
11369         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11370
11371         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11372
11373                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11374                 // load FSR0 from immediate
11375                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11376
11377 //              pic16_loadFSR0( left );
11378
11379                 offset = 0;
11380                 while(size--) {
11381                         if(size) {
11382                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11383                         } else {
11384                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11385                         }
11386                         offset++;
11387                 }
11388                 goto release;
11389
11390         }
11391         else { /* we need to get it byte by byte */
11392                 // set up FSR0 with address from left
11393                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11394                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11395                 
11396                 offset = 0 ;
11397
11398                 while(size--) {
11399                         if(size) {
11400                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11401                         } else {
11402                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11403                         }
11404                         offset++;
11405                 }
11406                 goto release;
11407         }
11408
11409   /* if bit then unpack */
11410         if (IS_BITFIELD(retype)) 
11411                 genUnpackBits(result,left,"BAD",GPOINTER);
11412
11413         release:
11414         pic16_freeAsmop(left,NULL,ic,TRUE);
11415         pic16_freeAsmop(result,NULL,ic,TRUE);
11416
11417 }
11418 #endif
11419
11420
11421 /*-----------------------------------------------------------------*/
11422 /* genGenPointerGet - gget value from generic pointer space        */
11423 /*-----------------------------------------------------------------*/
11424 static void genGenPointerGet (operand *left,
11425                               operand *result, iCode *ic)
11426 {
11427   int size, offset, lit;
11428   sym_link *letype = getSpec(operandType(left));
11429
11430     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11431     pic16_aopOp(left,ic,FALSE);
11432     pic16_aopOp(result,ic,TRUE);
11433     size = AOP_SIZE(result);
11434
11435     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11436   
11437     /* if bit then unpack */
11438     if (IS_BITFIELD(letype)) {
11439       genUnpackBits(result,left,"BAD",GPOINTER);
11440       goto release;
11441     }
11442
11443     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11444
11445       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11446       // load FSR0 from immediate
11447       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11448
11449       werror(W_POSSBUG2, __FILE__, __LINE__);
11450
11451       offset = 0;
11452       while(size--) {
11453         if(size) {
11454           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11455         } else {
11456           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11457         }
11458         offset++;
11459       }
11460
11461       goto release;
11462
11463     } else { /* we need to get it byte by byte */
11464
11465       /* set up WREG:PRODL:FSR0L with address from left */
11466       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11467       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11468       pic16_mov2w(AOP(left), 2);
11469       pic16_callGenericPointerRW(0, size);
11470       
11471       assignResultValue(result, size, 1);
11472       
11473       goto release;
11474     }
11475
11476 release:
11477   pic16_freeAsmop(left,NULL,ic,TRUE);
11478   pic16_freeAsmop(result,NULL,ic,TRUE);
11479 }
11480
11481 /*-----------------------------------------------------------------*/
11482 /* genConstPointerGet - get value from const generic pointer space */
11483 /*-----------------------------------------------------------------*/
11484 static void genConstPointerGet (operand *left,
11485                                 operand *result, iCode *ic)
11486 {
11487   //sym_link *retype = getSpec(operandType(result));
11488   // symbol *albl = newiTempLabel(NULL);        // patch 15
11489   // symbol *blbl = newiTempLabel(NULL);        //
11490   // PIC_OPCODE poc;                            // patch 15
11491   int size;
11492   int offset = 0;
11493
11494   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11495   pic16_aopOp(left,ic,FALSE);
11496   pic16_aopOp(result,ic,TRUE);
11497   size = AOP_SIZE(result);
11498
11499   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11500
11501   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11502
11503   // set up table pointer
11504   if( (AOP_TYPE(left) == AOP_PCODE) 
11505       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11506           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11507     {
11508       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11509       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11510       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11511       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11512       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11513       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11514   } else {
11515     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11516     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11517     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11518   }
11519
11520   while(size--) {
11521     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11522     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11523     offset++;
11524   }
11525     
11526   pic16_freeAsmop(left,NULL,ic,TRUE);
11527   pic16_freeAsmop(result,NULL,ic,TRUE);
11528 }
11529
11530
11531 /*-----------------------------------------------------------------*/
11532 /* genPointerGet - generate code for pointer get                   */
11533 /*-----------------------------------------------------------------*/
11534 static void genPointerGet (iCode *ic)
11535 {
11536   operand *left, *result ;
11537   sym_link *type, *etype;
11538   int p_type;
11539
11540     FENTRY;
11541     
11542     left = IC_LEFT(ic);
11543     result = IC_RESULT(ic) ;
11544
11545     /* depending on the type of pointer we need to
11546     move it to the correct pointer register */
11547     type = operandType(left);
11548     etype = getSpec(type);
11549
11550 #if 0
11551     if (IS_PTR_CONST(type))
11552 #else
11553     if (IS_CODEPTR(type))
11554 #endif
11555       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11556
11557     /* if left is of type of pointer then it is simple */
11558     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11559       p_type = DCL_TYPE(type);
11560     else {
11561       /* we have to go by the storage class */
11562       p_type = PTR_TYPE(SPEC_OCLS(etype));
11563
11564       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11565
11566       if (SPEC_OCLS(etype)->codesp ) {
11567         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11568         //p_type = CPOINTER ;   
11569       } else
11570       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11571         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11572         /*p_type = FPOINTER ;*/ 
11573       } else
11574       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11575         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11576         /* p_type = PPOINTER; */
11577       } else
11578       if (SPEC_OCLS(etype) == idata ) {
11579         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11580         /* p_type = IPOINTER; */
11581       } else {
11582         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11583         /* p_type = POINTER ; */
11584       }
11585     }
11586
11587     /* now that we have the pointer type we assign
11588     the pointer values */
11589     switch (p_type) {
11590       case POINTER:     
11591       case FPOINTER:
11592       case IPOINTER:
11593         genNearPointerGet (left,result,ic);
11594         break;
11595
11596       case PPOINTER:
11597         genPagedPointerGet(left,result,ic);
11598         break;
11599
11600 #if 0
11601       /* PICs do not support FAR pointers... */
11602       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11603       case FPOINTER:
11604         genFarPointerGet (left,result,ic);
11605         break;
11606 #endif
11607
11608       case CPOINTER:
11609         genConstPointerGet (left,result,ic);
11610         //pic16_emitcodePointerGet (left,result,ic);
11611         break;
11612
11613       case GPOINTER:
11614 #if 0
11615       if (IS_PTR_CONST(type))
11616         genConstPointerGet (left,result,ic);
11617       else
11618 #endif
11619         genGenPointerGet (left,result,ic);
11620       break;
11621
11622     default:
11623       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11624               "genPointerGet: illegal pointer type");
11625     
11626     }
11627 }
11628
11629 /*-----------------------------------------------------------------*/
11630 /* genPackBits - generates code for packed bit storage             */
11631 /*-----------------------------------------------------------------*/
11632 static void genPackBits (sym_link    *etype , operand *result,
11633                          operand *right ,
11634                          char *rname, int p_type)
11635 {
11636   int shCnt = 0 ;
11637   int offset = 0  ;
11638   int rLen = 0 ;
11639   int blen, bstr ;   
11640   int shifted_and_masked = 0;
11641   unsigned long lit = (unsigned long)-1;
11642   sym_link *retype;
11643
11644   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11645   blen = SPEC_BLEN(etype);
11646   bstr = SPEC_BSTR(etype);
11647
11648   retype = getSpec(operandType(right));
11649
11650   if(AOP_TYPE(right) == AOP_LIT) {
11651     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11652     
11653     if((blen == 1) && (bstr < 8)) {
11654       /* it is a single bit, so use the appropriate bit instructions */
11655
11656       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11657
11658       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11659         /* workaround to reduce the extra lfsr instruction */
11660         if(lit) {
11661           pic16_emitpcode(POC_BSF,
11662               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11663         } else {
11664           pic16_emitpcode(POC_BCF,
11665               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11666         }
11667       } else {
11668         if (PIC_IS_DATA_PTR(operandType(result))) {
11669           pic16_loadFSR0(result, 0);
11670           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11671               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11672         } else {
11673           /* get old value */
11674           pic16_derefPtr (result, p_type, 0, NULL);
11675           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11676               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11677           /* write back new value */
11678           pic16_derefPtr (result, p_type, 1, NULL);
11679         }
11680       }
11681
11682       return;
11683     }
11684     /* IORLW below is more efficient */
11685     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11686     lit = (lit & ((1UL << blen) - 1)) << bstr;
11687     shifted_and_masked = 1;
11688     offset++;
11689   } else
11690     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11691         && IS_BITFIELD(retype) 
11692         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11693         && (blen == 1)) {
11694       int rblen, rbstr;
11695
11696       rblen = SPEC_BLEN( retype );
11697       rbstr = SPEC_BSTR( retype );
11698
11699       if(IS_BITFIELD(etype)) {
11700         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11701         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11702       } else {
11703         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11704       }
11705
11706       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11707
11708       if(IS_BITFIELD(etype)) {
11709         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11710       } else {
11711         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11712       }
11713
11714       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11715
11716       return;
11717     } else {
11718       /* move right to W */
11719       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11720     }
11721
11722   /* if the bit length is less than or   */
11723   /* it exactly fits a byte then         */
11724   if((shCnt=SPEC_BSTR(etype))
11725       || SPEC_BLEN(etype) <= 8 )  {
11726     int fsr0_setup = 0;
11727
11728     if (blen != 8 || (bstr % 8) != 0) {
11729       // we need to combine the value with the old value
11730       if(!shifted_and_masked)
11731       {
11732         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11733
11734         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11735             SPEC_BSTR(etype), SPEC_BLEN(etype));
11736
11737         /* shift left acc, do NOT mask the result again */
11738         AccLsh(shCnt, 0);
11739
11740         /* using PRODH as a temporary register here */
11741         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11742       }
11743
11744       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11745         || IS_DIRECT(result)) {
11746         /* access symbol directly */
11747         pic16_mov2w (AOP(result), 0);
11748       } else {
11749         /* get old value */
11750         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11751       }
11752 #if 1
11753       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11754             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11755                             (unsigned char)(0xff >> (8-bstr))) ));
11756       if (!shifted_and_masked) {
11757         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11758       } else {
11759         /* We have the shifted and masked (literal) right value in `lit' */
11760         if (lit != 0)
11761           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11762       }
11763     } else { // if (blen == 8 && (bstr % 8) == 0)
11764         if (shifted_and_masked) {
11765             // move right (literal) to WREG (only case where right is not yet in WREG)
11766             pic16_mov2w(AOP(right), (bstr / 8));
11767         }
11768     }
11769
11770     /* write new value back */
11771     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11772         || IS_DIRECT(result)) {
11773       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11774     } else {
11775       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11776     }
11777 #endif
11778
11779     return;
11780   }
11781
11782
11783 #if 0
11784   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11785   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11786   exit(EXIT_FAILURE);
11787 #endif
11788
11789
11790   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11791   rLen = SPEC_BLEN(etype)-8;
11792
11793   /* now generate for lengths greater than one byte */
11794   while (1) {
11795     rLen -= 8 ;
11796     if (rLen <= 0 ) {
11797       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11798       break ;
11799     }
11800
11801     switch (p_type) {
11802       case POINTER:
11803         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11804         break;
11805
11806         /*
11807            case FPOINTER:
11808            MOVA(l);
11809            pic16_emitcode("movx","@dptr,a");
11810            break;
11811
11812            case GPOINTER:
11813            MOVA(l);
11814            DEBUGpic16_emitcode(";lcall","__gptrput");
11815            break;  
11816          */
11817       default:
11818         assert(0);
11819     }   
11820
11821
11822     pic16_mov2w(AOP(right), offset++);
11823   }
11824
11825   /* last last was not complete */
11826   if (rLen)   {
11827     /* save the byte & read byte */
11828     switch (p_type) {
11829       case POINTER:
11830         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11831         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11832         break;
11833
11834         /*
11835            case FPOINTER:
11836            pic16_emitcode ("mov","b,a");
11837            pic16_emitcode("movx","a,@dptr");
11838            break;
11839
11840            case GPOINTER:
11841            pic16_emitcode ("push","b");
11842            pic16_emitcode ("push","acc");
11843            pic16_emitcode ("lcall","__gptrget");
11844            pic16_emitcode ("pop","b");
11845            break;
11846          */
11847       default:
11848         assert(0);
11849     }
11850     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11851     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11852     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11853     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11854     //        pic16_emitcode ("orl","a,b");
11855   }
11856
11857   //    if (p_type == GPOINTER)
11858   //        pic16_emitcode("pop","b");
11859
11860   switch (p_type) {
11861
11862     case POINTER:
11863       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11864       //        pic16_emitcode("mov","@%s,a",rname);
11865       break;
11866       /*
11867          case FPOINTER:
11868          pic16_emitcode("movx","@dptr,a");
11869          break;
11870
11871          case GPOINTER:
11872          DEBUGpic16_emitcode(";lcall","__gptrput");
11873          break;                 
11874        */
11875     default:
11876       assert(0);
11877   }
11878
11879   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11880 }
11881
11882 /*-----------------------------------------------------------------*/
11883 /* genDataPointerSet - remat pointer to data space                 */
11884 /*-----------------------------------------------------------------*/
11885 static void genDataPointerSet(operand *right,
11886                               operand *result,
11887                               iCode *ic)
11888 {
11889   int size, offset = 0, resoffset=0 ;
11890
11891     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11892     pic16_aopOp(right,ic,FALSE);
11893
11894     size = AOP_SIZE(right);
11895
11896 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11897
11898 #if 0
11899     if ( AOP_TYPE(result) == AOP_PCODE) {
11900       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11901               AOP(result)->aopu.pcop->name,
11902                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11903               PCOR(AOP(result)->aopu.pcop)->instance:
11904               PCOI(AOP(result)->aopu.pcop)->offset);
11905     }
11906 #endif
11907
11908     if(AOP(result)->aopu.pcop->type == PO_DIR)
11909       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11910
11911     while (size--) {
11912       if (AOP_TYPE(right) == AOP_LIT) {
11913         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11914         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11915       } else {
11916         pic16_mov2w(AOP(right), offset);
11917         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11918       }
11919       offset++;
11920       resoffset++;
11921     }
11922
11923     pic16_freeAsmop(right,NULL,ic,TRUE);
11924 }
11925
11926
11927
11928 /*-----------------------------------------------------------------*/
11929 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11930 /*-----------------------------------------------------------------*/
11931 static void genNearPointerSet (operand *right,
11932                                operand *result, 
11933                                iCode *ic)
11934 {
11935   asmop *aop = NULL;
11936   sym_link *retype;
11937   sym_link *ptype = operandType(result);
11938   sym_link *resetype;
11939     
11940     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11941     retype= getSpec(operandType(right));
11942     resetype = getSpec(operandType(result));
11943   
11944     pic16_aopOp(result,ic,FALSE);
11945     
11946     /* if the result is rematerializable &
11947      * in data space & not a bit variable */
11948         
11949     /* and result is not a bit variable */
11950     if (AOP_TYPE(result) == AOP_PCODE
11951 //      && AOP_TYPE(result) == AOP_IMMD
11952       && DCL_TYPE(ptype) == POINTER
11953       && !IS_BITFIELD(retype)
11954       && !IS_BITFIELD(resetype)) {
11955
11956         genDataPointerSet (right,result,ic);
11957         pic16_freeAsmop(result,NULL,ic,TRUE);
11958       return;
11959     }
11960
11961     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11962     pic16_aopOp(right,ic,FALSE);
11963     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11964
11965     /* if bitfield then unpack the bits */
11966     if (IS_BITFIELD(resetype)) {
11967       genPackBits (resetype, result, right, NULL, POINTER);
11968     } else {
11969       /* we have can just get the values */
11970       int size = AOP_SIZE(right);
11971       int offset = 0 ;    
11972
11973         pic16_loadFSR0(result, 0);
11974             
11975         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11976         while (size--) {
11977           if (AOP_TYPE(right) == AOP_LIT) {
11978             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11979             if (size) {
11980               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11981             } else {
11982               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11983             }
11984           } else { // no literal
11985             if(size) {
11986               pic16_emitpcode(POC_MOVFF,
11987                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11988                   pic16_popCopyReg(&pic16_pc_postinc0)));
11989             } else {
11990               pic16_emitpcode(POC_MOVFF,
11991                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11992                   pic16_popCopyReg(&pic16_pc_indf0)));
11993             }
11994           }
11995           
11996           offset++;
11997         }
11998     }
11999
12000     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12001     /* now some housekeeping stuff */
12002     if (aop) {
12003       /* we had to allocate for this iCode */
12004       pic16_freeAsmop(NULL,aop,ic,TRUE);
12005     } else { 
12006       /* we did not allocate which means left
12007        * already in a pointer register, then
12008        * if size > 0 && this could be used again
12009        * we have to point it back to where it 
12010        * belongs */
12011       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12012       if (AOP_SIZE(right) > 1
12013         && !OP_SYMBOL(result)->remat
12014         && ( OP_SYMBOL(result)->liveTo > ic->seq
12015         || ic->depth )) {
12016
12017           int size = AOP_SIZE(right) - 1;
12018
12019             while (size--)
12020               pic16_emitcode("decf","fsr0,f");
12021               //pic16_emitcode("dec","%s",rname);
12022       }
12023     }
12024
12025     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12026     /* done */
12027 //release:
12028     pic16_freeAsmop(right,NULL,ic,TRUE);
12029     pic16_freeAsmop(result,NULL,ic,TRUE);
12030 }
12031
12032 /*-----------------------------------------------------------------*/
12033 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12034 /*-----------------------------------------------------------------*/
12035 static void genPagedPointerSet (operand *right,
12036                                operand *result, 
12037                                iCode *ic)
12038 {
12039     asmop *aop = NULL;
12040     regs *preg = NULL ;
12041     char *rname , *l;
12042     sym_link *retype;
12043        
12044     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12045
12046     retype= getSpec(operandType(right));
12047     
12048     pic16_aopOp(result,ic,FALSE);
12049     
12050     /* if the value is already in a pointer register
12051        then don't need anything more */
12052     if (!AOP_INPREG(AOP(result))) {
12053         /* otherwise get a free pointer register */
12054         aop = newAsmop(0);
12055         preg = getFreePtr(ic,&aop,FALSE);
12056         pic16_emitcode("mov","%s,%s",
12057                 preg->name,
12058                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12059         rname = preg->name ;
12060     } else
12061         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12062     
12063     pic16_freeAsmop(result,NULL,ic,TRUE);
12064     pic16_aopOp (right,ic,FALSE);
12065
12066     /* if bitfield then unpack the bits */
12067     if (IS_BITFIELD(retype)) 
12068         genPackBits (retype,result,right,rname,PPOINTER);
12069     else {
12070         /* we have can just get the values */
12071         int size = AOP_SIZE(right);
12072         int offset = 0 ;        
12073         
12074         while (size--) {
12075             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12076             
12077             MOVA(l);
12078             pic16_emitcode("movx","@%s,a",rname);
12079
12080             if (size)
12081                 pic16_emitcode("inc","%s",rname);
12082
12083             offset++;
12084         }
12085     }
12086     
12087     /* now some housekeeping stuff */
12088     if (aop) {
12089         /* we had to allocate for this iCode */
12090         pic16_freeAsmop(NULL,aop,ic,TRUE);
12091     } else { 
12092         /* we did not allocate which means left
12093            already in a pointer register, then
12094            if size > 0 && this could be used again
12095            we have to point it back to where it 
12096            belongs */
12097         if (AOP_SIZE(right) > 1 &&
12098             !OP_SYMBOL(result)->remat &&
12099             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12100               ic->depth )) {
12101             int size = AOP_SIZE(right) - 1;
12102             while (size--)
12103                 pic16_emitcode("dec","%s",rname);
12104         }
12105     }
12106
12107     /* done */
12108     pic16_freeAsmop(right,NULL,ic,TRUE);
12109     
12110         
12111 }
12112
12113 #if 0
12114 /* This code is not adjusted to PIC16 and fails utterly...
12115  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12116
12117 /*-----------------------------------------------------------------*/
12118 /* genFarPointerSet - set value from far space                     */
12119 /*-----------------------------------------------------------------*/
12120 static void genFarPointerSet (operand *right,
12121                               operand *result, iCode *ic)
12122 {
12123     int size, offset ;
12124     sym_link *retype = getSpec(operandType(right));
12125
12126     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12127     pic16_aopOp(result,ic,FALSE);
12128
12129     /* if the operand is already in dptr 
12130     then we do nothing else we move the value to dptr */
12131     if (AOP_TYPE(result) != AOP_STR) {
12132         /* if this is remateriazable */
12133         if (AOP_TYPE(result) == AOP_IMMD)
12134             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12135         else { /* we need to get it byte by byte */
12136             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12137             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12138             if (options.model == MODEL_FLAT24)
12139             {
12140                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12141             }
12142         }
12143     }
12144     /* so dptr know contains the address */
12145     pic16_freeAsmop(result,NULL,ic,TRUE);
12146     pic16_aopOp(right,ic,FALSE);
12147
12148     /* if bit then unpack */
12149     if (IS_BITFIELD(retype)) 
12150         genPackBits(retype,result,right,"dptr",FPOINTER);
12151     else {
12152         size = AOP_SIZE(right);
12153         offset = 0 ;
12154
12155         while (size--) {
12156             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12157             MOVA(l);
12158             pic16_emitcode("movx","@dptr,a");
12159             if (size)
12160                 pic16_emitcode("inc","dptr");
12161         }
12162     }
12163
12164     pic16_freeAsmop(right,NULL,ic,TRUE);
12165 }
12166 #endif
12167
12168 /*-----------------------------------------------------------------*/
12169 /* genGenPointerSet - set value from generic pointer space         */
12170 /*-----------------------------------------------------------------*/
12171 #if 0
12172 static void genGenPointerSet (operand *right,
12173                               operand *result, iCode *ic)
12174 {
12175         int i, size, offset, lit;
12176         sym_link *retype = getSpec(operandType(right));
12177
12178         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12179
12180         pic16_aopOp(result,ic,FALSE);
12181         pic16_aopOp(right,ic,FALSE);
12182         size = AOP_SIZE(right);
12183         offset = 0;
12184
12185         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12186
12187         /* if the operand is already in dptr 
12188                 then we do nothing else we move the value to dptr */
12189         if (AOP_TYPE(result) != AOP_STR) {
12190                 /* if this is remateriazable */
12191                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12192                 // WARNING: anythig until "else" is untested!
12193                 if (AOP_TYPE(result) == AOP_IMMD) {
12194                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12195                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12196                         // load FSR0 from immediate
12197                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12198                         offset = 0;
12199                         while(size--) {
12200                                 if(size) {
12201                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12202                                 } else {
12203                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12204                                 }
12205                                 offset++;
12206                         }
12207                         goto release;
12208                 }
12209                 else { /* we need to get it byte by byte */
12210                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12211                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12212
12213                         // set up FSR0 with address of result
12214                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12215                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12216
12217                         /* hack hack! see if this the FSR. If so don't load W */
12218                         if(AOP_TYPE(right) != AOP_ACC) {
12219
12220                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12221
12222                                 if(AOP_TYPE(right) == AOP_LIT)
12223                                 {
12224                                         // copy literal
12225                                         // note: pic16_popGet handles sign extension
12226                                         for(i=0;i<size;i++) {
12227                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12228                                                 if(i < size-1)
12229                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12230                                                 else
12231                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12232                                         }
12233                                 } else {
12234                                         // copy regs
12235
12236                                         for(i=0;i<size;i++) {
12237                                                 if(i < size-1)
12238                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12239                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12240                                                 else
12241                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12242                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12243                                         }
12244                                 }
12245                                 goto release;
12246                         } 
12247                         // right = ACC
12248                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12249                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12250                         goto release;
12251         } // if (AOP_TYPE(result) != AOP_IMMD)
12252
12253         } // if (AOP_TYPE(result) != AOP_STR)
12254         /* so dptr know contains the address */
12255
12256
12257         /* if bit then unpack */
12258         if (IS_BITFIELD(retype)) 
12259                 genPackBits(retype,result,right,"dptr",GPOINTER);
12260         else {
12261                 size = AOP_SIZE(right);
12262                 offset = 0 ;
12263
12264                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12265
12266                 // set up FSR0 with address of result
12267                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12268                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12269         
12270                 while (size--) {
12271                         if (AOP_TYPE(right) == AOP_LIT) {
12272                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12273                                 if (size) {
12274                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12275                                 } else {
12276                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12277                                 }
12278                         } else { // no literal
12279                                 if(size) {
12280                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12281                                 } else {
12282                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12283                                 }
12284                         }
12285                         offset++;
12286                 }
12287         }
12288
12289         release:
12290         pic16_freeAsmop(right,NULL,ic,TRUE);
12291         pic16_freeAsmop(result,NULL,ic,TRUE);
12292 }
12293 #endif
12294
12295 static void genGenPointerSet (operand *right,
12296                               operand *result, iCode *ic)
12297 {
12298   int size;
12299   sym_link *retype = getSpec(operandType(result));
12300
12301     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12302
12303     pic16_aopOp(result,ic,FALSE);
12304     pic16_aopOp(right,ic,FALSE);
12305     size = AOP_SIZE(right);
12306
12307     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12308
12309
12310     /* if bit then unpack */
12311     if (IS_BITFIELD(retype)) {
12312 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12313       genPackBits(retype,result,right,"dptr",GPOINTER);
12314       goto release;
12315     }
12316
12317     size = AOP_SIZE(right);
12318
12319     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12320
12321
12322     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12323
12324     /* value of right+0 is placed on stack, which will be retrieved
12325      * by the support function thus restoring the stack. The important
12326      * thing is that there is no need to manually restore stack pointer
12327      * here */
12328     pushaop(AOP(right), 0);
12329 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12330     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12331     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12332     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12333     
12334     /* load address to write to in WREG:FSR0H:FSR0L */
12335     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12336                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12337     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12338                                 pic16_popCopyReg(&pic16_pc_prodl)));
12339     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12340     
12341     pic16_callGenericPointerRW(1, size);
12342
12343 release:
12344     pic16_freeAsmop(right,NULL,ic,TRUE);
12345     pic16_freeAsmop(result,NULL,ic,TRUE);
12346 }
12347
12348 /*-----------------------------------------------------------------*/
12349 /* genPointerSet - stores the value into a pointer location        */
12350 /*-----------------------------------------------------------------*/
12351 static void genPointerSet (iCode *ic)
12352 {    
12353   operand *right, *result ;
12354   sym_link *type, *etype;
12355   int p_type;
12356
12357     FENTRY;
12358
12359     right = IC_RIGHT(ic);
12360     result = IC_RESULT(ic) ;
12361
12362     /* depending on the type of pointer we need to
12363     move it to the correct pointer register */
12364     type = operandType(result);
12365     etype = getSpec(type);
12366     
12367     /* if left is of type of pointer then it is simple */
12368     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12369         p_type = DCL_TYPE(type);
12370     }
12371     else {
12372         /* we have to go by the storage class */
12373         p_type = PTR_TYPE(SPEC_OCLS(etype));
12374
12375 /*      if (SPEC_OCLS(etype)->codesp ) { */
12376 /*          p_type = CPOINTER ;  */
12377 /*      } */
12378 /*      else */
12379 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12380 /*              p_type = FPOINTER ; */
12381 /*          else */
12382 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12383 /*                  p_type = PPOINTER ; */
12384 /*              else */
12385 /*                  if (SPEC_OCLS(etype) == idata ) */
12386 /*                      p_type = IPOINTER ; */
12387 /*                  else */
12388 /*                      p_type = POINTER ; */
12389     }
12390
12391     /* now that we have the pointer type we assign
12392     the pointer values */
12393     switch (p_type) {
12394       case POINTER:
12395       case FPOINTER:
12396       case IPOINTER:
12397         genNearPointerSet (right,result,ic);
12398         break;
12399
12400       case PPOINTER:
12401         genPagedPointerSet (right,result,ic);
12402         break;
12403
12404 #if 0
12405       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12406       case FPOINTER:
12407         genFarPointerSet (right,result,ic);
12408         break;
12409 #endif
12410         
12411       case GPOINTER:
12412         genGenPointerSet (right,result,ic);
12413         break;
12414
12415       default:
12416         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12417           "genPointerSet: illegal pointer type");
12418     }
12419 }
12420
12421 /*-----------------------------------------------------------------*/
12422 /* genIfx - generate code for Ifx statement                        */
12423 /*-----------------------------------------------------------------*/
12424 static void genIfx (iCode *ic, iCode *popIc)
12425 {
12426   operand *cond = IC_COND(ic);
12427   int isbit =0;
12428
12429     FENTRY;
12430
12431     pic16_aopOp(cond,ic,FALSE);
12432
12433     /* get the value into acc */
12434     if (AOP_TYPE(cond) != AOP_CRY)
12435       pic16_toBoolean(cond);
12436     else
12437       isbit = 1;
12438     /* the result is now in the accumulator */
12439     pic16_freeAsmop(cond,NULL,ic,TRUE);
12440
12441     /* if there was something to be popped then do it */
12442     if (popIc)
12443       genIpop(popIc);
12444
12445     /* if the condition is  a bit variable */
12446     if (isbit && IS_ITEMP(cond) && 
12447         SPIL_LOC(cond)) {
12448       genIfxJump(ic,"c");
12449       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12450     } else {
12451       if (isbit && !IS_ITEMP(cond))
12452         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12453         else
12454         genIfxJump(ic,"a");
12455     }
12456     ic->generated = 1;
12457 }
12458
12459 /*-----------------------------------------------------------------*/
12460 /* genAddrOf - generates code for address of                       */
12461 /*-----------------------------------------------------------------*/
12462 static void genAddrOf (iCode *ic)
12463 {
12464   operand *result, *left;
12465   int size;
12466   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12467   pCodeOp *pcop0, *pcop1, *pcop2;
12468
12469     FENTRY;
12470
12471     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12472
12473     sym = OP_SYMBOL( IC_LEFT(ic) );
12474     
12475     if(sym->onStack) {
12476       /* get address of symbol on stack */
12477       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12478 #if 0
12479       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12480                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12481 #endif
12482
12483       // operands on stack are accessible via "FSR2 + index" with index
12484       // starting at 2 for arguments and growing from 0 downwards for
12485       // local variables (index == 0 is not assigned so we add one here)
12486       {
12487         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12488
12489           if (soffs <= 0) {
12490             assert (soffs < 0);
12491             soffs++;
12492           } // if
12493
12494           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12495           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12496           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12497           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12498           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12499           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12500           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12501       }
12502
12503       goto release;
12504     }
12505         
12506 //      if(pic16_debug_verbose) {
12507 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12508 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12509 //      }
12510         
12511     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12512     size = AOP_SIZE(IC_RESULT(ic));
12513
12514     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12515     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12516     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12517         
12518     if (size == 3) {
12519       pic16_emitpcode(POC_MOVLW, pcop0);
12520       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12521       pic16_emitpcode(POC_MOVLW, pcop1);
12522       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12523       pic16_emitpcode(POC_MOVLW, pcop2);
12524       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12525     } else
12526     if (size == 2) {
12527       pic16_emitpcode(POC_MOVLW, pcop0);
12528       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12529       pic16_emitpcode(POC_MOVLW, pcop1);
12530     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12531     } else {
12532       pic16_emitpcode(POC_MOVLW, pcop0);
12533       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12534     }
12535
12536     pic16_freeAsmop(left, NULL, ic, FALSE);
12537 release:
12538     pic16_freeAsmop(result,NULL,ic,TRUE);
12539 }
12540
12541
12542 #if 0
12543 /*-----------------------------------------------------------------*/
12544 /* genFarFarAssign - assignment when both are in far space         */
12545 /*-----------------------------------------------------------------*/
12546 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12547 {
12548     int size = AOP_SIZE(right);
12549     int offset = 0;
12550     char *l ;
12551     /* first push the right side on to the stack */
12552     while (size--) {
12553         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12554         MOVA(l);
12555         pic16_emitcode ("push","acc");
12556     }
12557     
12558     pic16_freeAsmop(right,NULL,ic,FALSE);
12559     /* now assign DPTR to result */
12560     pic16_aopOp(result,ic,FALSE);
12561     size = AOP_SIZE(result);
12562     while (size--) {
12563         pic16_emitcode ("pop","acc");
12564         pic16_aopPut(AOP(result),"a",--offset);
12565     }
12566     pic16_freeAsmop(result,NULL,ic,FALSE);
12567         
12568 }
12569 #endif
12570
12571 /*-----------------------------------------------------------------*/
12572 /* genAssign - generate code for assignment                        */
12573 /*-----------------------------------------------------------------*/
12574 static void genAssign (iCode *ic)
12575 {
12576   operand *result, *right;
12577   sym_link *restype, *rtype;
12578   int size, offset,know_W;
12579   unsigned long lit = 0L;
12580
12581     result = IC_RESULT(ic);
12582     right  = IC_RIGHT(ic) ;
12583
12584     FENTRY;
12585   
12586     /* if they are the same */
12587     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12588       return ;
12589
12590     /* reversed order operands are aopOp'ed so that result operand
12591      * is effective in case right is a stack symbol. This maneauver
12592      * allows to use the _G.resDirect flag later */
12593      pic16_aopOp(result,ic,TRUE);
12594     pic16_aopOp(right,ic,FALSE);
12595
12596     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12597
12598     /* if they are the same registers */
12599     if (pic16_sameRegs(AOP(right),AOP(result)))
12600       goto release;
12601
12602     /* if the result is a bit */
12603     if (AOP_TYPE(result) == AOP_CRY) {
12604       /* if the right size is a literal then
12605          we know what the value is */
12606       if (AOP_TYPE(right) == AOP_LIT) {
12607           
12608         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12609             pic16_popGet(AOP(result),0));
12610
12611         if (((int) operandLitValue(right))) 
12612           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12613               AOP(result)->aopu.aop_dir,
12614               AOP(result)->aopu.aop_dir);
12615         else
12616           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12617               AOP(result)->aopu.aop_dir,
12618               AOP(result)->aopu.aop_dir);
12619         
12620         goto release;
12621       }
12622
12623       /* the right is also a bit variable */
12624       if (AOP_TYPE(right) == AOP_CRY) {
12625         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12626         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12627         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12628
12629         goto release ;
12630       }
12631
12632       /* we need to or */
12633       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12634       pic16_toBoolean(right);
12635       emitSKPZ;
12636       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12637       //pic16_aopPut(AOP(result),"a",0);
12638       goto release ;
12639     }
12640
12641     /* bit variables done */
12642     /* general case */
12643     size = AOP_SIZE(result);
12644     offset = 0 ;
12645
12646   /* bit variables done */
12647   /* general case */
12648   size = AOP_SIZE(result);
12649   restype = operandType(result);
12650   rtype = operandType(right);
12651   offset = 0 ;
12652
12653   if(AOP_TYPE(right) == AOP_LIT) {
12654     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12655     {
12656       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12657
12658       /* patch tag for literals that are cast to pointers */
12659       if (IS_CODEPTR(restype)) {
12660         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12661         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12662       } else {
12663         if (IS_GENPTR(restype))
12664         {
12665           if (IS_CODEPTR(rtype)) {
12666             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12667             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12668           } else if (PIC_IS_DATA_PTR(rtype)) {
12669             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12670             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12671           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12672             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12673           } else if (IS_PTR(rtype)) {
12674             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12675             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12676           }
12677         }
12678       }
12679     } else {
12680       union {
12681         unsigned long lit_int;
12682         float lit_float;
12683       } info;
12684
12685
12686       if(IS_FIXED16X16(operandType(right))) {
12687         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12688       } else {
12689         /* take care if literal is a float */
12690         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12691         lit = info.lit_int;
12692       }
12693     }
12694   }
12695
12696 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12697 //                      sizeof(unsigned long int), sizeof(float));
12698
12699
12700     if (AOP_TYPE(right) == AOP_REG) {
12701       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12702       while (size--) {
12703         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12704       } // while
12705       goto release;
12706     }
12707
12708     /* when do we have to read the program memory?
12709      * - if right itself is a symbol in code space
12710      *   (we don't care what it points to if it's a pointer)
12711      * - AND right is not a function (we would want its address)
12712      */
12713     if(AOP_TYPE(right) != AOP_LIT
12714       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12715       && !IS_FUNC(OP_SYM_TYPE(right))
12716       && !IS_ITEMP(right)) {
12717
12718       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12719       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12720       
12721       // set up table pointer
12722       if(is_LitOp(right)) {
12723 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12724         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12725         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12726         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12727         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12728         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12729         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12730       } else {
12731 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12732         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12733             pic16_popCopyReg(&pic16_pc_tblptrl)));
12734         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12735             pic16_popCopyReg(&pic16_pc_tblptrh)));
12736         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12737             pic16_popCopyReg(&pic16_pc_tblptru)));
12738       }
12739
12740       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12741       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12742       while(size--) {
12743         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12744         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12745             pic16_popGet(AOP(result),offset)));
12746         offset++;
12747       }
12748
12749       /* FIXME: for pointers we need to extend differently (according
12750        * to pointer type DATA/CODE/EEPROM/... :*/
12751       size = getSize(OP_SYM_TYPE(right));
12752       if(AOP_SIZE(result) > size) {
12753         size = AOP_SIZE(result) - size;
12754         while(size--) {
12755           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12756           offset++;
12757         }
12758       }
12759       goto release;
12760     }
12761
12762 #if 0
12763     /* VR - What is this?! */
12764     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12765       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12766       
12767       if(aopIdx(AOP(result),0) == 4) {
12768         /* this is a workaround to save value of right into wreg too,
12769          * value of wreg is going to be used later */
12770         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12771         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12772         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12773         goto release;
12774       } else
12775 //      assert(0);
12776       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12777     }
12778 #endif
12779
12780     size = AOP_SIZE(right);
12781     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12782     know_W=-1;
12783     while (size--) {
12784       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12785       if(AOP_TYPE(right) == AOP_LIT) {
12786         if(lit&0xff) {
12787           if(know_W != (lit&0xff))
12788             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12789           know_W = lit&0xff;
12790           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12791         } else
12792           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12793
12794         lit >>= 8;
12795
12796       } else if (AOP_TYPE(right) == AOP_CRY) {
12797         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12798         if(offset == 0) {
12799           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12800           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12801           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12802         }
12803       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12804         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12805         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12806       } else {
12807         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12808
12809         if(!_G.resDirect) {                                             /* use this aopForSym feature */
12810           if(AOP_TYPE(result) == AOP_ACC) {
12811             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12812           } else
12813             if(AOP_TYPE(right) == AOP_ACC) {
12814               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12815             } else {
12816               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12817             }
12818         }
12819       }
12820
12821       offset++;
12822     }
12823     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12824   
12825 release:
12826   pic16_freeAsmop (right,NULL,ic,FALSE);
12827   pic16_freeAsmop (result,NULL,ic,TRUE);
12828
12829
12830 /*-----------------------------------------------------------------*/
12831 /* genJumpTab - generates code for jump table                       */
12832 /*-----------------------------------------------------------------*/
12833 static void genJumpTab (iCode *ic)
12834 {
12835   symbol *jtab;
12836   char *l;
12837   pCodeOp *jt_offs;
12838   pCodeOp *jt_offs_hi;
12839   pCodeOp *jt_label;
12840
12841     FENTRY;
12842
12843     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12844     /* get the condition into accumulator */
12845     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12846     MOVA(l);
12847     /* multiply by three */
12848     pic16_emitcode("add","a,acc");
12849     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12850
12851     jtab = newiTempLabel(NULL);
12852     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12853     pic16_emitcode("jmp","@a+dptr");
12854     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12855
12856 #if 0
12857     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12858     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12859     emitSKPNC;
12860     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12861     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12862     pic16_emitpLabel(jtab->key);
12863
12864 #else
12865
12866     jt_offs = pic16_popGetTempReg(0);
12867     jt_offs_hi = pic16_popGetTempReg(1);
12868     jt_label = pic16_popGetLabel (jtab->key);
12869     //fprintf (stderr, "Creating jump table...\n");
12870
12871     // calculate offset into jump table (idx * sizeof (GOTO))
12872     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12873     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12874     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12875     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12876     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12877     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12878     pic16_emitpcode(POC_MOVWF , jt_offs);
12879
12880     // prepare PCLATx (set to first entry in jump table)
12881     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12882     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12883     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12884     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12885     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12886
12887     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12888     pic16_emitpcode(POC_ADDWF , jt_offs);
12889     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12890     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12891     emitSKPNC;
12892     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12893
12894     // release temporaries and prepare jump into table (new PCL --> WREG)
12895     pic16_emitpcode(POC_MOVFW , jt_offs);
12896     pic16_popReleaseTempReg (jt_offs_hi, 1);
12897     pic16_popReleaseTempReg (jt_offs, 0);
12898
12899     // jump into the table
12900     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12901
12902     pic16_emitpLabelFORCE(jtab->key);
12903 #endif
12904
12905     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12906 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12907
12908     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12909     /* now generate the jump labels */
12910     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12911          jtab = setNextItem(IC_JTLABELS(ic))) {
12912 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12913         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12914         
12915     }
12916     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12917
12918 }
12919
12920 /*-----------------------------------------------------------------*/
12921 /* genMixedOperation - gen code for operators between mixed types  */
12922 /*-----------------------------------------------------------------*/
12923 /*
12924   TSD - Written for the PIC port - but this unfortunately is buggy.
12925   This routine is good in that it is able to efficiently promote 
12926   types to different (larger) sizes. Unfortunately, the temporary
12927   variables that are optimized out by this routine are sometimes
12928   used in other places. So until I know how to really parse the 
12929   iCode tree, I'm going to not be using this routine :(.
12930 */
12931 static int genMixedOperation (iCode *ic)
12932 {
12933 #if 0
12934   operand *result = IC_RESULT(ic);
12935   sym_link *ctype = operandType(IC_LEFT(ic));
12936   operand *right = IC_RIGHT(ic);
12937   int ret = 0;
12938   int big,small;
12939   int offset;
12940
12941   iCode *nextic;
12942   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12943
12944   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12945
12946   nextic = ic->next;
12947   if(!nextic)
12948     return 0;
12949
12950   nextright = IC_RIGHT(nextic);
12951   nextleft  = IC_LEFT(nextic);
12952   nextresult = IC_RESULT(nextic);
12953
12954   pic16_aopOp(right,ic,FALSE);
12955   pic16_aopOp(result,ic,FALSE);
12956   pic16_aopOp(nextright,  nextic, FALSE);
12957   pic16_aopOp(nextleft,   nextic, FALSE);
12958   pic16_aopOp(nextresult, nextic, FALSE);
12959
12960   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12961
12962     operand *t = right;
12963     right = nextright;
12964     nextright = t; 
12965
12966     pic16_emitcode(";remove right +","");
12967
12968   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12969 /*
12970     operand *t = right;
12971     right = nextleft;
12972     nextleft = t; 
12973 */
12974     pic16_emitcode(";remove left +","");
12975   } else
12976     return 0;
12977
12978   big = AOP_SIZE(nextleft);
12979   small = AOP_SIZE(nextright);
12980
12981   switch(nextic->op) {
12982
12983   case '+':
12984     pic16_emitcode(";optimize a +","");
12985     /* if unsigned or not an integral type */
12986     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12987       pic16_emitcode(";add a bit to something","");
12988     } else {
12989
12990       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12991
12992       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12993         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12994         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12995       } else
12996         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12997
12998       offset = 0;
12999       while(--big) {
13000
13001         offset++;
13002
13003         if(--small) {
13004           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13005             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13006             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13007           }
13008
13009           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13010           emitSKPNC;
13011           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13012                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13013                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13014           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13015           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13016
13017         } else {
13018           pic16_emitcode("rlf","known_zero,w");
13019
13020           /*
13021             if right is signed
13022               btfsc  right,7
13023                addlw ff
13024           */
13025           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13026             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13027             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13028           } else {
13029             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13030           }
13031         }
13032       }
13033       ret = 1;
13034     }
13035   }
13036   ret = 1;
13037
13038 release:
13039   pic16_freeAsmop(right,NULL,ic,TRUE);
13040   pic16_freeAsmop(result,NULL,ic,TRUE);
13041   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13042   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13043   if(ret)
13044     nextic->generated = 1;
13045
13046   return ret;
13047 #else
13048   return 0;
13049 #endif
13050 }
13051 /*-----------------------------------------------------------------*/
13052 /* genCast - gen code for casting                                  */
13053 /*-----------------------------------------------------------------*/
13054 static void genCast (iCode *ic)
13055 {
13056   operand *result = IC_RESULT(ic);
13057   sym_link *ctype = operandType(IC_LEFT(ic));
13058   sym_link *rtype = operandType(IC_RIGHT(ic));
13059   sym_link *restype = operandType(IC_RESULT(ic));
13060   operand *right = IC_RIGHT(ic);
13061   int size, offset ;
13062
13063
13064     FENTRY;
13065
13066         /* if they are equivalent then do nothing */
13067 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13068 //              return ;
13069
13070         pic16_aopOp(result,ic,FALSE);
13071         pic16_aopOp(right,ic,FALSE) ;
13072
13073         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13074
13075
13076         /* if the result is a bit */
13077         if (AOP_TYPE(result) == AOP_CRY) {
13078         
13079                 /* if the right size is a literal then
13080                  * we know what the value is */
13081                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13082
13083                 if (AOP_TYPE(right) == AOP_LIT) {
13084                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13085                                 pic16_popGet(AOP(result),0));
13086
13087                         if (((int) operandLitValue(right))) 
13088                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13089                                         AOP(result)->aopu.aop_dir,
13090                                         AOP(result)->aopu.aop_dir);
13091                         else
13092                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13093                                         AOP(result)->aopu.aop_dir,
13094                                         AOP(result)->aopu.aop_dir);
13095                         goto release;
13096                 }
13097
13098                 /* the right is also a bit variable */
13099                 if (AOP_TYPE(right) == AOP_CRY) {
13100                         emitCLRC;
13101                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13102
13103                         pic16_emitcode("clrc","");
13104                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13105                                 AOP(right)->aopu.aop_dir,
13106                                 AOP(right)->aopu.aop_dir);
13107                         pic16_aopPut(AOP(result),"c",0);
13108                         goto release ;
13109                 }
13110
13111                 /* we need to or */
13112                 if (AOP_TYPE(right) == AOP_REG) {
13113                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13114                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13115                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13116                 }
13117                 pic16_toBoolean(right);
13118                 pic16_aopPut(AOP(result),"a",0);
13119                 goto release ;
13120         }
13121
13122         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13123           int offset = 1;
13124
13125                 size = AOP_SIZE(result);
13126
13127                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13128
13129                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13130                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13131                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13132
13133                 while (size--)
13134                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13135
13136                 goto release;
13137         }
13138
13139         if(IS_BITFIELD(getSpec(restype))
13140           && IS_BITFIELD(getSpec(rtype))) {
13141           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13142         }
13143         
13144         /* port from pic14 to cope with generic pointers */
13145         if (PIC_IS_TAGGED(restype))
13146         {
13147           operand *result = IC_RESULT(ic);
13148           //operand *left = IC_LEFT(ic);
13149           operand *right = IC_RIGHT(ic);
13150           int tag = 0xff;
13151
13152           /* copy common part */
13153           int max, size = AOP_SIZE(result);
13154           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13155           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13156
13157           max = size;
13158           while (size--)
13159           {
13160             pic16_mov2w (AOP(right), size);
13161             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13162           } // while
13163
13164           /* upcast into generic pointer type? */
13165           if (IS_GENPTR(restype)
13166               && !PIC_IS_TAGGED(rtype)
13167               && (AOP_SIZE(result) > max))
13168           {
13169             /* determine appropriate tag for right */
13170             if (PIC_IS_DATA_PTR(rtype))
13171               tag = GPTR_TAG_DATA;
13172             else if (IS_CODEPTR(rtype))
13173               tag = GPTR_TAG_CODE;
13174             else if (PIC_IS_DATA_PTR(ctype)) {
13175               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13176               tag = GPTR_TAG_DATA;
13177             } else if (IS_CODEPTR(ctype)) {
13178               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13179               tag = GPTR_TAG_CODE;
13180             } else if (IS_PTR(rtype)) {
13181               PERFORM_ONCE(weirdcast,
13182               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
13183               );
13184               tag = GPTR_TAG_DATA;
13185             } else {
13186               PERFORM_ONCE(weirdcast,
13187               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
13188               );
13189               tag = GPTR_TAG_DATA;
13190             }
13191
13192             assert (AOP_SIZE(result) == 3);
13193             /* zero-extend address... */
13194             for (size = max; size < AOP_SIZE(result)-1; size++)
13195               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13196             /* ...and add tag */
13197             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13198           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13199             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13200             for (size = max; size < AOP_SIZE(result)-1; size++)
13201               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13202             /* add __code tag */
13203             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13204           } else if (AOP_SIZE(result) > max) {
13205             /* extend non-pointers */
13206             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13207             pic16_addSign(result, max, 0);
13208           } // if
13209           goto release;
13210         }
13211
13212         /* if they are the same size : or less */
13213         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13214
13215                 /* if they are in the same place */
13216                 if (pic16_sameRegs(AOP(right),AOP(result)))
13217                         goto release;
13218
13219                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13220 #if 0
13221                 if (IS_PTR_CONST(rtype))
13222 #else
13223                 if (IS_CODEPTR(rtype))
13224 #endif
13225                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13226
13227 #if 0
13228                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13229 #else
13230                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13231 #endif
13232                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13233
13234 #if 0
13235                 if(AOP_TYPE(right) == AOP_IMMD) {
13236                   pCodeOp *pcop0, *pcop1, *pcop2;
13237                   symbol *sym = OP_SYMBOL( right );
13238
13239                         size = AOP_SIZE(result);
13240                         /* low */
13241                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13242                         /* high */
13243                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13244                         /* upper */
13245                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13246         
13247                         if (size == 3) {
13248                                 pic16_emitpcode(POC_MOVLW, pcop0);
13249                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13250                                 pic16_emitpcode(POC_MOVLW, pcop1);
13251                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13252                                 pic16_emitpcode(POC_MOVLW, pcop2);
13253                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13254                         } else
13255                         if (size == 2) {
13256                                 pic16_emitpcode(POC_MOVLW, pcop0);
13257                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13258                                 pic16_emitpcode(POC_MOVLW, pcop1);
13259                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13260                         } else {
13261                                 pic16_emitpcode(POC_MOVLW, pcop0);
13262                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13263                         }
13264                 } else
13265 #endif
13266                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13267                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13268                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13269
13270                         if(AOP_SIZE(result) < 2) {
13271                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13272                         } else {
13273                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13274                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13275                         }
13276                 } else {
13277                         /* if they in different places then copy */
13278                         size = AOP_SIZE(result);
13279                         offset = 0 ;
13280                         while (size--) {
13281                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13282                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13283                                 offset++;
13284                         }
13285                 }
13286                 goto release;
13287         }
13288
13289         /* if the result is of type pointer */
13290         if (IS_PTR(ctype)) {
13291           int p_type;
13292           sym_link *type = operandType(right);
13293           sym_link *etype = getSpec(type);
13294
13295                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13296
13297                 /* pointer to generic pointer */
13298                 if (IS_GENPTR(ctype)) {
13299                   char *l = zero;
13300             
13301                         if (IS_PTR(type)) 
13302                                 p_type = DCL_TYPE(type);
13303                         else {
13304                 /* we have to go by the storage class */
13305                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13306
13307 /*              if (SPEC_OCLS(etype)->codesp )  */
13308 /*                  p_type = CPOINTER ;  */
13309 /*              else */
13310 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13311 /*                      p_type = FPOINTER ; */
13312 /*                  else */
13313 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13314 /*                          p_type = PPOINTER; */
13315 /*                      else */
13316 /*                          if (SPEC_OCLS(etype) == idata ) */
13317 /*                              p_type = IPOINTER ; */
13318 /*                          else */
13319 /*                              p_type = POINTER ; */
13320             }
13321                 
13322             /* the first two bytes are known */
13323       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13324             size = GPTRSIZE - 1; 
13325             offset = 0 ;
13326             while (size--) {
13327               if(offset < AOP_SIZE(right)) {
13328                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13329                 pic16_mov2f(AOP(result), AOP(right), offset);
13330 /*
13331                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13332                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13333                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13334                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13335                 } else { 
13336                   
13337                   pic16_aopPut(AOP(result),
13338                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13339                          offset);
13340                 }
13341 */
13342               } else 
13343                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13344               offset++;
13345             }
13346             /* the last byte depending on type */
13347             switch (p_type) {
13348             case IPOINTER:
13349             case POINTER:
13350             case FPOINTER:
13351                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13352                 break;
13353
13354             case CPOINTER:
13355                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13356                 break;
13357
13358             case PPOINTER:
13359               pic16_emitcode(";BUG!? ","%d",__LINE__);
13360                 l = "#0x03";
13361                 break;
13362
13363             case GPOINTER:
13364                 if (GPTRSIZE > AOP_SIZE(right)) {
13365                   // assume __data pointer... THIS MIGHT BE WRONG!
13366                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13367                 } else {
13368                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13369                 }
13370               break;
13371               
13372             default:
13373                 /* this should never happen */
13374                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13375                        "got unknown pointer type");
13376                 exit(1);
13377             }
13378             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13379             goto release ;
13380         }
13381         
13382         
13383         assert( 0 );
13384         /* just copy the pointers */
13385         size = AOP_SIZE(result);
13386         offset = 0 ;
13387         while (size--) {
13388             pic16_aopPut(AOP(result),
13389                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13390                    offset);
13391             offset++;
13392         }
13393         goto release ;
13394     }
13395     
13396
13397
13398     /* so we now know that the size of destination is greater
13399     than the size of the source.
13400     Now, if the next iCode is an operator then we might be
13401     able to optimize the operation without performing a cast.
13402     */
13403     if(genMixedOperation(ic))
13404       goto release;
13405
13406     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13407     
13408     /* we move to result for the size of source */
13409     size = AOP_SIZE(right);
13410     offset = 0 ;
13411
13412     while (size--) {
13413       if(!_G.resDirect)
13414         pic16_mov2f(AOP(result), AOP(right), offset);
13415       offset++;
13416     }
13417
13418     /* now depending on the sign of the destination */
13419     size = AOP_SIZE(result) - AOP_SIZE(right);
13420     /* if unsigned or not an integral type */
13421     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13422       while (size--)
13423         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13424     } else {
13425       /* we need to extend the sign :( */
13426
13427       if(size == 1) {
13428         /* Save one instruction of casting char to int */
13429         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13430         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13431         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13432       } else {
13433         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13434
13435         if(offset)
13436           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13437         else
13438           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13439         
13440         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13441
13442         while (size--)
13443           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13444       }
13445     }
13446
13447 release:
13448     pic16_freeAsmop(right,NULL,ic,TRUE);
13449     pic16_freeAsmop(result,NULL,ic,TRUE);
13450
13451 }
13452
13453 /*-----------------------------------------------------------------*/
13454 /* genDjnz - generate decrement & jump if not zero instrucion      */
13455 /*-----------------------------------------------------------------*/
13456 static int genDjnz (iCode *ic, iCode *ifx)
13457 {
13458     symbol *lbl, *lbl1;
13459     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13460
13461     if (!ifx)
13462         return 0;
13463     
13464     /* if the if condition has a false label
13465        then we cannot save */
13466     if (IC_FALSE(ifx))
13467         return 0;
13468
13469     /* if the minus is not of the form 
13470        a = a - 1 */
13471     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13472         !IS_OP_LITERAL(IC_RIGHT(ic)))
13473         return 0;
13474
13475     if (operandLitValue(IC_RIGHT(ic)) != 1)
13476         return 0;
13477
13478     /* if the size of this greater than one then no
13479        saving */
13480     if (getSize(operandType(IC_RESULT(ic))) > 1)
13481         return 0;
13482
13483     /* otherwise we can save BIG */
13484     lbl = newiTempLabel(NULL);
13485     lbl1= newiTempLabel(NULL);
13486
13487     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13488     
13489     if (IS_AOP_PREG(IC_RESULT(ic))) {
13490         pic16_emitcode("dec","%s",
13491                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13492         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13493         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13494     } else {    
13495
13496
13497       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13498       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13499
13500       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13501       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13502
13503     }
13504     
13505     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13506     ifx->generated = 1;
13507     return 1;
13508 }
13509
13510 /*-----------------------------------------------------------------*/
13511 /* genReceive - generate code for a receive iCode                  */
13512 /*-----------------------------------------------------------------*/
13513 static void genReceive (iCode *ic)
13514 {    
13515
13516   FENTRY;
13517
13518 #if 0
13519   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13520         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13521 #endif
13522 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13523
13524   if (isOperandInFarSpace(IC_RESULT(ic))
13525       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13526           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13527
13528     int size = getSize(operandType(IC_RESULT(ic)));
13529     int offset =  pic16_fReturnSizePic - size;
13530
13531       assert( 0 );
13532       while (size--) {
13533         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13534                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13535                       offset++;
13536         }
13537
13538       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13539
13540       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13541       size = AOP_SIZE(IC_RESULT(ic));
13542       offset = 0;
13543       while (size--) {
13544         pic16_emitcode ("pop","acc");
13545         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13546       }
13547   } else {
13548     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13549     _G.accInUse++;
13550     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13551     _G.accInUse--;
13552
13553     /* set pseudo stack pointer to where it should be - dw*/
13554     GpsuedoStkPtr = ic->parmBytes;
13555
13556     /* setting GpsuedoStkPtr has side effects here: */
13557     /* FIXME: What's the correct size of the return(ed) value?
13558      *        For now, assuming '4' as before... */
13559     assignResultValue(IC_RESULT(ic), 4, 0);
13560   }
13561
13562   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13563 }
13564
13565 /*-----------------------------------------------------------------*/
13566 /* genDummyRead - generate code for dummy read of volatiles        */
13567 /*-----------------------------------------------------------------*/
13568 static void
13569 genDummyRead (iCode * ic)
13570 {
13571   operand *op;
13572   int i;
13573
13574   op = IC_RIGHT(ic);
13575   if (op && IS_SYMOP(op)) {
13576     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13577       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13578       return;
13579     }
13580     pic16_aopOp (op, ic, FALSE);
13581     for (i=0; i < AOP_SIZE(op); i++) {
13582       // may need to protect this from the peepholer -- this is not nice but works...
13583       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13584       pic16_mov2w (AOP(op),i);
13585       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13586     } // for i
13587     pic16_freeAsmop (op, NULL, ic, TRUE);
13588   } else if (op) {
13589     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13590   } // if
13591 }
13592
13593 /*-----------------------------------------------------------------*/
13594 /* genpic16Code - generate code for pic16 based controllers        */
13595 /*-----------------------------------------------------------------*/
13596 /*
13597  * At this point, ralloc.c has gone through the iCode and attempted
13598  * to optimize in a way suitable for a PIC. Now we've got to generate
13599  * PIC instructions that correspond to the iCode.
13600  *
13601  * Once the instructions are generated, we'll pass through both the
13602  * peep hole optimizer and the pCode optimizer.
13603  *-----------------------------------------------------------------*/
13604
13605 void genpic16Code (iCode *lic)
13606 {
13607   iCode *ic;
13608   int cln = 0;
13609
13610     lineHead = lineCurr = NULL;
13611
13612     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13613     pic16_addpBlock(pb);
13614
13615 #if 0
13616     /* if debug information required */
13617     if (options.debug && currFunc) {
13618       if (currFunc) {
13619         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13620       }
13621     }
13622 #endif
13623
13624     for (ic = lic ; ic ; ic = ic->next ) {
13625
13626       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13627       if ( cln != ic->lineno ) {
13628         if ( options.debug ) {
13629           debugFile->writeCLine (ic);
13630         }
13631         
13632         if(!options.noCcodeInAsm) {
13633           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13634               printCLine(ic->filename, ic->lineno)));
13635         }
13636
13637         cln = ic->lineno ;
13638       }
13639         
13640       if(options.iCodeInAsm) {
13641         char *l;
13642
13643           /* insert here code to print iCode as comment */
13644           l = Safe_strdup(printILine(ic));
13645           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13646       }
13647
13648       /* if the result is marked as
13649        * spilt and rematerializable or code for
13650        * this has already been generated then
13651        * do nothing */
13652       if (resultRemat(ic) || ic->generated ) 
13653         continue ;
13654         
13655       /* depending on the operation */
13656       switch (ic->op) {
13657         case '!' :
13658           pic16_genNot(ic);
13659           break;
13660             
13661         case '~' :
13662           pic16_genCpl(ic);
13663           break;
13664             
13665         case UNARYMINUS:
13666           genUminus (ic);
13667           break;
13668             
13669         case IPUSH:
13670           genIpush (ic);
13671           break;
13672             
13673         case IPOP:
13674           /* IPOP happens only when trying to restore a 
13675            * spilt live range, if there is an ifx statement
13676            * following this pop then the if statement might
13677            * be using some of the registers being popped which
13678            * would destroy the contents of the register so
13679            * we need to check for this condition and handle it */
13680            if (ic->next
13681              && ic->next->op == IFX
13682              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13683                genIfx (ic->next,ic);
13684           else
13685             genIpop (ic);
13686           break; 
13687             
13688         case CALL:
13689           genCall (ic);
13690           break;
13691             
13692         case PCALL:
13693           genPcall (ic);
13694           break;
13695             
13696         case FUNCTION:
13697           genFunction (ic);
13698           break;
13699             
13700         case ENDFUNCTION:
13701           genEndFunction (ic);
13702           break;
13703             
13704         case RETURN:
13705           genRet (ic);
13706           break;
13707             
13708         case LABEL:
13709           genLabel (ic);
13710           break;
13711             
13712         case GOTO:
13713           genGoto (ic);
13714           break;
13715             
13716         case '+' :
13717           pic16_genPlus (ic) ;
13718           break;
13719             
13720         case '-' :
13721           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13722             pic16_genMinus (ic);
13723           break;
13724
13725         case '*' :
13726           genMult (ic);
13727           break;
13728             
13729         case '/' :
13730           genDiv (ic) ;
13731           break;
13732             
13733         case '%' :
13734           genMod (ic);
13735           break;
13736             
13737         case '>' :
13738           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13739           break;
13740             
13741         case '<' :
13742           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13743           break;
13744             
13745         case LE_OP:
13746         case GE_OP:
13747         case NE_OP:
13748           /* note these two are xlated by algebraic equivalence
13749            * during parsing SDCC.y */
13750           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13751             "got '>=' or '<=' shouldn't have come here");
13752           break;
13753
13754         case EQ_OP:
13755           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13756           break;            
13757             
13758         case AND_OP:
13759           genAndOp (ic);
13760           break;
13761             
13762         case OR_OP:
13763           genOrOp (ic);
13764           break;
13765             
13766         case '^' :
13767           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13768           break;
13769             
13770         case '|' :
13771           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13772           break;
13773             
13774         case BITWISEAND:
13775           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13776           break;
13777             
13778         case INLINEASM:
13779           genInline (ic);
13780           break;
13781             
13782         case RRC:
13783           genRRC (ic);
13784           break;
13785             
13786         case RLC:
13787           genRLC (ic);
13788           break;
13789             
13790         case GETHBIT:
13791           genGetHbit (ic);
13792           break;
13793             
13794         case LEFT_OP:
13795           genLeftShift (ic);
13796           break;
13797             
13798         case RIGHT_OP:
13799           genRightShift (ic);
13800           break;
13801             
13802         case GET_VALUE_AT_ADDRESS:
13803           genPointerGet(ic);
13804           break;
13805             
13806         case '=' :
13807           if (POINTER_SET(ic))
13808             genPointerSet(ic);
13809           else
13810             genAssign(ic);
13811           break;
13812             
13813         case IFX:
13814           genIfx (ic,NULL);
13815           break;
13816             
13817         case ADDRESS_OF:
13818           genAddrOf (ic);
13819           break;
13820             
13821         case JUMPTABLE:
13822           genJumpTab (ic);
13823           break;
13824             
13825         case CAST:
13826           genCast (ic);
13827           break;
13828             
13829         case RECEIVE:
13830           genReceive(ic);
13831           break;
13832             
13833         case SEND:
13834           addSet(&_G.sendSet,ic);
13835           break;
13836
13837         case DUMMY_READ_VOLATILE:
13838           genDummyRead (ic);
13839           break;
13840
13841         default :
13842           ic = ic;
13843       }
13844     }
13845
13846
13847     /* now we are ready to call the
13848        peep hole optimizer */
13849     if (!options.nopeep)
13850       peepHole (&lineHead);
13851
13852     /* now do the actual printing */
13853     printLine (lineHead, codeOutFile);
13854
13855 #ifdef PCODE_DEBUG
13856     DFPRINTF((stderr,"printing pBlock\n\n"));
13857     pic16_printpBlock(stdout,pb);
13858 #endif
13859
13860     return;
13861 }
13862