* sim/ucsim/cmd.src/cmdutil.cc: NUL device is detected as CG_FILE type
[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 struct dbuf_s *codeOutBuf;
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 //              chat *iLine = printILine(ic);
959 //              pic16_emitpcomment("ic: %s\n", iLine);
960 //              dbuf_free(iLine);
961         
962                 if (ic->op == '+') {
963                         val += (int) operandLitValue(IC_RIGHT(ic));
964                 } else if (ic->op == '-') {
965                         val -= (int) operandLitValue(IC_RIGHT(ic));
966                 } else
967                         break;
968                 
969                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
970         }
971
972         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
973         refop = IC_LEFT(ic);
974
975         if(!op->isaddr)viaimmd++; else viaimmd=0;
976                 
977 /* set the following if to 1 to revert to good old immediate code */
978         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
979                 || viaimmd) {
980
981                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
982
983                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
984
985 #if 0
986                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
987 #else
988                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
989 #endif
990
991                 PCOI(aop->aopu.pcop)->index = val;
992                 
993                 aop->size = getSize( sym->type );
994         } else {
995                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
996
997                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
998                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
999
1000                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
1001         }
1002
1003
1004         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
1005                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1006 #if 0
1007                 val, IS_PTR_CONST(operandType(op)));
1008 #else
1009                 val, IS_CODEPTR(operandType(op)));
1010 #endif
1011
1012 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1013
1014         pic16_allocDirReg (IC_LEFT(ic));
1015
1016         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1017                 aop->code = 1;
1018
1019   return aop;        
1020 }
1021
1022 #if 0
1023 static int aopIdx (asmop *aop, int offset)
1024 {
1025   if(!aop)
1026     return -1;
1027
1028   if(aop->type !=  AOP_REG)
1029     return -2;
1030         
1031   return aop->aopu.aop_reg[offset]->rIdx;
1032
1033 }
1034 #endif
1035
1036 /*-----------------------------------------------------------------*/
1037 /* regsInCommon - two operands have some registers in common       */
1038 /*-----------------------------------------------------------------*/
1039 static bool regsInCommon (operand *op1, operand *op2)
1040 {
1041     symbol *sym1, *sym2;
1042     int i;
1043
1044     /* if they have registers in common */
1045     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1046         return FALSE ;
1047
1048     sym1 = OP_SYMBOL(op1);
1049     sym2 = OP_SYMBOL(op2);
1050
1051     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1052         return FALSE ;
1053
1054     for (i = 0 ; i < sym1->nRegs ; i++) {
1055         int j;
1056         if (!sym1->regs[i])
1057             continue ;
1058
1059         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1060             if (!sym2->regs[j])
1061                 continue ;
1062
1063             if (sym2->regs[j] == sym1->regs[i])
1064                 return TRUE ;
1065         }
1066     }
1067
1068     return FALSE ;
1069 }
1070
1071 /*-----------------------------------------------------------------*/
1072 /* operandsEqu - equivalent                                        */
1073 /*-----------------------------------------------------------------*/
1074 static bool operandsEqu ( operand *op1, operand *op2)
1075 {
1076     symbol *sym1, *sym2;
1077
1078     /* if they not symbols */
1079     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1080         return FALSE;
1081
1082     sym1 = OP_SYMBOL(op1);
1083     sym2 = OP_SYMBOL(op2);
1084
1085     /* if both are itemps & one is spilt
1086        and the other is not then false */
1087     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1088         sym1->isspilt != sym2->isspilt )
1089         return FALSE ;
1090
1091     /* if they are the same */
1092     if (sym1 == sym2)
1093         return TRUE ;
1094
1095     if (sym1->rname[0] && sym2->rname[0]
1096         && strcmp (sym1->rname, sym2->rname) == 0)
1097         return TRUE;
1098
1099
1100     /* if left is a tmp & right is not */
1101     if (IS_ITEMP(op1)  && 
1102         !IS_ITEMP(op2) &&
1103         sym1->isspilt  &&
1104         (sym1->usl.spillLoc == sym2))
1105         return TRUE;
1106
1107     if (IS_ITEMP(op2)  && 
1108         !IS_ITEMP(op1) &&
1109         sym2->isspilt  &&
1110         sym1->level > 0 &&
1111         (sym2->usl.spillLoc == sym1))
1112         return TRUE ;
1113
1114     return FALSE ;
1115 }
1116
1117 /*-----------------------------------------------------------------*/
1118 /* pic16_sameRegs - two asmops have the same registers                   */
1119 /*-----------------------------------------------------------------*/
1120 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1121 {
1122     int i;
1123
1124     if (aop1 == aop2)
1125         return TRUE ;
1126
1127     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1128                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1129
1130     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1131
1132     if (aop1->type != AOP_REG ||
1133         aop2->type != AOP_REG )
1134         return FALSE ;
1135
1136     /* This is a bit too restrictive if one is a subset of the other...
1137     if (aop1->size != aop2->size )
1138         return FALSE ;
1139     */
1140
1141     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1142 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1143
1144 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1145         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1146             return FALSE ;
1147     }
1148
1149     return TRUE ;
1150 }
1151
1152 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1153 {
1154     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1155                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1156
1157     if(aop1 == aop2)return TRUE;
1158     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1159       
1160       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1161     
1162   return TRUE;
1163 }
1164
1165
1166 /*-----------------------------------------------------------------*/
1167 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1168 /*-----------------------------------------------------------------*/
1169 void pic16_aopOp (operand *op, iCode *ic, bool result)
1170 {
1171     asmop *aop;
1172     symbol *sym;
1173     int i;
1174
1175     if (!op)
1176         return ;
1177
1178     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1179
1180     /* if this a literal */
1181     if (IS_OP_LITERAL(op)) {
1182         op->aop = aop = newAsmop(AOP_LIT);
1183         aop->aopu.aop_lit = op->operand.valOperand;
1184         aop->size = getSize(operandType(op));
1185         return;
1186     }
1187
1188     {
1189       sym_link *type = operandType(op);
1190 #if 0
1191       if(IS_PTR_CONST(type))
1192 #else
1193       if(IS_CODEPTR(type))
1194 #endif
1195         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1196     }
1197
1198     /* if already has a asmop then continue */
1199     if (op->aop)
1200         return ;
1201
1202     /* if the underlying symbol has a aop */
1203     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1204       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1205         op->aop = OP_SYMBOL(op)->aop;
1206         return;
1207     }
1208
1209     /* if this is a true symbol */
1210     if (IS_TRUE_SYMOP(op)) {    
1211         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1212       op->aop = aopForSym(ic, op, result);
1213       return ;
1214     }
1215
1216     /* this is a temporary : this has
1217     only four choices :
1218     a) register
1219     b) spillocation
1220     c) rematerialize 
1221     d) conditional   
1222     e) can be a return use only */
1223
1224     sym = OP_SYMBOL(op);
1225
1226     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1227     /* if the type is a conditional */
1228     if (sym->regType == REG_CND) {
1229         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1230         aop->size = 0;
1231         return;
1232     }
1233
1234     /* if it is spilt then two situations
1235     a) is rematerialize 
1236     b) has a spill location */
1237     if (sym->isspilt || sym->nRegs == 0) {
1238
1239 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1240       DEBUGpic16_emitcode(";","%d",__LINE__);
1241         /* rematerialize it NOW */
1242         if (sym->remat) {
1243
1244             sym->aop = op->aop = aop = aopForRemat (op, result);
1245 //            aop->size = getSize(sym->type);
1246 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1247             return;
1248         }
1249
1250 #if 1
1251         if (sym->accuse) {
1252             int i;
1253             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1254             aop->size = getSize(sym->type);
1255             for ( i = 0 ; i < 1 ; i++ ) {
1256                 aop->aopu.aop_str[i] = accUse[i];
1257 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1258             }
1259             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1260             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1261             return;  
1262         }
1263 #endif
1264
1265 #if 1
1266         if (sym->ruonly) {
1267           /*
1268           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1269           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1270           //pic16_allocDirReg (IC_LEFT(ic));
1271           aop->size = getSize(sym->type);
1272           */
1273
1274           unsigned i;
1275
1276           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1277           aop->size = getSize(sym->type);
1278           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1279             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1280
1281           DEBUGpic16_emitcode(";","%d",__LINE__);
1282           return;
1283         }
1284 #endif
1285         /* else spill location  */
1286         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1287             /* force a new aop if sizes differ */
1288             sym->usl.spillLoc->aop = NULL;
1289         }
1290
1291 #if 0
1292         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1293                             __FUNCTION__,__LINE__,
1294                             sym->usl.spillLoc->rname,
1295                             sym->rname, sym->usl.spillLoc->offset);
1296 #endif
1297
1298         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1299         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1300           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1301           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1302                                                   getSize(sym->type), 
1303                                                   sym->usl.spillLoc->offset, op);
1304         } else if (getSize(sym->type) <= 1) {
1305           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1306           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1307           assert (getSize(sym->type) <= 1);
1308           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1309           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1310         } else {
1311           /* We need some kind of dummy area for getSize(sym->type) byte,
1312            * use WREG for all storage locations.
1313            * XXX: This only works if we are implementing a `dummy read',
1314            *      the stored value will not be retrievable...
1315            *      See #1503234 for a case requiring this. */
1316           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1317           aop->size = getSize(sym->type);
1318           for ( i = 0 ; i < aop->size ;i++)
1319             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1320         }
1321         aop->size = getSize(sym->type);
1322
1323         return;
1324     }
1325
1326     {
1327       sym_link *type = operandType(op);
1328 #if 0
1329       if(IS_PTR_CONST(type)) 
1330 #else
1331       if(IS_CODEPTR(type)) 
1332 #endif
1333         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1334     }
1335
1336     /* must be in a register */
1337     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1338     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1339     aop->size = sym->nRegs;
1340     for ( i = 0 ; i < sym->nRegs ;i++)
1341         aop->aopu.aop_reg[i] = sym->regs[i];
1342 }
1343
1344 /*-----------------------------------------------------------------*/
1345 /* pic16_freeAsmop - free up the asmop given to an operand               */
1346 /*----------------------------------------------------------------*/
1347 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1348 {   
1349     asmop *aop ;
1350
1351     if (!op)
1352         aop = aaop;
1353     else 
1354         aop = op->aop;
1355
1356     if (!aop)
1357         return ;
1358
1359     if (aop->freed)
1360         goto dealloc; 
1361
1362     aop->freed = 1;
1363
1364     /* depending on the asmop type only three cases need work AOP_RO
1365        , AOP_R1 && AOP_STK */
1366 #if 1
1367     switch (aop->type) {
1368         case AOP_FSR0 :
1369             if (_G.fsr0Pushed ) {
1370                 if (pop) {
1371                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1372                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1373 //                    pic16_emitcode ("pop","ar0");
1374                     _G.fsr0Pushed--;
1375                 }
1376             }
1377             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1378             break;
1379
1380         case AOP_FSR2 :
1381             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1382             break;
1383
1384         case AOP_R0 :
1385             if (_G.r0Pushed ) {
1386                 if (pop) {
1387                     pic16_emitcode ("pop","ar0");     
1388                     _G.r0Pushed--;
1389                 }
1390             }
1391             bitVectUnSetBit(ic->rUsed,R0_IDX);
1392             break;
1393
1394         case AOP_R1 :
1395             if (_G.r1Pushed ) {
1396                 if (pop) {
1397                     pic16_emitcode ("pop","ar1");
1398                     _G.r1Pushed--;
1399                 }
1400             }
1401             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1402             break;
1403
1404         case AOP_STA:
1405           {
1406             int i;
1407
1408               /* we must store the result on stack */
1409               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1410                 // operands on stack are accessible via "FSR2 + index" with index
1411                 // starting at 2 for arguments and growing from 0 downwards for
1412                 // local variables (index == 0 is not assigned so we add one here)
1413                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1414                 if (soffs <= 0) {
1415                   assert (soffs < 0);
1416                   soffs++;
1417                 } // if
1418                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1419                 for(i=0;i<aop->size;i++) {
1420                   /* initialise for stack access via frame pointer */
1421                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1422                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1423                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1424                 }
1425         
1426                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1427               }
1428
1429               if(!_G.resDirect) {
1430                 for(i=0;i<aop->size;i++) {
1431                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1432
1433                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1434                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1435 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1436                   }
1437                 }
1438                 
1439                 {
1440                   regs *sr;
1441                   
1442                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1443                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1444                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1445                       deleteSetItem( &_G.sregsAllocSet, sr );
1446                     }
1447                 }
1448               }
1449               _G.resDirect = 0;
1450           }
1451           break;
1452 #if 0
1453         case AOP_STK :
1454         {
1455             int sz = aop->size;    
1456             int stk = aop->aopu.aop_stk + aop->size;
1457             bitVectUnSetBit(ic->rUsed,R0_IDX);
1458             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1459
1460             getFreePtr(ic,&aop,FALSE);
1461             
1462             if (options.stack10bit)
1463             {
1464                 /* I'm not sure what to do here yet... */
1465                 /* #STUB */
1466                 fprintf(stderr, 
1467                         "*** Warning: probably generating bad code for "
1468                         "10 bit stack mode.\n");
1469             }
1470             
1471             if (stk) {
1472                 pic16_emitcode ("mov","a,_bp");
1473                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1474                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1475             } else {
1476                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1477             }
1478
1479             while (sz--) {
1480                 pic16_emitcode("pop","acc");
1481                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1482                 if (!sz) break;
1483                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1484             }
1485             op->aop = aop;
1486             pic16_freeAsmop(op,NULL,ic,TRUE);
1487             if (_G.r0Pushed) {
1488                 pic16_emitcode("pop","ar0");
1489                 _G.r0Pushed--;
1490             }
1491
1492             if (_G.r1Pushed) {
1493                 pic16_emitcode("pop","ar1");
1494                 _G.r1Pushed--;
1495             }       
1496         }
1497 #endif
1498
1499     }
1500 #endif
1501
1502 dealloc:
1503     /* all other cases just dealloc */
1504     if (op ) {
1505         op->aop = NULL;
1506         if (IS_SYMOP(op)) {
1507             OP_SYMBOL(op)->aop = NULL;    
1508             /* if the symbol has a spill */
1509             if (SPIL_LOC(op))
1510                 SPIL_LOC(op)->aop = NULL;
1511         }
1512     }
1513 }
1514
1515 /*-----------------------------------------------------------------*/
1516 /* pic16_aopGet - for fetching value of the aop                          */
1517 /*-----------------------------------------------------------------*/
1518 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1519 {
1520     char *s = buffer ;
1521     char *rs;
1522
1523     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1524
1525     /* offset is greater than size then zero */
1526     if (offset > (aop->size - 1) &&
1527         aop->type != AOP_LIT)
1528         return zero;
1529
1530     /* depending on type */
1531     switch (aop->type) {
1532
1533     case AOP_FSR0:
1534     case AOP_FSR2:
1535       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1536       rs = Safe_calloc(1, strlen(s)+1);
1537       strcpy(rs, s);
1538       return (rs);
1539       
1540 #if 0
1541       /* if we need to increment it */
1542       while (offset > aop->coff)
1543         {
1544           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1545           aop->coff++;
1546         }
1547
1548       while (offset < aop->coff)
1549         {
1550           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1551           aop->coff--;
1552         }
1553       aop->coff = offset;
1554       if (aop->paged)
1555         {
1556           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1557           return (dname ? "acc" : "a");
1558         }
1559       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1560       rs = Safe_calloc (1, strlen (s) + 1);
1561       strcpy (rs, s);
1562       return rs;
1563 #endif
1564
1565         
1566     case AOP_IMMD:
1567         if (bit16) 
1568             sprintf (s,"%s",aop->aopu.aop_immd);
1569         else
1570             if (offset) 
1571                 sprintf(s,"(%s >> %d)",
1572                         aop->aopu.aop_immd,
1573                         offset*8);
1574             else
1575                 sprintf(s,"%s",
1576                         aop->aopu.aop_immd);
1577         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1578         rs = Safe_calloc(1,strlen(s)+1);
1579         strcpy(rs,s);   
1580         return rs;
1581         
1582     case AOP_DIR:
1583       if (offset) {
1584         sprintf(s,"(%s + %d)",
1585                 aop->aopu.aop_dir,
1586                 offset);
1587         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1588       } else
1589             sprintf(s,"%s",aop->aopu.aop_dir);
1590         rs = Safe_calloc(1,strlen(s)+1);
1591         strcpy(rs,s);   
1592         return rs;
1593         
1594     case AOP_REG:
1595       return aop->aopu.aop_reg[offset]->name;
1596         
1597     case AOP_CRY:
1598       return aop->aopu.aop_dir;
1599         
1600     case AOP_ACC:
1601         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1602 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1603 //        assert( 0 );
1604 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1605         rs = Safe_strdup("WREG");
1606         return (rs);
1607
1608     case AOP_LIT:
1609         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1610         rs = Safe_calloc(1,strlen(s)+1);
1611         strcpy(rs,s);   
1612         return rs;
1613         
1614     case AOP_STR:
1615         aop->coff = offset ;
1616
1617 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1618 //          dname)
1619 //          return "acc";
1620         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1621           aop->type = AOP_ACC;
1622           return Safe_strdup("_WREG");
1623         }
1624         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1625         
1626         return aop->aopu.aop_str[offset];
1627         
1628     case AOP_PCODE:
1629       {
1630         pCodeOp *pcop = aop->aopu.pcop;
1631         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1632         if(pcop->name) {
1633           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1634           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1635           if (offset) {
1636             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1637           } else {
1638             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1639           }
1640         } else
1641           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1642
1643       }
1644       rs = Safe_calloc(1,strlen(s)+1);
1645       strcpy(rs,s);   
1646       return rs;
1647
1648 #if 0
1649     case AOP_PAGED:
1650       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1651       if (offset) {
1652         sprintf(s,"(%s + %d)",
1653                 aop->aopu.aop_dir,
1654                 offset);
1655       } else
1656             sprintf(s,"%s",aop->aopu.aop_dir);
1657       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1658       rs = Safe_calloc(1,strlen(s)+1);
1659       strcpy(rs,s);   
1660       return rs;
1661 #endif
1662
1663     case AOP_STA:
1664         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1665         return (rs);
1666         
1667     case AOP_STK:
1668 //        pCodeOp *pcop = aop->aop
1669         break;
1670
1671     }
1672
1673     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1674     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1675            "aopget got unsupported aop->type");
1676     exit(0);
1677 }
1678
1679
1680
1681 /* lock has the following meaning: When allocating temporary registers
1682  * for stack variables storage, the value of the temporary register is
1683  * saved on stack. Its value is restored at the end. This procedure is
1684  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1685  * a possibility that before a call to pic16_aopOp, a temporary register
1686  * is allocated for a while and it is freed after some time, this will
1687  * mess the stack and values will not be restored properly. So use lock=1
1688  * to allocate temporary registers used internally by the programmer, and
1689  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1690  * to inform the compiler developer about a possible bug. This is an internal
1691  * feature for developing the compiler -- VR */
1692  
1693 int _TempReg_lock = 0;
1694 /*-----------------------------------------------------------------*/
1695 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1696 /*-----------------------------------------------------------------*/
1697 pCodeOp *pic16_popGetTempReg(int lock)
1698 {
1699   pCodeOp *pcop=NULL;
1700   symbol *cfunc;
1701
1702 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1703     if(_TempReg_lock) {
1704 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1705     }
1706     
1707     _TempReg_lock += lock;
1708     
1709     cfunc = currFunc;
1710     currFunc = NULL;
1711
1712 #if 0
1713         {
1714           regs *rr;
1715           int i;
1716
1717                 /* this code might seem better but it does the *same* job with
1718                  * the old code, it all depends on ralloc.c to get a free/unused
1719                  * register */
1720          
1721                 i=0;
1722                 while(i < pic16_nRegs) {
1723                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1724                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1725                         if((!rr || (rr && rr->isFree))
1726                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1727                                 pcop = pic16_newpCodeOpReg( i );
1728                                 PCOR(pcop)->r->wasUsed = 1;
1729                                 PCOR(pcop)->r->isFree = 0;
1730                                 break;
1731                         }
1732                         i++;
1733                 }
1734
1735                 if(pcop) {
1736                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1737                 }
1738         }
1739 #else
1740     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1741     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1742       PCOR(pcop)->r->wasUsed=1;
1743       PCOR(pcop)->r->isFree=0;
1744
1745       /* push value on stack */
1746       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1747     }
1748 #endif
1749
1750     currFunc = cfunc;
1751
1752   return pcop;
1753 }
1754
1755 /*-----------------------------------------------------------------*/
1756 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1757 /*                           is not part of f, but don't save if   */
1758 /*                           inside v                              */
1759 /*-----------------------------------------------------------------*/
1760 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1761 {
1762   pCodeOp *pcop=NULL;
1763   symbol *cfunc;
1764   int i;
1765
1766 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1767
1768     if(_TempReg_lock) {
1769 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1770     }
1771
1772     _TempReg_lock += lock;
1773
1774     cfunc = currFunc;
1775     currFunc = NULL;
1776
1777     i = bitVectFirstBit(f);
1778     while(i < 128) {
1779
1780       /* bypass registers that are used by function */
1781       if(!bitVectBitValue(f, i)) {
1782       
1783         /* bypass registers that are already allocated for stack access */
1784         if(!bitVectBitValue(v, i))  {
1785         
1786 //          debugf("getting register rIdx = %d\n", i);
1787           /* ok, get the operand */
1788           pcop = pic16_newpCodeOpReg( i );
1789     
1790           /* should never by NULL */
1791           assert( pcop != NULL );
1792
1793           
1794           /* sanity check */
1795           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1796             int found=0;
1797             
1798               PCOR(pcop)->r->wasUsed=1;
1799               PCOR(pcop)->r->isFree=0;
1800
1801
1802               {
1803                 regs *sr;
1804               
1805                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1806
1807                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1808                       /* already used in previous steps, break */
1809                       found=1;          
1810                       break;
1811                     }
1812                   }
1813               }
1814
1815               /* caller takes care of the following */
1816 //              bitVectSetBit(v, i);
1817
1818               if(!found) {
1819                 /* push value on stack */
1820                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1821                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1822               }
1823           
1824             break;
1825           }
1826         }
1827       }
1828       i++;
1829     }
1830
1831     currFunc = cfunc;
1832
1833   return pcop;
1834 }
1835
1836
1837 /*-----------------------------------------------------------------*/
1838 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1839 /*-----------------------------------------------------------------*/
1840 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1841 {
1842   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1843
1844   _TempReg_lock -= lock;
1845
1846   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1847     PCOR(pcop)->r->isFree = 1;
1848
1849     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1850   }
1851 }
1852 /*-----------------------------------------------------------------*/
1853 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1854 /*-----------------------------------------------------------------*/
1855 pCodeOp *pic16_popGetLabel(int key)
1856 {
1857
1858   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1859
1860   if(key>max_key)
1861     max_key = key;
1862
1863   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1864 }
1865
1866 /*-----------------------------------------------------------------*/
1867 /* pic16_popCopyReg - copy a pcode operator                              */
1868 /*-----------------------------------------------------------------*/
1869 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1870 {
1871   pCodeOpReg *pcor;
1872
1873   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1874   memcpy (pcor, pc, sizeof (pCodeOpReg));
1875   pcor->r->wasUsed = 1;
1876   
1877   //pcor->pcop.type = pc->pcop.type;
1878   if(pc->pcop.name) {
1879     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1880       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1881   } else
1882     pcor->pcop.name = NULL;
1883
1884   //pcor->r = pc->r;
1885   //pcor->rIdx = pc->rIdx;
1886   //pcor->r->wasUsed=1;
1887   //pcor->instance = pc->instance;
1888
1889 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1890
1891   return PCOP(pcor);
1892 }
1893
1894 /*-----------------------------------------------------------------*/
1895 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1896 /*-----------------------------------------------------------------*/
1897 pCodeOp *pic16_popGetLit(int lit)
1898 {
1899   return pic16_newpCodeOpLit(lit);
1900 }
1901
1902 /* Allow for 12 bit literals (LFSR x, <here!>). */
1903 pCodeOp *pic16_popGetLit12(int lit)
1904 {
1905   return pic16_newpCodeOpLit12(lit);
1906 }
1907
1908 /*-----------------------------------------------------------------*/
1909 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1910 /*-----------------------------------------------------------------*/
1911 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1912 {
1913   return pic16_newpCodeOpLit2(lit, arg2);
1914 }
1915
1916
1917 /*-----------------------------------------------------------------*/
1918 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1919 /*-----------------------------------------------------------------*/
1920 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1921 {
1922   return pic16_newpCodeOpImmd(name, offset,index, 0);
1923 }
1924
1925
1926 /*-----------------------------------------------------------------*/
1927 /* pic16_popGet - asm operator to pcode operator conversion              */
1928 /*-----------------------------------------------------------------*/
1929 pCodeOp *pic16_popGetWithString(char *str)
1930 {
1931   pCodeOp *pcop;
1932
1933
1934   if(!str) {
1935     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1936     exit (1);
1937   }
1938
1939   pcop = pic16_newpCodeOp(str,PO_STR);
1940
1941   return pcop;
1942 }
1943
1944 /*-----------------------------------------------------------------*/
1945 /* pic16_popRegFromString -                                        */
1946 /*-----------------------------------------------------------------*/
1947 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1948 {
1949
1950   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1951   pcop->type = PO_DIR;
1952
1953   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1954   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1955
1956   if(!str)
1957     str = "BAD_STRING";
1958
1959   pcop->name = Safe_calloc(1,strlen(str)+1);
1960   strcpy(pcop->name,str);
1961
1962   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1963
1964   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1965 //  PCOR(pcop)->r->wasUsed = 1;
1966
1967   /* make sure that register doesn't exist,
1968    * and operand isn't NULL
1969    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1970   if((PCOR(pcop)->r == NULL) 
1971     && (op)
1972     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1973 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1974 //              __FUNCTION__, __LINE__, str, size, offset);
1975
1976     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1977     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1978
1979   }
1980   PCOR(pcop)->instance = offset;
1981
1982   return pcop;
1983 }
1984
1985 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1986 {
1987   pCodeOp *pcop;
1988
1989 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1990 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1991         
1992         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1993         PCOR(pcop)->rIdx = rIdx;
1994         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1995         if(!PCOR(pcop)->r)
1996                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1997                 
1998         PCOR(pcop)->r->isFree = 0;
1999         PCOR(pcop)->r->wasUsed = 1;
2000
2001         pcop->type = PCOR(pcop)->r->pc_type;
2002
2003   return pcop;
2004 }
2005
2006 /*---------------------------------------------------------------------------------*/
2007 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2008 /*                 VR 030601                                                       */
2009 /*---------------------------------------------------------------------------------*/
2010 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2011 {
2012   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2013         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2014   return PCOP(pcop2);
2015 }
2016
2017
2018
2019 /*--------------------------------------------------------------------------------.-*/
2020 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2021 /*                  VR 030601 , adapted by Hans Dorn                                */
2022 /*--------------------------------------------------------------------------------.-*/
2023 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2024 {
2025   pCodeOp2 *pcop2;
2026   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2027   return PCOP(pcop2);
2028 }
2029
2030 /*---------------------------------------------------------------------------------*/
2031 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2032 /*                     movff instruction                                           */
2033 /*---------------------------------------------------------------------------------*/
2034 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2035 {
2036   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2037         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2038
2039   return PCOP(pcop2);
2040 }
2041
2042
2043 /*-----------------------------------------------------------------*/
2044 /* pic16_popGet - asm operator to pcode operator conversion              */
2045 /*-----------------------------------------------------------------*/
2046 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2047 {
2048 //  char *s = buffer ;
2049 //  char *rs;
2050   pCodeOp *pcop;
2051
2052     FENTRY2;
2053     
2054       /* offset is greater than size then zero */
2055
2056 //    if (offset > (aop->size - 1) &&
2057 //        aop->type != AOP_LIT)
2058 //      return NULL;  //zero;
2059
2060     /* depending on type */
2061     switch (aop->type) {
2062                 case AOP_R0:
2063                 case AOP_R1:
2064                 case AOP_DPTR:
2065                 case AOP_DPTR2:
2066                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2067                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2068                         assert( 0 );
2069                         return NULL;
2070
2071                 case AOP_FSR0:
2072                 case AOP_FSR2:
2073                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2074                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2075                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2076                         PCOR(pcop)->r->wasUsed = 1;
2077                         PCOR(pcop)->r->isFree = 0;
2078       
2079                         PCOR(pcop)->instance = offset;
2080                         pcop->type = PCOR(pcop)->r->pc_type;
2081                         return (pcop);
2082
2083                 case AOP_IMMD:
2084                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2085                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2086
2087                 case AOP_STA:
2088                         /* pCodeOp is already allocated from aopForSym */
2089                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2090                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2091                         return (pcop);
2092       
2093                 case AOP_ACC:
2094                         {
2095                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2096
2097                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2098
2099                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2100         
2101                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2102                                 PCOR(pcop)->rIdx = rIdx;
2103                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2104                                 PCOR(pcop)->r->wasUsed=1;
2105                                 PCOR(pcop)->r->isFree=0;
2106
2107                                 PCOR(pcop)->instance = offset;
2108                                 pcop->type = PCOR(pcop)->r->pc_type;
2109 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2110                                 return pcop;
2111
2112
2113 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2114 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2115
2116 //      assert( 0 );
2117                         }
2118         
2119     case AOP_DIR:
2120       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2121       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2122         
2123 #if 0
2124     case AOP_PAGED:
2125       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2126       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2127 #endif
2128
2129     case AOP_REG:
2130       {
2131         int rIdx;
2132
2133 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
2134 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
2135         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2136
2137         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2138         
2139         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2140 //      pcop->type = PO_GPR_REGISTER;
2141         PCOR(pcop)->rIdx = rIdx;
2142         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2143         PCOR(pcop)->r->wasUsed=1;
2144         PCOR(pcop)->r->isFree=0;
2145
2146         PCOR(pcop)->instance = offset;
2147         pcop->type = PCOR(pcop)->r->pc_type;
2148         
2149         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2150 //      rs = aop->aopu.aop_reg[offset]->name;
2151 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2152         return pcop;
2153       }
2154
2155     case AOP_CRY:
2156         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2157
2158       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2159       PCOR(pcop)->instance = offset;
2160       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2161       //if(PCOR(pcop)->r == NULL)
2162       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2163       return pcop;
2164         
2165     case AOP_LIT:
2166         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2167       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2168
2169     case AOP_STR:
2170       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2171       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2172
2173       /*
2174       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2175       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2176       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2177       pcop->type = PCOR(pcop)->r->pc_type;
2178       pcop->name = PCOR(pcop)->r->name;
2179
2180       return pcop;
2181       */
2182
2183     case AOP_PCODE:
2184       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2185                           __LINE__, 
2186                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2187       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2188       switch( aop->aopu.pcop->type ) {
2189         case PO_DIR: PCOR(pcop)->instance += offset; break;
2190         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2191         case PO_WREG:
2192             assert (offset==0);
2193             break;
2194         default:
2195           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2196           assert( 0 );  /* should never reach here */;
2197       }
2198       return pcop;
2199     }
2200
2201     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2202            "pic16_popGet got unsupported aop->type");
2203     exit(0);
2204 }
2205 /*-----------------------------------------------------------------*/
2206 /* pic16_aopPut - puts a string for a aop                                */
2207 /*-----------------------------------------------------------------*/
2208 void pic16_aopPut (asmop *aop, char *s, int offset)
2209 {
2210     char *d = buffer ;
2211     symbol *lbl ;
2212
2213     return;
2214
2215     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2216
2217     if (aop->size && offset > ( aop->size - 1)) {
2218         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2219                "pic16_aopPut got offset > aop->size");
2220         exit(0);
2221     }
2222
2223     /* will assign value to value */
2224     /* depending on where it is ofcourse */
2225     switch (aop->type) {
2226     case AOP_DIR:
2227       if (offset) {
2228         sprintf(d,"(%s + %d)",
2229                 aop->aopu.aop_dir,offset);
2230         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2231
2232       } else
2233             sprintf(d,"%s",aop->aopu.aop_dir);
2234         
2235         if (strcmp(d,s)) {
2236           DEBUGpic16_emitcode(";","%d",__LINE__);
2237           if(strcmp(s,"W"))
2238             pic16_emitcode("movf","%s,w",s);
2239           pic16_emitcode("movwf","%s",d);
2240
2241           if(strcmp(s,"W")) {
2242             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2243             if(offset >= aop->size) {
2244               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2245               break;
2246             } else
2247               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2248           }
2249
2250           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2251
2252
2253         }
2254         break;
2255         
2256     case AOP_REG:
2257       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2258         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2259           /*
2260             if (*s == '@'           ||
2261                 strcmp(s,"r0") == 0 ||
2262                 strcmp(s,"r1") == 0 ||
2263                 strcmp(s,"r2") == 0 ||
2264                 strcmp(s,"r3") == 0 ||
2265                 strcmp(s,"r4") == 0 ||
2266                 strcmp(s,"r5") == 0 ||
2267                 strcmp(s,"r6") == 0 || 
2268                 strcmp(s,"r7") == 0 )
2269                 pic16_emitcode("mov","%s,%s  ; %d",
2270                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2271             else
2272           */
2273
2274           if(strcmp(s,"W")==0 )
2275             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2276
2277           pic16_emitcode("movwf","%s",
2278                    aop->aopu.aop_reg[offset]->name);
2279
2280           if(strcmp(s,zero)==0) {
2281             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2282
2283           } else if(strcmp(s,"W")==0) {
2284             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2285             pcop->type = PO_GPR_REGISTER;
2286
2287             PCOR(pcop)->rIdx = -1;
2288             PCOR(pcop)->r = NULL;
2289
2290             DEBUGpic16_emitcode(";","%d",__LINE__);
2291             pcop->name = Safe_strdup(s);
2292             pic16_emitpcode(POC_MOVFW,pcop);
2293             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2294           } else if(strcmp(s,one)==0) {
2295             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2296             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2297           } else {
2298             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2299           }
2300         }
2301         break;
2302         
2303     case AOP_DPTR:
2304     case AOP_DPTR2:
2305     
2306     if (aop->type == AOP_DPTR2)
2307     {
2308         genSetDPTR(1);
2309     }
2310     
2311         if (aop->code) {
2312             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2313                    "pic16_aopPut writting to code space");
2314             exit(0);
2315         }
2316         
2317         while (offset > aop->coff) {
2318             aop->coff++;
2319             pic16_emitcode ("inc","dptr");
2320         }
2321         
2322         while (offset < aop->coff) {
2323             aop->coff-- ;
2324             pic16_emitcode("lcall","__decdptr");
2325         }
2326         
2327         aop->coff = offset;
2328         
2329         /* if not in accumulater */
2330         MOVA(s);        
2331         
2332         pic16_emitcode ("movx","@dptr,a");
2333         
2334     if (aop->type == AOP_DPTR2)
2335     {
2336         genSetDPTR(0);
2337     }
2338         break;
2339         
2340     case AOP_R0:
2341     case AOP_R1:
2342         while (offset > aop->coff) {
2343             aop->coff++;
2344             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2345         }
2346         while (offset < aop->coff) {
2347             aop->coff-- ;
2348             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2349         }
2350         aop->coff = offset;
2351         
2352         if (aop->paged) {
2353             MOVA(s);           
2354             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2355             
2356         } else
2357             if (*s == '@') {
2358                 MOVA(s);
2359                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2360             } else
2361                 if (strcmp(s,"r0") == 0 ||
2362                     strcmp(s,"r1") == 0 ||
2363                     strcmp(s,"r2") == 0 ||
2364                     strcmp(s,"r3") == 0 ||
2365                     strcmp(s,"r4") == 0 ||
2366                     strcmp(s,"r5") == 0 ||
2367                     strcmp(s,"r6") == 0 || 
2368                     strcmp(s,"r7") == 0 ) {
2369                     char buffer[10];
2370                     sprintf(buffer,"a%s",s);
2371                     pic16_emitcode("mov","@%s,%s",
2372                              aop->aopu.aop_ptr->name,buffer);
2373                 } else
2374                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2375         
2376         break;
2377         
2378     case AOP_STK:
2379         if (strcmp(s,"a") == 0)
2380             pic16_emitcode("push","acc");
2381         else
2382             pic16_emitcode("push","%s",s);
2383         
2384         break;
2385         
2386     case AOP_CRY:
2387         /* if bit variable */
2388         if (!aop->aopu.aop_dir) {
2389             pic16_emitcode("clr","a");
2390             pic16_emitcode("rlc","a");
2391         } else {
2392             if (s == zero) 
2393                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2394             else
2395                 if (s == one)
2396                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2397                 else
2398                     if (!strcmp(s,"c"))
2399                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2400                     else {
2401                         lbl = newiTempLabel(NULL);
2402                         
2403                         if (strcmp(s,"a")) {
2404                             MOVA(s);
2405                         }
2406                         pic16_emitcode("clr","c");
2407                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2408                         pic16_emitcode("cpl","c");
2409                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2410                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2411                     }
2412         }
2413         break;
2414         
2415     case AOP_STR:
2416         aop->coff = offset;
2417         if (strcmp(aop->aopu.aop_str[offset],s))
2418             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2419         break;
2420         
2421     case AOP_ACC:
2422         aop->coff = offset;
2423         if (!offset && (strcmp(s,"acc") == 0))
2424             break;
2425         
2426         if (strcmp(aop->aopu.aop_str[offset],s))
2427             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2428         break;
2429
2430     default :
2431         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2432 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2433 //             "pic16_aopPut got unsupported aop->type");
2434 //      exit(0);    
2435     }    
2436
2437 }
2438
2439 /*-----------------------------------------------------------------*/
2440 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2441 /*-----------------------------------------------------------------*/
2442 void pic16_mov2w (asmop *aop, int offset)
2443 {
2444   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2445
2446   if(is_LitAOp(aop))
2447     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2448   else
2449     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2450 }
2451
2452 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2453 {
2454   if(is_LitAOp(src)) {
2455     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2456     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2457   } else {
2458     if(pic16_sameRegsOfs(src, dst, offset))return;
2459     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2460                       pic16_popGet(dst, offset)));
2461   }
2462 }
2463
2464 static void pic16_movLit2f(pCodeOp *pc, int lit)
2465 {
2466   if (0 == (lit & 0x00ff))
2467   {
2468     pic16_emitpcode (POC_CLRF, pc);
2469   } else if (0xff == (lit & 0x00ff))
2470   {
2471     pic16_emitpcode (POC_SETF, pc);
2472   } else {
2473     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2474     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2475   }
2476 }
2477
2478 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2479 {
2480   if(is_LitAOp(src)) {
2481     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2482     pic16_emitpcode(POC_MOVWF, dst);
2483   } else {
2484     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2485   }
2486 }
2487
2488 void pic16_testStackOverflow(void)
2489 {
2490 #define GSTACK_TEST_NAME        "_gstack_test"
2491
2492   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2493   
2494   {
2495     symbol *sym;
2496
2497       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2498       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2499 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2500       checkAddSym(&externs, sym);
2501   }
2502
2503 }
2504
2505 /* push pcop into stack */
2506 void pic16_pushpCodeOp(pCodeOp *pcop)
2507 {
2508 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2509   if (pcop->type == PO_LITERAL) {
2510     pic16_emitpcode(POC_MOVLW, pcop);
2511     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2512   } else {
2513     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2514   }
2515   if(pic16_options.gstack)
2516     pic16_testStackOverflow();
2517     
2518 }
2519
2520 /* pop pcop from stack */
2521 void pic16_poppCodeOp(pCodeOp *pcop)
2522 {
2523   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2524   if(pic16_options.gstack)
2525     pic16_testStackOverflow();
2526 }
2527
2528
2529 /*-----------------------------------------------------------------*/
2530 /* pushw - pushes wreg to stack                                    */
2531 /*-----------------------------------------------------------------*/
2532 void pushw(void)
2533 {
2534   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2535   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2536   if(pic16_options.gstack)
2537     pic16_testStackOverflow();
2538 }
2539
2540                 
2541 /*-----------------------------------------------------------------*/
2542 /* pushaop - pushes aop to stack                                   */
2543 /*-----------------------------------------------------------------*/
2544 void pushaop(asmop *aop, int offset)
2545 {
2546   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2547
2548   if(_G.resDirect)return;
2549   
2550   if(is_LitAOp(aop)) {
2551     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2552     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2553   } else {
2554     pic16_emitpcode(POC_MOVFF,
2555       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2556   }
2557
2558   if(pic16_options.gstack)
2559     pic16_testStackOverflow();
2560 }
2561
2562 /*-----------------------------------------------------------------*/
2563 /* popaop - pops aop from stack                                    */
2564 /*-----------------------------------------------------------------*/
2565 void popaop(asmop *aop, int offset)
2566 {
2567   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2568   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2569   if(pic16_options.gstack)
2570     pic16_testStackOverflow();
2571 }
2572
2573 void popaopidx(asmop *aop, int offset, int index)
2574 {
2575   int ofs=1;
2576
2577     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2578
2579     if(STACK_MODEL_LARGE)ofs++;
2580
2581     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2582     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2583     if(pic16_options.gstack)
2584       pic16_testStackOverflow();
2585 }
2586
2587 #if !(USE_GENERIC_SIGNED_SHIFT)
2588 /*-----------------------------------------------------------------*/
2589 /* reAdjustPreg - points a register back to where it should        */
2590 /*-----------------------------------------------------------------*/
2591 static void reAdjustPreg (asmop *aop)
2592 {
2593     int size ;
2594
2595     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2596     aop->coff = 0;
2597     if ((size = aop->size) <= 1)
2598         return ;
2599     size-- ;
2600     switch (aop->type) {
2601         case AOP_R0 :
2602         case AOP_R1 :
2603             while (size--)
2604                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2605             break;          
2606         case AOP_DPTR :
2607         case AOP_DPTR2:
2608             if (aop->type == AOP_DPTR2)
2609             {
2610                 genSetDPTR(1);
2611             } 
2612             while (size--)
2613             {
2614                 pic16_emitcode("lcall","__decdptr");
2615             }
2616                 
2617             if (aop->type == AOP_DPTR2)
2618             {
2619                 genSetDPTR(0);
2620             }                
2621             break;  
2622
2623     }   
2624
2625 }
2626 #endif
2627
2628 #if 0
2629 /*-----------------------------------------------------------------*/
2630 /* opIsGptr: returns non-zero if the passed operand is             */   
2631 /* a generic pointer type.                                         */
2632 /*-----------------------------------------------------------------*/ 
2633 static int opIsGptr(operand *op)
2634 {
2635     sym_link *type = operandType(op);
2636     
2637     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2638     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2639     {
2640         return 1;
2641     }
2642     return 0;        
2643 }
2644 #endif
2645
2646 /*-----------------------------------------------------------------*/
2647 /* pic16_getDataSize - get the operand data size                         */
2648 /*-----------------------------------------------------------------*/
2649 int pic16_getDataSize(operand *op)
2650 {
2651     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2652
2653
2654     return AOP_SIZE(op);
2655
2656     // tsd- in the pic port, the genptr size is 1, so this code here
2657     // fails. ( in the 8051 port, the size was 4).
2658 #if 0
2659     int size;
2660     size = AOP_SIZE(op);
2661     if (size == GPTRSIZE)
2662     {
2663         sym_link *type = operandType(op);
2664         if (IS_GENPTR(type))
2665         {
2666             /* generic pointer; arithmetic operations
2667              * should ignore the high byte (pointer type).
2668              */
2669             size--;
2670     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2671         }
2672     }
2673     return size;
2674 #endif
2675 }
2676
2677 /*-----------------------------------------------------------------*/
2678 /* pic16_outAcc - output Acc                                             */
2679 /*-----------------------------------------------------------------*/
2680 void pic16_outAcc(operand *result)
2681 {
2682   int size,offset;
2683   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2684   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2685
2686
2687   size = pic16_getDataSize(result);
2688   if(size){
2689     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2690     size--;
2691     offset = 1;
2692     /* unsigned or positive */
2693     while(size--)
2694       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2695   }
2696
2697 }
2698
2699 /*-----------------------------------------------------------------*/
2700 /* pic16_outBitC - output a bit C                                  */
2701 /*                 Move to result the value of Carry flag -- VR    */
2702 /*-----------------------------------------------------------------*/
2703 void pic16_outBitC(operand *result)
2704 {
2705   int i;
2706
2707     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2708
2709     /* if the result is bit */
2710     if (AOP_TYPE(result) == AOP_CRY) {
2711         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2712         pic16_aopPut(AOP(result),"c",0);
2713     } else {
2714
2715         i = AOP_SIZE(result);
2716         while(i--) {
2717                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2718         }
2719         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2720     }
2721 }
2722
2723 /*-----------------------------------------------------------------*/
2724 /* pic16_outBitOp - output a bit from Op                           */
2725 /*                 Move to result the value of set/clr op -- VR    */
2726 /*-----------------------------------------------------------------*/
2727 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2728 {
2729   int i;
2730
2731     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2732
2733     /* if the result is bit */
2734     if (AOP_TYPE(result) == AOP_CRY) {
2735         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2736         pic16_aopPut(AOP(result),"c",0);
2737     } else {
2738
2739         i = AOP_SIZE(result);
2740         while(i--) {
2741                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2742         }
2743         pic16_emitpcode(POC_RRCF, pcop);          
2744         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2745     }
2746 }
2747
2748 /*-----------------------------------------------------------------*/
2749 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2750 /*-----------------------------------------------------------------*/
2751 void pic16_toBoolean(operand *oper)
2752 {
2753     int size = AOP_SIZE(oper) - 1;
2754     int offset = 1;
2755
2756     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2757
2758     if ( AOP_TYPE(oper) != AOP_ACC) {
2759       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2760     }
2761     while (size--) {
2762       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2763     }
2764 }
2765
2766 /*-----------------------------------------------------------------*/
2767 /* genUminusFloat - unary minus for floating points                */
2768 /*-----------------------------------------------------------------*/
2769 static void genUminusFloat(operand *op,operand *result)
2770 {
2771   int size ,offset =0 ;
2772   
2773     FENTRY;
2774     /* for this we just need to flip the 
2775     first it then copy the rest in place */
2776     size = AOP_SIZE(op);
2777     assert( size == AOP_SIZE(result) );
2778
2779     while(size--) {
2780       pic16_mov2f(AOP(result), AOP(op), offset);
2781       offset++;
2782     }
2783     
2784     /* toggle the MSB's highest bit */
2785     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2786 }
2787
2788 /*-----------------------------------------------------------------*/
2789 /* genUminus - unary minus code generation                         */
2790 /*-----------------------------------------------------------------*/
2791 static void genUminus (iCode *ic)
2792 {
2793   int size, i;
2794   sym_link *optype, *rtype;
2795   symbol *label;
2796   int needLabel=0;
2797
2798     FENTRY;     
2799     
2800     /* assign asmops */
2801     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2802     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2803
2804     /* if both in bit space then special case */
2805     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2806       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2807         
2808         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2809         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2810         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2811         goto release; 
2812     } 
2813
2814     optype = operandType(IC_LEFT(ic));
2815     rtype = operandType(IC_RESULT(ic));
2816
2817
2818     /* if float then do float stuff */
2819     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2820       if(IS_FIXED(optype))
2821         debugf("implement fixed16x16 type\n", 0);
2822         
2823         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2824         goto release;
2825     }
2826
2827     /* otherwise subtract from zero by taking the 2's complement */
2828     size = AOP_SIZE(IC_LEFT(ic));
2829     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2830     label = newiTempLabel ( NULL );
2831     
2832     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2833       for (i=size-1; i > 0; i--) {
2834         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2835       } // for
2836       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2837       for (i=1; i < size; i++) {
2838         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2839         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2840       } // for
2841     } else {
2842       for (i=size-1; i >= 0; i--) {
2843         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2844         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2845       } // for
2846       if (size > 1) {
2847         for (i=0; i < size-2; i++) {
2848           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2849           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2850         } // for
2851         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2852       } // if
2853       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2854     }
2855     if (needLabel)
2856       pic16_emitpLabel (label->key);
2857
2858 release:
2859     /* release the aops */
2860     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2861     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2862 }
2863
2864 #if 0
2865 /*-----------------------------------------------------------------*/
2866 /* saveRegisters - will look for a call and save the registers     */
2867 /*-----------------------------------------------------------------*/
2868 static void saveRegisters(iCode *lic) 
2869 {
2870     int i;
2871     iCode *ic;
2872     bitVect *rsave;
2873     sym_link *dtype;
2874
2875     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2876     /* look for call */
2877     for (ic = lic ; ic ; ic = ic->next) 
2878         if (ic->op == CALL || ic->op == PCALL)
2879             break;
2880
2881     if (!ic) {
2882         fprintf(stderr,"found parameter push with no function call\n");
2883         return ;
2884     }
2885
2886     /* if the registers have been saved already then
2887     do nothing */
2888     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2889         return ;
2890
2891     /* find the registers in use at this time 
2892     and push them away to safety */
2893     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2894                           ic->rUsed);
2895
2896     ic->regsSaved = 1;
2897     if (options.useXstack) {
2898         if (bitVectBitValue(rsave,R0_IDX))
2899             pic16_emitcode("mov","b,r0");
2900         pic16_emitcode("mov","r0,%s",spname);
2901         for (i = 0 ; i < pic16_nRegs ; i++) {
2902             if (bitVectBitValue(rsave,i)) {
2903                 if (i == R0_IDX)
2904                     pic16_emitcode("mov","a,b");
2905                 else
2906                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2907                 pic16_emitcode("movx","@r0,a");
2908                 pic16_emitcode("inc","r0");
2909             }
2910         }
2911         pic16_emitcode("mov","%s,r0",spname);
2912         if (bitVectBitValue(rsave,R0_IDX))
2913             pic16_emitcode("mov","r0,b");           
2914     }// else
2915     //for (i = 0 ; i < pic16_nRegs ; i++) {
2916     //    if (bitVectBitValue(rsave,i))
2917     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2918     //}
2919
2920     dtype = operandType(IC_LEFT(ic));
2921     if (currFunc && dtype && 
2922         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2923         IFFUNC_ISISR(currFunc->type) &&
2924         !ic->bankSaved) 
2925
2926         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2927
2928 }
2929 /*-----------------------------------------------------------------*/
2930 /* unsaveRegisters - pop the pushed registers                      */
2931 /*-----------------------------------------------------------------*/
2932 static void unsaveRegisters (iCode *ic)
2933 {
2934     int i;
2935     bitVect *rsave;
2936
2937     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2938     /* find the registers in use at this time 
2939     and push them away to safety */
2940     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2941                           ic->rUsed);
2942     
2943     if (options.useXstack) {
2944         pic16_emitcode("mov","r0,%s",spname);   
2945         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2946             if (bitVectBitValue(rsave,i)) {
2947                 pic16_emitcode("dec","r0");
2948                 pic16_emitcode("movx","a,@r0");
2949                 if (i == R0_IDX)
2950                     pic16_emitcode("mov","b,a");
2951                 else
2952                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2953             }       
2954
2955         }
2956         pic16_emitcode("mov","%s,r0",spname);
2957         if (bitVectBitValue(rsave,R0_IDX))
2958             pic16_emitcode("mov","r0,b");
2959     } //else
2960     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2961     //    if (bitVectBitValue(rsave,i))
2962     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2963     //}
2964
2965 }  
2966 #endif
2967
2968 #if 0  // patch 14
2969 /*-----------------------------------------------------------------*/
2970 /* pushSide -                                                      */
2971 /*-----------------------------------------------------------------*/
2972 static void pushSide(operand * oper, int size)
2973 {
2974         int offset = 0;
2975     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2976         while (size--) {
2977                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2978                 if (AOP_TYPE(oper) != AOP_REG &&
2979                     AOP_TYPE(oper) != AOP_DIR &&
2980                     strcmp(l,"a") ) {
2981                         pic16_emitcode("mov","a,%s",l);
2982                         pic16_emitcode("push","acc");
2983                 } else
2984                         pic16_emitcode("push","%s",l);
2985         }
2986 }
2987 #endif // patch 14
2988
2989 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2990 {
2991   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2992     pic16_emitpcode(POC_MOVFW, src);
2993     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2994   } else {
2995     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2996         src, pic16_popGet(AOP(op), offset)));
2997   }
2998 }
2999
3000
3001 /*-----------------------------------------------------------------*/
3002 /* assignResultValue - assign results to oper, rescall==1 is       */
3003 /*                     called from genCall() or genPcall()         */
3004 /*-----------------------------------------------------------------*/
3005 static void assignResultValue(operand * oper, int res_size, int rescall)
3006 {
3007   int size = AOP_SIZE(oper);
3008   int offset=0;
3009   
3010     FENTRY2;
3011 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3012     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3013
3014     if(rescall) {
3015       /* assign result from a call/pcall function() */
3016                 
3017       /* function results are stored in a special order,
3018        * see top of file with Function return policy, or manual */
3019
3020       if(size <= 4) {
3021         /* 8-bits, result in WREG */
3022         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3023                         
3024         if(size > 1 && res_size > 1) {
3025           /* 16-bits, result in PRODL:WREG */
3026           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3027         }
3028                         
3029         if(size > 2 && res_size > 2) {
3030           /* 24-bits, result in PRODH:PRODL:WREG */
3031           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3032         }
3033                         
3034         if(size > 3 && res_size > 3) {
3035           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3036           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3037         }
3038
3039         pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
3040       
3041       } else {
3042         /* >32-bits, result on stack, and FSR0 points to beginning.
3043          * Fix stack when done */
3044         /* FIXME FIXME */
3045 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3046         while (size--) {
3047 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3048 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3049                 
3050           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3051           GpsuedoStkPtr++;
3052         }
3053                         
3054         /* fix stack */
3055         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3056         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3057         if(STACK_MODEL_LARGE) {
3058           emitSKPNC;
3059           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3060         }
3061       }                 
3062     } else {
3063       int areg = 0;             /* matching argument register */
3064       
3065 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3066       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3067
3068
3069       /* its called from genReceive (probably) -- VR */
3070       /* I hope this code will not be called from somewhere else in the future! 
3071        * We manually set the pseudo stack pointer in genReceive. - dw
3072        */
3073       if(!GpsuedoStkPtr && _G.useWreg) {
3074 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3075
3076         /* The last byte in the assignment is in W */
3077         if(areg <= GpsuedoStkPtr) {
3078           size--;
3079           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3080           offset++;
3081 //          debugf("receive from WREG\n", 0);
3082         }
3083         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3084       }
3085 //      GpsuedoStkPtr++;
3086       _G.stack_lat = AOP_SIZE(oper)-1;
3087
3088       while (size) {
3089         size--;
3090         GpsuedoStkPtr++;
3091         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3092 //        debugf("receive from STACK\n", 0);
3093         offset++;
3094       }
3095     }
3096 }
3097
3098
3099 /*-----------------------------------------------------------------*/
3100 /* genIpush - generate code for pushing this gets a little complex */
3101 /*-----------------------------------------------------------------*/
3102 static void genIpush (iCode *ic)
3103 {
3104 //  int size, offset=0;
3105
3106   FENTRY;
3107   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3108
3109   if(ic->parmPush) {
3110     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3111
3112     /* send to stack as normal */
3113     addSet(&_G.sendSet,ic);
3114 //    addSetHead(&_G.sendSet,ic);
3115     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3116   }
3117
3118         
3119 #if 0
3120     int size, offset = 0 ;
3121     char *l;
3122
3123
3124     /* if this is not a parm push : ie. it is spill push 
3125     and spill push is always done on the local stack */
3126     if (!ic->parmPush) {
3127
3128         /* and the item is spilt then do nothing */
3129         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3130             return ;
3131
3132         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3133         size = AOP_SIZE(IC_LEFT(ic));
3134         /* push it on the stack */
3135         while(size--) {
3136             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3137             if (*l == '#') {
3138                 MOVA(l);
3139                 l = "acc";
3140             }
3141             pic16_emitcode("push","%s",l);
3142         }
3143         return ;        
3144     }
3145
3146     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3147 #endif
3148 }
3149
3150 /*-----------------------------------------------------------------*/
3151 /* genIpop - recover the registers: can happen only for spilling   */
3152 /*-----------------------------------------------------------------*/
3153 static void genIpop (iCode *ic)
3154 {
3155   FENTRY;
3156   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3157 #if 0
3158     int size,offset ;
3159
3160
3161     /* if the temp was not pushed then */
3162     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3163         return ;
3164
3165     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3166     size = AOP_SIZE(IC_LEFT(ic));
3167     offset = (size-1);
3168     while (size--) 
3169         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3170                                    FALSE,TRUE));
3171
3172     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3173 #endif
3174 }
3175
3176 #if 0
3177 /*-----------------------------------------------------------------*/
3178 /* unsaverbank - restores the resgister bank from stack            */
3179 /*-----------------------------------------------------------------*/
3180 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3181 {
3182   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3183 #if 0
3184     int i;
3185     asmop *aop ;
3186     regs *r = NULL;
3187
3188     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3189     if (popPsw) {
3190         if (options.useXstack) {
3191             aop = newAsmop(0);
3192             r = getFreePtr(ic,&aop,FALSE);
3193             
3194             
3195             pic16_emitcode("mov","%s,_spx",r->name);
3196             pic16_emitcode("movx","a,@%s",r->name);
3197             pic16_emitcode("mov","psw,a");
3198             pic16_emitcode("dec","%s",r->name);
3199             
3200         }else
3201             pic16_emitcode ("pop","psw");
3202     }
3203
3204     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3205         if (options.useXstack) {       
3206             pic16_emitcode("movx","a,@%s",r->name);
3207             //pic16_emitcode("mov","(%s+%d),a",
3208             //       regspic16[i].base,8*bank+regspic16[i].offset);
3209             pic16_emitcode("dec","%s",r->name);
3210
3211         } else 
3212           pic16_emitcode("pop",""); //"(%s+%d)",
3213         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3214     }
3215
3216     if (options.useXstack) {
3217
3218         pic16_emitcode("mov","_spx,%s",r->name);
3219         pic16_freeAsmop(NULL,aop,ic,TRUE);
3220
3221     }
3222 #endif 
3223 }
3224
3225 /*-----------------------------------------------------------------*/
3226 /* saverbank - saves an entire register bank on the stack          */
3227 /*-----------------------------------------------------------------*/
3228 static void saverbank (int bank, iCode *ic, bool pushPsw)
3229 {
3230   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3231 #if 0
3232     int i;
3233     asmop *aop ;
3234     regs *r = NULL;
3235
3236     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3237     if (options.useXstack) {
3238
3239         aop = newAsmop(0);
3240         r = getFreePtr(ic,&aop,FALSE);  
3241         pic16_emitcode("mov","%s,_spx",r->name);
3242
3243     }
3244
3245     for (i = 0 ; i < pic16_nRegs ;i++) {
3246         if (options.useXstack) {
3247             pic16_emitcode("inc","%s",r->name);
3248             //pic16_emitcode("mov","a,(%s+%d)",
3249             //         regspic16[i].base,8*bank+regspic16[i].offset);
3250             pic16_emitcode("movx","@%s,a",r->name);           
3251         } else 
3252           pic16_emitcode("push","");// "(%s+%d)",
3253                      //regspic16[i].base,8*bank+regspic16[i].offset);
3254     }
3255     
3256     if (pushPsw) {
3257         if (options.useXstack) {
3258             pic16_emitcode("mov","a,psw");
3259             pic16_emitcode("movx","@%s,a",r->name);     
3260             pic16_emitcode("inc","%s",r->name);
3261             pic16_emitcode("mov","_spx,%s",r->name);       
3262             pic16_freeAsmop (NULL,aop,ic,TRUE);
3263             
3264         } else
3265             pic16_emitcode("push","psw");
3266         
3267         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3268     }
3269     ic->bankSaved = 1;
3270 #endif
3271 }
3272 #endif  /* 0 */
3273
3274
3275 static int wparamCmp(void *p1, void *p2)
3276 {
3277   return (!strcmp((char *)p1, (char *)p2));
3278 }
3279
3280 int inWparamList(char *s)
3281 {
3282   return isinSetWith(wparamList, s, wparamCmp);
3283
3284
3285
3286 /*-----------------------------------------------------------------*/
3287 /* genCall - generates a call statement                            */
3288 /*-----------------------------------------------------------------*/
3289 static void genCall (iCode *ic)
3290 {
3291   sym_link *ftype;   
3292   int stackParms=0;
3293   int use_wreg=0;
3294   int inwparam=0;
3295   char *fname;
3296   
3297     FENTRY;
3298
3299     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3300     /* if caller saves & we have not saved then */
3301 //    if (!ic->regsSaved)
3302 //      saveRegisters(ic);
3303
3304         /* initialise stackParms for IPUSH pushes */
3305 //      stackParms = psuedoStkPtr;
3306 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3307     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3308     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3309
3310 #if 0
3311     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3312 #endif
3313
3314     /* if send set is not empty the assign */
3315     if (_G.sendSet) {
3316       iCode *sic;
3317       int psuedoStkPtr=-1; 
3318       int firstTimeThruLoop = 1;
3319
3320
3321         /* reverse sendSet if function is not reentrant */
3322         if(!IFFUNC_ISREENT(ftype))
3323           _G.sendSet = reverseSet(_G.sendSet);
3324
3325         /* First figure how many parameters are getting passed */
3326         stackParms = 0;
3327         use_wreg = 0;
3328         
3329         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3330           int size;
3331 //          int offset = 0;
3332
3333             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3334             size = AOP_SIZE(IC_LEFT(sic));
3335
3336             stackParms += size;
3337
3338             /* pass the last byte through WREG */
3339             if(inwparam) {
3340
3341               while (size--) {
3342                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3343                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3344                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3345
3346                 if(!firstTimeThruLoop) {
3347                   /* If this is not the first time we've been through the loop
3348                    * then we need to save the parameter in a temporary
3349                    * register. The last byte of the last parameter is
3350                    * passed in W. */
3351
3352                   pushw();
3353 //                  --psuedoStkPtr;             // sanity check
3354                   use_wreg = 1;
3355                 }
3356                 
3357                 firstTimeThruLoop=0;
3358
3359                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3360
3361 //                offset++;
3362               }
3363             } else {
3364               /* all arguments are passed via stack */
3365               use_wreg = 0;
3366
3367               while (size--) {
3368                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3369                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3370                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3371
3372 //                pushaop(AOP(IC_LEFT(sic)), size);
3373                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3374                                 
3375                 if(!_G.resDirect)
3376                   pushw();
3377               }
3378             }
3379
3380             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3381           }
3382
3383           if(inwparam) {
3384             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3385               pushw();  /* save last parameter to stack if functions has varargs */
3386               use_wreg = 0;
3387             } else
3388               use_wreg = 1;
3389           } else use_wreg = 0;
3390
3391           _G.stackRegSet = _G.sendSet;
3392           _G.sendSet = NULL;
3393     }
3394
3395     /* make the call */
3396     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3397
3398     GpsuedoStkPtr=0;
3399     
3400     /* if we need to assign a result value */
3401     if ((IS_ITEMP(IC_RESULT(ic))
3402           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3403               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3404         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3405
3406       _G.accInUse++;
3407       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3408       _G.accInUse--;
3409
3410       /* Must not assign an 8-bit result to a 16-bit variable;
3411        * this would use (used...) the uninitialized PRODL! */
3412       /* FIXME: Need a proper way to obtain size of function result type,
3413        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
3414       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
3415
3416       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3417                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3418                 
3419       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3420     }
3421
3422     if(!stackParms && ic->parmBytes) {
3423       stackParms = ic->parmBytes;
3424     }
3425       
3426     stackParms -= use_wreg;
3427     
3428     if(stackParms>0) {
3429       if(stackParms == 1) {
3430         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3431       } else {
3432         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3433         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3434       }
3435       if(STACK_MODEL_LARGE) {
3436         emitSKPNC;
3437         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3438       }
3439     }
3440
3441 #if 0
3442     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3443 #endif
3444
3445     /* adjust the stack for parameters if required */
3446 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3447
3448 #if 0
3449       /* if register bank was saved then pop them */
3450       if (ic->bankSaved)
3451         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3452
3453       /* if we hade saved some registers then unsave them */
3454       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3455         unsaveRegisters (ic);
3456 #endif
3457 }
3458
3459
3460
3461 /*-----------------------------------------------------------------*/
3462 /* genPcall - generates a call by pointer statement                */
3463 /*            new version, created from genCall - HJD              */
3464 /*-----------------------------------------------------------------*/
3465 static void genPcall (iCode *ic)
3466 {
3467   sym_link *fntype;
3468   int stackParms=0;
3469   symbol *retlbl = newiTempLabel(NULL);
3470   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3471   
3472     FENTRY;
3473
3474     fntype = operandType( IC_LEFT(ic) )->next;
3475
3476     /* if send set is not empty the assign */
3477     if (_G.sendSet) {
3478       iCode *sic;
3479       int psuedoStkPtr=-1; 
3480
3481       /* reverse sendSet if function is not reentrant */
3482       if(!IFFUNC_ISREENT(fntype))
3483         _G.sendSet = reverseSet(_G.sendSet);
3484
3485       stackParms = 0;
3486       
3487       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3488         int size;
3489
3490           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3491           size = AOP_SIZE(IC_LEFT(sic));
3492           stackParms += size;
3493
3494           /* all parameters are passed via stack, since WREG is clobbered
3495            * by the calling sequence */
3496           while (size--) {
3497             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3498             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3499             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3500
3501             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3502             pushw();
3503           }
3504
3505           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3506       }
3507
3508       _G.stackRegSet = _G.sendSet;
3509       _G.sendSet = NULL;
3510     }
3511
3512     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3513
3514     // push return address
3515     // push $ on return stack, then replace with retlbl
3516
3517     /* Thanks to Thorsten Klose for pointing out that the following
3518      * snippet should be interrupt safe */
3519     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3520     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3521
3522     pic16_emitpcodeNULLop(POC_PUSH);
3523
3524     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3525     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3526     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3527     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3528     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3529     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3530
3531
3532     /* restore interrupt control register */
3533     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3534     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3535
3536     /* make the call by writing the pointer into pc */
3537     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3538     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3539
3540     // note: MOVFF to PCL not allowed
3541     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3542     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3543
3544
3545     /* return address is here: (X) */
3546     pic16_emitpLabelFORCE(retlbl->key);
3547
3548     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3549
3550     GpsuedoStkPtr=0;
3551     /* if we need assign a result value */
3552     if ((IS_ITEMP(IC_RESULT(ic))
3553           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3554               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3555         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3556
3557       _G.accInUse++;
3558       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3559       _G.accInUse--;
3560
3561       /* FIXME: Need proper way to obtain the function result's type.
3562        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
3563       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
3564
3565       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3566               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3567                 
3568       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3569     }
3570
3571 //    stackParms -= use_wreg;
3572     
3573     if(stackParms>0) {
3574       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3575       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3576       if(STACK_MODEL_LARGE) {
3577         emitSKPNC;
3578         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3579       }
3580     }
3581 }
3582
3583 /*-----------------------------------------------------------------*/
3584 /* resultRemat - result  is rematerializable                       */
3585 /*-----------------------------------------------------------------*/
3586 static int resultRemat (iCode *ic)
3587 {
3588   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3589   if (SKIP_IC(ic) || ic->op == IFX)
3590     return 0;
3591
3592   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3593     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3594     if (sym->remat && !POINTER_SET(ic)) 
3595       return 1;
3596   }
3597
3598   return 0;
3599 }
3600
3601 #if 0
3602 /*-----------------------------------------------------------------*/
3603 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3604 /*-----------------------------------------------------------------*/
3605 static bool inExcludeList(char *s)
3606 {
3607   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3608     int i =0;
3609     
3610     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3611     if (options.excludeRegs[i] &&
3612     STRCASECMP(options.excludeRegs[i],"none") == 0)
3613         return FALSE ;
3614
3615     for ( i = 0 ; options.excludeRegs[i]; i++) {
3616         if (options.excludeRegs[i] &&
3617         STRCASECMP(s,options.excludeRegs[i]) == 0)
3618             return TRUE;
3619     }
3620     return FALSE ;
3621 }
3622 #endif
3623
3624 /*-----------------------------------------------------------------*/
3625 /* genFunction - generated code for function entry                 */
3626 /*-----------------------------------------------------------------*/
3627 static void genFunction (iCode *ic)
3628 {
3629   symbol *sym;
3630   sym_link *ftype;
3631   
3632     FENTRY;
3633     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3634
3635     pic16_labelOffset += (max_key+4);
3636     max_key=0;
3637     GpsuedoStkPtr=0;
3638     _G.nRegsSaved = 0;
3639         
3640     ftype = operandType(IC_LEFT(ic));
3641     sym = OP_SYMBOL(IC_LEFT(ic));
3642
3643     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3644       /* create an absolute section at the interrupt vector:
3645        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3646       symbol *asym;
3647       char asymname[128];
3648       pBlock *apb;
3649
3650 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3651
3652         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3653           sprintf(asymname, "ivec_%s", sym->name);
3654         else
3655           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3656   
3657         /* when an interrupt is declared as naked, do not emit the special
3658          * wrapper segment at vector address. The user should take care for
3659          * this instead. -- VR */
3660
3661         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3662           asym = newSymbol(asymname, 0);
3663           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3664           pic16_addpBlock( apb );
3665
3666           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3667           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3668           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3669           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3670           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3671                 
3672           /* mark the end of this tiny function */
3673           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3674         } else {
3675           sprintf(asymname, "%s", sym->rname);
3676         }
3677
3678         {
3679           absSym *abSym;
3680
3681             abSym = Safe_calloc(1, sizeof(absSym));
3682             strcpy(abSym->name, asymname);
3683
3684             switch( FUNC_INTNO(sym->type) ) {
3685               case 0: abSym->address = 0x000000; break;
3686               case 1: abSym->address = 0x000008; break;
3687               case 2: abSym->address = 0x000018; break;
3688               
3689               default:
3690 //                fprintf(stderr, "no interrupt number is given\n");
3691                 abSym->address = -1; break;
3692             }
3693
3694             /* relocate interrupt vectors if needed */
3695             if(abSym->address != -1)
3696               abSym->address += pic16_options.ivt_loc;
3697
3698             addSet(&absSymSet, abSym);
3699         }
3700     }
3701
3702     /* create the function header */
3703     pic16_emitcode(";","-----------------------------------------");
3704     pic16_emitcode(";"," function %s",sym->name);
3705     pic16_emitcode(";","-----------------------------------------");
3706
3707     /* prevent this symbol from being emitted as 'extern' */
3708     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3709
3710     pic16_emitcode("","%s:",sym->rname);
3711     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3712
3713     {
3714       absSym *ab;
3715
3716         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3717           if(!strcmp(ab->name, sym->rname)) {
3718             pic16_pBlockConvert2Absolute(pb);
3719             break;
3720           }
3721         }
3722     }
3723
3724     if(IFFUNC_ISNAKED(ftype)) {
3725       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3726       return;
3727     }
3728         
3729     /* if critical function then turn interrupts off */
3730     if (IFFUNC_ISCRITICAL(ftype)) {
3731       //pic16_emitcode("clr","ea");
3732     }
3733
3734     currFunc = sym;             /* update the currFunc symbol */
3735     _G.fregsUsed = sym->regsUsed;
3736     _G.sregsAlloc = newBitVect(128);
3737     
3738
3739     /* if this is an interrupt service routine then
3740      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3741     if (IFFUNC_ISISR(sym->type)) {
3742         _G.usefastretfie = 1;   /* use shadow registers by default */
3743         
3744         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3745         if(!FUNC_ISSHADOWREGS(sym->type)) {
3746           /* do not save WREG,STATUS,BSR for high priority interrupts
3747            * because they are stored in the hardware shadow registers already */
3748           _G.usefastretfie = 0;
3749           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3750           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3751           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3752         }
3753
3754         /* these should really be optimized somehow, because not all
3755          * interrupt handlers modify them */
3756         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3757         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3758         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3759         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3760         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3761         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3762         
3763 //        pic16_pBlockConvert2ISR(pb);
3764     }
3765
3766     /* emit code to setup stack frame if user enabled,
3767      * and function is not main() */
3768     
3769 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3770     if(strcmp(sym->name, "main")) {
3771       if(0 
3772         || !options.ommitFramePtr 
3773 //        || sym->regsUsed
3774         || IFFUNC_ARGS(sym->type)
3775         || FUNC_HASSTACKPARM(sym->etype)
3776         ) {
3777         /* setup the stack frame */
3778         if(STACK_MODEL_LARGE)
3779           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3780         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3781
3782         if(STACK_MODEL_LARGE)
3783           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3784         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3785       }
3786     }
3787
3788     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3789           && sym->stack) {
3790
3791       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3792
3793       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3794       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3795       emitSKPC;
3796       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3797     }
3798           
3799     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3800       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3801         _G.useWreg = 0;
3802       else
3803         _G.useWreg = 1;
3804     } else
3805       _G.useWreg = 0;
3806
3807     /* if callee-save to be used for this function
3808      * then save the registers being used in this function */
3809 //    if (IFFUNC_CALLEESAVES(sym->type))
3810     if(strcmp(sym->name, "main")) {
3811       int i;
3812
3813         /* if any registers used */
3814         if (sym->regsUsed) {
3815                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3816
3817           if(!xinst) {
3818             /* save the registers used */
3819             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3820             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3821               if (bitVectBitValue(sym->regsUsed,i)) {
3822 #if 0
3823                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3824 #endif
3825                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3826                 _G.nRegsSaved++;
3827
3828                 if(!pic16_regWithIdx(i)->wasUsed) {
3829                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3830                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3831                   pic16_regWithIdx(i)->wasUsed = 1;
3832                 }
3833               }
3834             }
3835           } else {
3836             
3837             /* xinst */
3838             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3839             for(i=0;i<sym->regsUsed->size;i++) {
3840               if(bitVectBitValue(sym->regsUsed, i)) {
3841                 _G.nRegsSaved++;
3842               }
3843             }
3844                         
3845 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3846           }
3847
3848           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3849
3850         }
3851     }
3852         
3853     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3854 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3855 }
3856
3857 /*-----------------------------------------------------------------*/
3858 /* genEndFunction - generates epilogue for functions               */
3859 /*-----------------------------------------------------------------*/
3860 static void genEndFunction (iCode *ic)
3861 {
3862   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3863
3864     FENTRY;
3865
3866     if(IFFUNC_ISNAKED(sym->type)) {
3867       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3868       return;
3869     }
3870
3871     _G.stack_lat = 0;
3872
3873     /* add code for ISCRITICAL */
3874     if(IFFUNC_ISCRITICAL(sym->type)) {
3875       /* if critical function, turn on interrupts */
3876       
3877       /* TODO: add code here -- VR */
3878     }
3879     
3880 //    sym->regsUsed = _G.fregsUsed;
3881     
3882     /* now we need to restore the registers */
3883     /* if any registers used */
3884
3885     /* first restore registers that might be used for stack access */
3886     if(_G.sregsAllocSet) {
3887     regs *sr;
3888     
3889       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3890       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3891         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3892       }
3893     }
3894
3895     if (strcmp(sym->name, "main") && sym->regsUsed) {
3896       int i;
3897
3898         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3899         /* restore registers used */
3900         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3901         for ( i = sym->regsUsed->size; i >= 0; i--) {
3902           if (bitVectBitValue(sym->regsUsed,i)) {
3903             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3904             _G.nRegsSaved--;
3905           }
3906         }
3907         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3908     }
3909
3910       
3911
3912     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3913           && sym->stack) {
3914       if (sym->stack == 1) {
3915         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3916         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3917       } else {
3918         // we have to add more than one...
3919         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3920         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3921         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3922         emitSKPNC;
3923         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3924         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3925         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3926       }
3927     }
3928
3929     if(strcmp(sym->name, "main")) {
3930       if(0
3931         || !options.ommitFramePtr
3932 //        || sym->regsUsed
3933         || IFFUNC_ARGS(sym->type)
3934         || FUNC_HASSTACKPARM(sym->etype)
3935         ) {
3936         /* restore stack frame */
3937         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3938         if(STACK_MODEL_LARGE)
3939           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3940       }
3941     }
3942
3943     _G.useWreg = 0;
3944
3945     if (IFFUNC_ISISR(sym->type)) {
3946       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3947       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3948       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3949       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3950       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3951       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3952
3953       if(!FUNC_ISSHADOWREGS(sym->type)) {
3954         /* do not restore interrupt vector for WREG,STATUS,BSR
3955          * for high priority interrupt, see genFunction */
3956         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3957         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3958         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3959       }
3960 //      _G.interruptvector = 0;         /* sanity check */
3961
3962
3963       /* if debug then send end of function */
3964 /*      if (options.debug && currFunc)  */
3965       if (currFunc) {
3966         debugFile->writeEndFunction (currFunc, ic, 1);
3967       }
3968         
3969       if(_G.usefastretfie)
3970         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3971       else
3972         pic16_emitpcodeNULLop(POC_RETFIE);
3973
3974       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3975       
3976       _G.usefastretfie = 0;
3977       return;
3978     }
3979
3980     if (IFFUNC_ISCRITICAL(sym->type)) {
3981       pic16_emitcode("setb","ea");
3982     }
3983
3984     /* if debug then send end of function */
3985     if (currFunc) {
3986       debugFile->writeEndFunction (currFunc, ic, 1);
3987     }
3988
3989     /* insert code to restore stack frame, if user enabled it
3990      * and function is not main() */
3991          
3992
3993     pic16_emitpcodeNULLop(POC_RETURN);
3994
3995     /* Mark the end of a function */
3996     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3997 }
3998
3999
4000 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
4001 {
4002   unsigned long lit=1;
4003   operand *op;
4004   
4005     op = IC_LEFT(ic);
4006   
4007     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4008     if(AOP_TYPE(op) == AOP_LIT) {
4009       if(!IS_FLOAT(operandType( op ))) {
4010         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4011       } else {
4012         union {
4013           unsigned long lit_int;
4014           float lit_float;
4015         } info;
4016         
4017         /* take care if literal is a float */
4018         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4019         lit = info.lit_int;
4020       }
4021     }
4022
4023     if (AOP_TYPE(op) == AOP_LIT) {
4024       /* FIXME: broken for
4025        *   char __at(0x456) foo;
4026        *   return &foo;
4027        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4028       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4029     } else if (AOP_TYPE(op) == AOP_PCODE
4030                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4031       /* char *s= "aaa"; return s; */
4032       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4033        *      that the generic pointer is interpreted correctly
4034        *      as referring to __code space, but this is fragile! */
4035       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4036       /* XXX: should check that dest != WREG */
4037       pic16_emitpcode(POC_MOVWF, dest);
4038     } else {
4039       if(dest->type == PO_WREG && (offset == 0)) {
4040         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4041         return;
4042       }
4043       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4044     }
4045 }
4046
4047 /*-----------------------------------------------------------------*/
4048 /* genRet - generate code for return statement                     */
4049 /*-----------------------------------------------------------------*/
4050 static void genRet (iCode *ic)
4051 {
4052   int size;
4053   operand *left;
4054
4055     FENTRY;
4056         /* if we have no return value then
4057          * just generate the "ret" */
4058         
4059         if (!IC_LEFT(ic)) 
4060                 goto jumpret;       
4061     
4062         /* we have something to return then
4063          * move the return value into place */
4064         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4065         size = AOP_SIZE(IC_LEFT(ic));
4066
4067         if(size <= 4) {
4068           if(size>3)
4069             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4070           
4071           if(size>2)
4072             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4073
4074           if(size>1)
4075             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4076           
4077           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4078
4079         } else {
4080                 /* >32-bits, setup stack and FSR0 */
4081                 while (size--) {
4082 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4083 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4084
4085                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4086
4087 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4088                         GpsuedoStkPtr++;
4089                 }
4090                         
4091                 /* setup FSR0 */
4092                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4093                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4094
4095                 if(STACK_MODEL_LARGE) {
4096                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4097                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4098                 } else {
4099                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4100                 }
4101         }
4102                                 
4103 #if 0
4104         /* old code, left here for reference -- VR */    
4105         while (size--) {
4106           char *l ;
4107
4108                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4109                         /* #NOCHANGE */
4110                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4111                         pic16_emitpcomment("push %s",l);
4112                         pushed++;
4113                 } else {
4114                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4115                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4116                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4117                         
4118                         if (strcmp(fReturn[offset],l)) {
4119                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4120                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4121                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4122                                 } else {
4123                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4124                                 }
4125                                 
4126                                 if(size) {
4127                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4128                                 }
4129                                 offset++;
4130                         }
4131                 }
4132         }    
4133
4134         if (pushed) {
4135                 while(pushed) {
4136                         pushed--;
4137                         if (strcmp(fReturn[pushed],"a"))
4138                                 pic16_emitcode("pop",fReturn[pushed]);
4139                         else
4140                                 pic16_emitcode("pop","acc");
4141                 }
4142         }
4143 #endif
4144
4145
4146         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4147     
4148 jumpret:
4149         /* generate a jump to the return label
4150          * if the next is not the return statement */
4151         if (!(ic->next && ic->next->op == LABEL
4152                 && IC_LABEL(ic->next) == returnLabel)) {
4153         
4154                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4155                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4156         }
4157 }
4158
4159 /*-----------------------------------------------------------------*/
4160 /* genLabel - generates a label                                    */
4161 /*-----------------------------------------------------------------*/
4162 static void genLabel (iCode *ic)
4163 {
4164   FENTRY;
4165
4166   /* special case never generate */
4167   if (IC_LABEL(ic) == entryLabel)
4168     return ;
4169
4170   pic16_emitpLabel(IC_LABEL(ic)->key);
4171 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4172 }
4173
4174 /*-----------------------------------------------------------------*/
4175 /* genGoto - generates a goto                                      */
4176 /*-----------------------------------------------------------------*/
4177 //tsd
4178 static void genGoto (iCode *ic)
4179 {
4180   FENTRY;
4181   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4182 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4183 }
4184
4185
4186 /*-----------------------------------------------------------------*/
4187 /* genMultbits :- multiplication of bits                           */
4188 /*-----------------------------------------------------------------*/
4189 static void genMultbits (operand *left, 
4190                          operand *right, 
4191                          operand *result)
4192 {
4193   FENTRY;
4194
4195   if(!pic16_sameRegs(AOP(result),AOP(right)))
4196     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4197
4198   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4199   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4200   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4201
4202 }
4203
4204
4205 /*-----------------------------------------------------------------*/
4206 /* genMultOneByte : 8 bit multiplication & division                */
4207 /*-----------------------------------------------------------------*/
4208 static void genMultOneByte (operand *left,
4209                             operand *right,
4210                             operand *result)
4211 {
4212
4213   FENTRY;
4214   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4215   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4216
4217   /* (if two literals, the value is computed before) */
4218   /* if one literal, literal on the right */
4219   if (AOP_TYPE(left) == AOP_LIT){
4220     operand *t = right;
4221     right = left;
4222     left = t;
4223   }
4224
4225         /* size is already checked in genMult == 1 */
4226 //      size = AOP_SIZE(result);
4227
4228         if (AOP_TYPE(right) == AOP_LIT){
4229                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4230                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4231                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4232                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4233         } else {
4234                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4235                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4236                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4237                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4238         }
4239         
4240         pic16_genMult8X8_n (left, right,result);
4241 }
4242
4243 #if 0
4244 /*-----------------------------------------------------------------*/
4245 /* genMultOneWord : 16 bit multiplication                          */
4246 /*-----------------------------------------------------------------*/
4247 static void genMultOneWord (operand *left,
4248                             operand *right,
4249                             operand *result)
4250 {
4251   FENTRY;
4252   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4253   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4254
4255   /* (if two literals, the value is computed before)
4256    * if one literal, literal on the right */
4257   if (AOP_TYPE(left) == AOP_LIT){
4258     operand *t = right;
4259     right = left;
4260     left = t;
4261   }
4262
4263   /* size is checked already == 2 */
4264 //  size = AOP_SIZE(result);
4265
4266   if (AOP_TYPE(right) == AOP_LIT) {
4267     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4268       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4269       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4270       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4271   } else {
4272     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4273       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4274       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4275       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4276   }
4277         
4278   pic16_genMult16X16_16(left, right,result);
4279 }
4280 #endif
4281
4282 #if 0
4283 /*-----------------------------------------------------------------*/
4284 /* genMultOneLong : 32 bit multiplication                          */
4285 /*-----------------------------------------------------------------*/
4286 static void genMultOneLong (operand *left,
4287                             operand *right,
4288                             operand *result)
4289 {
4290   FENTRY;
4291   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4292   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4293
4294   /* (if two literals, the value is computed before)
4295    * if one literal, literal on the right */
4296   if (AOP_TYPE(left) == AOP_LIT){
4297     operand *t = right;
4298     right = left;
4299     left = t;
4300   }
4301
4302   /* size is checked already == 4 */
4303 //  size = AOP_SIZE(result);
4304
4305   if (AOP_TYPE(right) == AOP_LIT) {
4306     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4307         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4308         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4309         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4310   } else {
4311     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4312         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4313         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4314         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4315   }
4316         
4317   pic16_genMult32X32_32(left, right,result);
4318 }
4319 #endif
4320
4321
4322
4323 /*-----------------------------------------------------------------*/
4324 /* genMult - generates code for multiplication                     */
4325 /*-----------------------------------------------------------------*/
4326 static void genMult (iCode *ic)
4327 {
4328   operand *left = IC_LEFT(ic);
4329   operand *right = IC_RIGHT(ic);
4330   operand *result= IC_RESULT(ic);   
4331
4332     FENTRY;
4333         /* assign the amsops */
4334         pic16_aopOp (left,ic,FALSE);
4335         pic16_aopOp (right,ic,FALSE);
4336         pic16_aopOp (result,ic,TRUE);
4337
4338         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4339
4340         /* special cases first *
4341         * both are bits */
4342         if (AOP_TYPE(left) == AOP_CRY
4343                 && AOP_TYPE(right)== AOP_CRY) {
4344                 genMultbits(left,right,result);
4345           goto release ;
4346         }
4347
4348         /* if both are of size == 1 */
4349         if(AOP_SIZE(left) == 1
4350                 && AOP_SIZE(right) == 1) {
4351                 genMultOneByte(left,right,result);
4352           goto release ;
4353         }
4354
4355 #if 0
4356         /* if both are of size == 2 */
4357         if(AOP_SIZE(left) == 2
4358                 && AOP_SIZE(right) == 2) {
4359                 genMultOneWord(left, right, result);
4360           goto release;
4361         }
4362         
4363         /* if both are of size == 4 */
4364         if(AOP_SIZE(left) == 4
4365                 && AOP_SIZE(right) == 4) {
4366                 genMultOneLong(left, right, result);
4367           goto release;
4368         }
4369 #endif
4370
4371         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4372         assert( !"Multiplication should have been transformed into function call!" );
4373
4374         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4375
4376
4377         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4378         /* should have been converted to function call */
4379         assert(0) ;
4380
4381 release :
4382         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4383         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4384         pic16_freeAsmop(result,NULL,ic,TRUE); 
4385 }
4386
4387 #if 0
4388 /*-----------------------------------------------------------------*/
4389 /* genDivbits :- division of bits                                  */
4390 /*-----------------------------------------------------------------*/
4391 static void genDivbits (operand *left, 
4392                         operand *right, 
4393                         operand *result)
4394 {
4395   char *l;
4396
4397     FENTRY;
4398     /* the result must be bit */    
4399     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4400     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4401
4402     MOVA(l);    
4403
4404     pic16_emitcode("div","ab");
4405     pic16_emitcode("rrc","a");
4406     pic16_aopPut(AOP(result),"c",0);
4407 }
4408
4409 /*-----------------------------------------------------------------*/
4410 /* genDivOneByte : 8 bit division                                  */
4411 /*-----------------------------------------------------------------*/
4412 static void genDivOneByte (operand *left,
4413                            operand *right,
4414                            operand *result)
4415 {
4416   sym_link *opetype = operandType(result);
4417   char *l ;
4418   symbol *lbl ;
4419   int size,offset;
4420
4421         /* result = divident / divisor
4422          * - divident may be a register or a literal,
4423          * - divisor may be a register or a literal,
4424          * so there are 3 cases (literal / literal is optimized
4425          * by the front-end) to handle.
4426          * In addition we must handle signed and unsigned, which
4427          * result in 6 final different cases -- VR */
4428
4429     FENTRY;
4430     
4431     size = AOP_SIZE(result) - 1;
4432     offset = 1;
4433     /* signed or unsigned */
4434     if (SPEC_USIGN(opetype)) {
4435       pCodeOp *pct1,    /* count */
4436                 *pct2,  /* reste */
4437                 *pct3;  /* temp */
4438       symbol *label1, *label2, *label3;;
4439
4440
4441         /* unsigned is easy */
4442
4443         pct1 = pic16_popGetTempReg(1);
4444         pct2 = pic16_popGetTempReg(1);
4445         pct3 = pic16_popGetTempReg(1);
4446         
4447         label1 = newiTempLabel(NULL);
4448         label2 = newiTempLabel(NULL);
4449         label3 = newiTempLabel(NULL);
4450
4451         /* the following algorithm is extracted from divuint.c */
4452
4453         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4454         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4455         
4456         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4457
4458         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4459         
4460         pic16_emitpLabel(label1->key);
4461         
4462         emitCLRC;
4463         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4464
4465
4466         emitCLRC;
4467         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4468         
4469
4470         emitSKPNC;
4471         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4472         
4473         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4474         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4475         
4476         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4477         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4478         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4479         
4480         pic16_emitpLabel( label3->key );
4481         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4482         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4483         
4484         
4485
4486         pic16_emitpLabel(label2->key);
4487         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4488         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4489         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4490         
4491         /* result is in wreg */
4492         if(AOP_TYPE(result) != AOP_ACC)
4493                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4494
4495         pic16_popReleaseTempReg( pct3, 1);
4496         pic16_popReleaseTempReg( pct2, 1);
4497         pic16_popReleaseTempReg( pct1, 1);
4498
4499         return ;
4500     }
4501
4502     /* signed is a little bit more difficult */
4503
4504     /* save the signs of the operands */
4505     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4506     MOVA(l);    
4507     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4508     pic16_emitcode("push","acc"); /* save it on the stack */
4509
4510     /* now sign adjust for both left & right */
4511     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4512     MOVA(l);       
4513     lbl = newiTempLabel(NULL);
4514     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4515     pic16_emitcode("cpl","a");   
4516     pic16_emitcode("inc","a");
4517     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4518     pic16_emitcode("mov","b,a");
4519
4520     /* sign adjust left side */
4521     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4522     MOVA(l);
4523
4524     lbl = newiTempLabel(NULL);
4525     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4526     pic16_emitcode("cpl","a");
4527     pic16_emitcode("inc","a");
4528     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4529
4530     /* now the division */
4531     pic16_emitcode("div","ab");
4532     /* we are interested in the lower order
4533     only */
4534     pic16_emitcode("mov","b,a");
4535     lbl = newiTempLabel(NULL);
4536     pic16_emitcode("pop","acc");   
4537     /* if there was an over flow we don't 
4538     adjust the sign of the result */
4539     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4540     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4541     CLRC;
4542     pic16_emitcode("clr","a");
4543     pic16_emitcode("subb","a,b");
4544     pic16_emitcode("mov","b,a");
4545     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4546
4547     /* now we are done */
4548     pic16_aopPut(AOP(result),"b",0);
4549     if(size > 0){
4550         pic16_emitcode("mov","c,b.7");
4551         pic16_emitcode("subb","a,acc");   
4552     }
4553     while (size--)
4554         pic16_aopPut(AOP(result),"a",offset++);
4555
4556 }
4557 #endif
4558
4559 /*-----------------------------------------------------------------*/
4560 /* genDiv - generates code for division                            */
4561 /*-----------------------------------------------------------------*/
4562 static void genDiv (iCode *ic)
4563 {
4564     operand *left = IC_LEFT(ic);
4565     operand *right = IC_RIGHT(ic);
4566     operand *result= IC_RESULT(ic);   
4567     int negated = 0;
4568     int leftVal = 0, rightVal = 0;
4569     int signedLits = 0;
4570     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4571     int op = 0;
4572     
4573         /* Division is a very lengthy algorithm, so it is better
4574          * to call support routines than inlining algorithm.
4575          * Division functions written here just in case someone
4576          * wants to inline and not use the support libraries -- VR */
4577
4578     FENTRY;
4579     
4580     /* assign the amsops */
4581     pic16_aopOp (left,ic,FALSE);
4582     pic16_aopOp (right,ic,FALSE);
4583     pic16_aopOp (result,ic,TRUE);
4584
4585     if (ic->op == '/')
4586       op = 0;
4587     else if (ic->op == '%')
4588       op = 1;
4589     else
4590       assert( !"invalid operation requested in genDivMod" );
4591
4592     /* get literal values */
4593     if (IS_VALOP(left)) {
4594       leftVal = (int)floatFromVal( OP_VALUE(left) );
4595       assert( leftVal >= -128 && leftVal < 256 );
4596       if (leftVal < 0) { signedLits++; }
4597     }
4598     if (IS_VALOP(right)) {
4599       rightVal = (int)floatFromVal( OP_VALUE(right) );
4600       assert( rightVal >= -128 && rightVal < 256 );
4601       if (rightVal < 0) { signedLits++; }
4602     }
4603
4604     /* We should only come here to convert all
4605      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4606      * with exactly one operand being s8_t into
4607      * u8_t x u8_t -> u8_t. All other cases should have been
4608      * turned into calls to support routines beforehand... */
4609     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4610         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4611     {
4612       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4613           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4614       {
4615         /* Both operands are signed or negative, use _divschar
4616          * instead of _divuchar */
4617         pushaop(AOP(right), 0);
4618         pushaop(AOP(left), 0);
4619
4620         /* call _divschar */
4621         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4622
4623         {
4624           symbol *sym;
4625           sym = newSymbol( functions[op][0], 0 );
4626           sym->used++;
4627           strcpy(sym->rname, functions[op][0]);
4628           checkAddSym(&externs, sym);
4629         }
4630
4631         /* assign result */
4632         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4633         if (AOP_SIZE(result) > 1)
4634         {
4635           pic16_emitpcode(POC_MOVFF,
4636               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4637                 pic16_popGet(AOP(result), 1)));
4638           /* sign extend */
4639           pic16_addSign(result, 2, 1);
4640         }
4641
4642         /* clean up stack */
4643         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4644         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4645
4646         goto release;
4647       }
4648       
4649       /* push right operand */
4650       if (IS_VALOP(right)) {
4651         if (rightVal < 0) {
4652           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4653           negated++;
4654         } else {
4655           pushaop(AOP(right), 0);
4656         }
4657       } else if (!IS_UNSIGNED(operandType(right))) {
4658         pic16_mov2w(AOP(right), 0);
4659         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4660         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4661         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4662         negated++;
4663       } else {
4664         pushaop(AOP(right), 0);
4665       }
4666
4667       /* push left operand */
4668       if (IS_VALOP(left)) {
4669         if (leftVal < 0) {
4670           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4671           negated++;
4672         } else {
4673           pushaop(AOP(left), 0);
4674         }
4675       } else if (!IS_UNSIGNED(operandType(left))) {
4676         pic16_mov2w(AOP(left),0);
4677         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4678         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4679         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4680         negated++;
4681       } else {
4682         pushaop(AOP(left), 0);
4683       }
4684       
4685       /* call _divuchar */
4686       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4687
4688       {
4689         symbol *sym;
4690         sym = newSymbol( functions[op][1], 0 );
4691         sym->used++;
4692         strcpy(sym->rname, functions[op][1]);
4693         checkAddSym(&externs, sym);
4694       }
4695
4696       /* Revert negation(s) from above.
4697        * This is inefficient: if both operands are negative, this
4698        * should not touch WREG. However, determining that exactly
4699        * one operand was negated costs at least 3 instructions,
4700        * so there is nothing to be gained here, is there?
4701        *
4702        * I negate WREG because either operand might share registers with
4703        * result, so assigning first might destroy an operand. */
4704       
4705       /* For the modulus operator, (a/b)*b == a shall hold.
4706        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4707        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
4708        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
4709        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
4710        * Only invert the result if the left operand is negative (sigh).
4711        */
4712       if (AOP_SIZE(result) <= 1 || !negated)
4713       {
4714         if (ic->op == '/')
4715         {
4716           if (IS_VALOP(right)) {
4717             if (rightVal < 0) {
4718               /* we negated this operand above */
4719               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4720             }
4721           } else if (!IS_UNSIGNED(operandType(right))) {
4722             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4723             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4724           }
4725         }
4726
4727         if (IS_VALOP(left)) {
4728           if (leftVal < 0) {
4729             /* we negated this operand above */
4730             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4731           }
4732         } else if (!IS_UNSIGNED(operandType(left))) {
4733           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4734           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4735         }
4736
4737         /* Move result to destination. */
4738         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4739
4740         /* Zero-extend:  no operand was signed (or result is just a byte). */
4741         pic16_addSign(result, 1, 0);
4742       } else {
4743         assert( AOP_SIZE(result) > 1 );
4744         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4745         if (ic->op == '/')
4746         {
4747           if (IS_VALOP(right)) {
4748             if (rightVal < 0) {
4749               /* we negated this operand above */
4750               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4751             }
4752           } else if (!IS_UNSIGNED(operandType(right))) {
4753             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4754             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4755           }
4756         }
4757
4758         if (IS_VALOP(left)) {
4759           if (leftVal < 0) {
4760             /* we negated this operand above */
4761             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4762           }
4763         } else if (!IS_UNSIGNED(operandType(left))) {
4764           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4765           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4766         }
4767
4768         /* Move result to destination. */
4769         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4770
4771         /* Negate result if required. */
4772         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4773         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4774
4775         /* Sign-extend. */
4776         pic16_addSign(result, 2, 1);
4777       }
4778
4779       /* clean up stack */
4780       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4781       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4782       goto release;
4783     }
4784
4785 #if 0
4786     /* special cases first */
4787     /* both are bits */
4788     if (AOP_TYPE(left) == AOP_CRY &&
4789         AOP_TYPE(right)== AOP_CRY) {
4790         genDivbits(left,right,result);
4791         goto release ;
4792     }
4793
4794     /* if both are of size == 1 */
4795     if (AOP_SIZE(left) == 1 &&
4796         AOP_SIZE(right) == 1 ) {
4797         genDivOneByte(left,right,result);
4798         goto release ;
4799     }
4800 #endif
4801
4802     /* should have been converted to function call */
4803     assert(0);
4804 release :
4805     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4806     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4807     pic16_freeAsmop(result,NULL,ic,TRUE); 
4808 }
4809
4810 #if 0
4811 /*-----------------------------------------------------------------*/
4812 /* genModbits :- modulus of bits                                   */
4813 /*-----------------------------------------------------------------*/
4814 static void genModbits (operand *left, 
4815                         operand *right, 
4816                         operand *result)
4817 {
4818   char *l;
4819
4820     FENTRY;  
4821     
4822     werror(W_POSSBUG2, __FILE__, __LINE__);
4823     /* the result must be bit */    
4824     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4825     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4826
4827     MOVA(l);       
4828
4829     pic16_emitcode("div","ab");
4830     pic16_emitcode("mov","a,b");
4831     pic16_emitcode("rrc","a");
4832     pic16_aopPut(AOP(result),"c",0);
4833 }
4834
4835 /*-----------------------------------------------------------------*/
4836 /* genModOneByte : 8 bit modulus                                   */
4837 /*-----------------------------------------------------------------*/
4838 static void genModOneByte (operand *left,
4839                            operand *right,
4840                            operand *result)
4841 {
4842   sym_link *opetype = operandType(result);
4843   char *l ;
4844   symbol *lbl ;
4845
4846     FENTRY;
4847     werror(W_POSSBUG2, __FILE__, __LINE__);
4848
4849     /* signed or unsigned */
4850     if (SPEC_USIGN(opetype)) {
4851         /* unsigned is easy */
4852         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4853         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4854         MOVA(l);    
4855         pic16_emitcode("div","ab");
4856         pic16_aopPut(AOP(result),"b",0);
4857         return ;
4858     }
4859
4860     /* signed is a little bit more difficult */
4861
4862     /* save the signs of the operands */
4863     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4864     MOVA(l);
4865
4866     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4867     pic16_emitcode("push","acc"); /* save it on the stack */
4868
4869     /* now sign adjust for both left & right */
4870     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4871     MOVA(l);
4872
4873     lbl = newiTempLabel(NULL);
4874     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4875     pic16_emitcode("cpl","a");   
4876     pic16_emitcode("inc","a");
4877     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4878     pic16_emitcode("mov","b,a"); 
4879
4880     /* sign adjust left side */
4881     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4882     MOVA(l);
4883
4884     lbl = newiTempLabel(NULL);
4885     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4886     pic16_emitcode("cpl","a");   
4887     pic16_emitcode("inc","a");
4888     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4889
4890     /* now the multiplication */
4891     pic16_emitcode("div","ab");
4892     /* we are interested in the lower order
4893     only */
4894     lbl = newiTempLabel(NULL);
4895     pic16_emitcode("pop","acc");   
4896     /* if there was an over flow we don't 
4897     adjust the sign of the result */
4898     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4899     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4900     CLRC ;
4901     pic16_emitcode("clr","a");
4902     pic16_emitcode("subb","a,b");
4903     pic16_emitcode("mov","b,a");
4904     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4905
4906     /* now we are done */
4907     pic16_aopPut(AOP(result),"b",0);
4908
4909 }
4910 #endif
4911
4912 /*-----------------------------------------------------------------*/
4913 /* genMod - generates code for division                            */
4914 /*-----------------------------------------------------------------*/
4915 static void genMod (iCode *ic)
4916 {
4917   /* Task deferred to genDiv */
4918   genDiv(ic);
4919 #if 0
4920   operand *left = IC_LEFT(ic);
4921   operand *right = IC_RIGHT(ic);
4922   operand *result= IC_RESULT(ic);  
4923
4924     FENTRY;
4925     
4926     /* assign the amsops */
4927     pic16_aopOp (left,ic,FALSE);
4928     pic16_aopOp (right,ic,FALSE);
4929     pic16_aopOp (result,ic,TRUE);
4930
4931     /* special cases first */
4932     /* both are bits */
4933     if (AOP_TYPE(left) == AOP_CRY &&
4934         AOP_TYPE(right)== AOP_CRY) {
4935         genModbits(left,right,result);
4936         goto release ;
4937     }
4938
4939     /* if both are of size == 1 */
4940     if (AOP_SIZE(left) == 1 &&
4941         AOP_SIZE(right) == 1 ) {
4942         genModOneByte(left,right,result);
4943         goto release ;
4944     }
4945
4946     /* should have been converted to function call */
4947     assert(0);
4948
4949 release :
4950     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4951     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4952     pic16_freeAsmop(result,NULL,ic,TRUE); 
4953 #endif
4954 }
4955
4956 /*-----------------------------------------------------------------*/
4957 /* genIfxJump :- will create a jump depending on the ifx           */
4958 /*-----------------------------------------------------------------*/
4959 /*
4960   note: May need to add parameter to indicate when a variable is in bit space.
4961 */
4962 static void genIfxJump (iCode *ic, char *jval)
4963 {
4964   FENTRY;
4965   
4966     /* if true label then we jump if condition
4967     supplied is true */
4968     if ( IC_TRUE(ic) ) {
4969
4970         if(strcmp(jval,"a") == 0)
4971           emitSKPZ;
4972         else if (strcmp(jval,"c") == 0)
4973           emitSKPNC;
4974         else {
4975           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4976           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4977         }
4978
4979         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4980         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4981
4982     }
4983     else {
4984         /* false label is present */
4985         if(strcmp(jval,"a") == 0)
4986           emitSKPNZ;
4987         else if (strcmp(jval,"c") == 0)
4988           emitSKPC;
4989         else {
4990           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4991           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4992         }
4993
4994         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4995         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4996
4997     }
4998
4999
5000     /* mark the icode as generated */
5001     ic->generated = 1;
5002 }
5003
5004 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5005 {
5006   FENTRY;
5007   
5008     /* if true label then we jump if condition
5009     supplied is true */
5010     if ( IC_TRUE(ic) ) {
5011       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
5012       pic16_emitpcode(POC_BTFSC, jop);
5013
5014       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5015       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5016
5017     } else {
5018       /* false label is present */
5019       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5020       pic16_emitpcode(POC_BTFSS, jop);
5021           
5022       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5023       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5024     }
5025
5026
5027     /* mark the icode as generated */
5028     ic->generated = 1;
5029 }
5030
5031 #if 0
5032 // not needed ATM
5033
5034 /*-----------------------------------------------------------------*/
5035 /* genSkip                                                         */
5036 /*-----------------------------------------------------------------*/
5037 static void genSkip(iCode *ifx,int status_bit)
5038 {
5039   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5040   if(!ifx)
5041     return;
5042
5043   if ( IC_TRUE(ifx) ) {
5044     switch(status_bit) {
5045     case 'z':
5046       emitSKPNZ;
5047       break;
5048
5049     case 'c':
5050       emitSKPNC;
5051       break;
5052
5053     case 'd':
5054       emitSKPDC;
5055       break;
5056
5057     }
5058
5059     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5060     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5061
5062   } else {
5063
5064     switch(status_bit) {
5065
5066     case 'z':
5067       emitSKPZ;
5068       break;
5069
5070     case 'c':
5071       emitSKPC;
5072       break;
5073
5074     case 'd':
5075       emitSKPDC;
5076       break;
5077     }
5078     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5079     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5080
5081   }
5082
5083 }
5084 #endif
5085
5086 /*-----------------------------------------------------------------*/
5087 /* genSkipc                                                        */
5088 /*-----------------------------------------------------------------*/
5089 static void genSkipc(resolvedIfx *rifx)
5090 {
5091   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5092   
5093   if(!rifx)
5094     return;
5095
5096   if(rifx->condition)
5097     emitSKPNC;
5098   else
5099     emitSKPC;
5100
5101   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5102   rifx->generated = 1;
5103 }
5104
5105 #if !(USE_SIMPLE_GENCMP)
5106 /*-----------------------------------------------------------------*/
5107 /* genSkipz2                                                       */
5108 /*-----------------------------------------------------------------*/
5109 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5110 {
5111   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5112   
5113   if(!rifx)
5114     return;
5115
5116   if( (rifx->condition ^ invert_condition) & 1)
5117     emitSKPZ;
5118   else
5119     emitSKPNZ;
5120
5121   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5122   rifx->generated = 1;
5123 }
5124 #endif
5125
5126 #if 0
5127 /*-----------------------------------------------------------------*/
5128 /* genSkipz                                                        */
5129 /*-----------------------------------------------------------------*/
5130 static void genSkipz(iCode *ifx, int condition)
5131 {
5132   if(!ifx)
5133     return;
5134
5135   if(condition)
5136     emitSKPNZ;
5137   else
5138     emitSKPZ;
5139
5140   if ( IC_TRUE(ifx) )
5141     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5142   else
5143     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5144
5145   if ( IC_TRUE(ifx) )
5146     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5147   else
5148     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5149
5150 }
5151 #endif
5152
5153 #if !(USE_SIMPLE_GENCMP)
5154 /*-----------------------------------------------------------------*/
5155 /* genSkipCond                                                     */
5156 /*-----------------------------------------------------------------*/
5157 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5158 {
5159   if(!rifx)
5160     return;
5161
5162   if(rifx->condition)
5163     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5164   else
5165     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5166
5167
5168   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5169   rifx->generated = 1;
5170 }
5171 #endif
5172
5173 #if 0
5174 /*-----------------------------------------------------------------*/
5175 /* genChkZeroes :- greater or less than comparison                 */
5176 /*     For each byte in a literal that is zero, inclusive or the   */
5177 /*     the corresponding byte in the operand with W                */
5178 /*     returns true if any of the bytes are zero                   */
5179 /*-----------------------------------------------------------------*/
5180 static int genChkZeroes(operand *op, int lit,  int size)
5181 {
5182
5183   int i;
5184   int flag =1;
5185
5186   while(size--) {
5187     i = (lit >> (size*8)) & 0xff;
5188
5189     if(i==0) {
5190       if(flag) 
5191         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5192       else
5193         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5194       flag = 0;
5195     }
5196   }
5197
5198   return (flag==0);
5199 }
5200 #endif
5201
5202
5203 /*-----------------------------------------------------------------*/
5204 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
5205 /*                  aop (if it's NOT a literal) or from lit (if    */
5206 /*                  aop is a literal)                              */
5207 /*-----------------------------------------------------------------*/
5208 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5209   if (aop->type == AOP_LIT) {
5210     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5211   } else {
5212     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5213   }
5214 }
5215
5216 /*-----------------------------------------------------------------*/
5217 /* genCmp :- greater or less than comparison                       */
5218 /*-----------------------------------------------------------------*/
5219
5220 #if USE_SIMPLE_GENCMP           /* { */
5221
5222 /* genCmp performs a left < right comparison, stores
5223  * the outcome in result (if != NULL) and generates
5224  * control flow code for the ifx (if != NULL).
5225  *
5226  * This version leaves in sequences like
5227  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5228  * which should be optmized by the peephole
5229  * optimizer - RN 2005-01-01 */
5230 static void genCmp (operand *left,operand *right,
5231                     operand *result, iCode *ifx, int sign)
5232 {
5233   resolvedIfx rIfx;
5234   int size;
5235   int offs;
5236   symbol *templbl;
5237   operand *dummy;
5238   unsigned long lit;
5239   unsigned long mask;
5240   int performedLt;
5241
5242   FENTRY;
5243   
5244   assert (left && right);
5245   assert (AOP_SIZE(left) == AOP_SIZE(right));
5246
5247   size = AOP_SIZE(right) - 1;
5248   mask = (0x100UL << (size*8)) - 1;
5249   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5250   performedLt = 1;
5251   templbl = NULL;
5252   lit = 0;
5253   
5254   resolveIfx (&rIfx, ifx);
5255
5256   /* handle for special cases */
5257   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5258       return;
5259
5260   /**********************************************************************
5261    * handle bits - bit compares are promoted to int compares seemingly! *
5262    **********************************************************************/
5263 #if 0
5264   // THIS IS COMPLETELY UNTESTED!
5265   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5266     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5267     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5268     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5269
5270     emitSETC;
5271     // 1 < {0,1} is false --> clear C by skipping the next instruction
5272     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5273     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5274     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5275     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5276     emitCLRC; // only skipped for left=0 && right=1
5277
5278     goto correct_result_in_carry;
5279   } // if
5280 #endif
5281
5282   /*************************************************
5283    * make sure that left is register (or the like) *
5284    *************************************************/
5285   if (!isAOP_REGlike(left)) {
5286     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5287     assert (isAOP_LIT(left));
5288     assert (isAOP_REGlike(right));
5289     // swap left and right
5290     // left < right <==> right > left <==> (right >= left + 1)
5291     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5292
5293     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5294       // MAXVALUE < right? always false
5295       if (performedLt) emitCLRC; else emitSETC;
5296       goto correct_result_in_carry;
5297     } // if
5298
5299     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5300     // that's why we handled it above.
5301     lit++;
5302
5303     dummy = left;
5304     left = right;
5305     right = dummy;
5306
5307     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5308   } else if (isAOP_LIT(right)) {
5309     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5310   } // if
5311
5312   assert (isAOP_REGlike(left)); // left must be register or the like
5313   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5314
5315   /*************************************************
5316    * special cases go here                         *
5317    *************************************************/
5318
5319   if (isAOP_LIT(right)) {
5320     if (!sign) {
5321       // unsigned comparison to a literal
5322       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5323       if (lit == 0) {
5324         // unsigned left < 0? always false
5325         if (performedLt) emitCLRC; else emitSETC;
5326         goto correct_result_in_carry;
5327       }
5328     } else {
5329       // signed comparison to a literal
5330       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5331       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5332         // signed left < 0x80000000? always false
5333         if (performedLt) emitCLRC; else emitSETC;
5334         goto correct_result_in_carry;
5335       } else if (lit == 0) {
5336         // compare left < 0; set CARRY if SIGNBIT(left) is set
5337         if (performedLt) emitSETC; else emitCLRC;
5338         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5339         if (performedLt) emitCLRC; else emitSETC;
5340         goto correct_result_in_carry;
5341       }
5342     } // if (!sign)
5343   } // right is literal
5344
5345   /*************************************************
5346    * perform a general case comparison             *
5347    * make sure we get CARRY==1 <==> left >= right  *
5348    *************************************************/
5349   // compare most significant bytes
5350   //DEBUGpc ("comparing bytes at offset %d", size);
5351   if (!sign) {
5352     // unsigned comparison
5353     mov2w_regOrLit (AOP(right), lit, size);
5354     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5355   } else {
5356     // signed comparison
5357     // (add 2^n to both operands then perform an unsigned comparison)
5358     if (isAOP_LIT(right)) {
5359       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5360       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5361
5362       if (litbyte == 0x80) {
5363         // left >= 0x80 -- always true, but more bytes to come
5364         pic16_mov2w (AOP(left), size);
5365         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5366         emitSETC;
5367       } else {
5368         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5369         pic16_mov2w (AOP(left), size);
5370         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5371         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5372       } // if
5373     } else {
5374       /* using PRODL as a temporary register here */
5375       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5376       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5377       pic16_mov2w (AOP(left), size);
5378       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5379       pic16_emitpcode (POC_MOVWF, pctemp);
5380       pic16_mov2w (AOP(right), size);
5381       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5382       pic16_emitpcode (POC_SUBFW, pctemp);
5383       //pic16_popReleaseTempReg(pctemp, 1);
5384     }
5385   } // if (!sign)
5386
5387   // compare remaining bytes (treat as unsigned case from above)
5388   templbl = newiTempLabel ( NULL );
5389   offs = size;
5390   while (offs--) {
5391     //DEBUGpc ("comparing bytes at offset %d", offs);
5392     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5393     mov2w_regOrLit (AOP(right), lit, offs);
5394     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5395   } // while (offs)
5396   pic16_emitpLabel (templbl->key);
5397   goto result_in_carry;
5398
5399 result_in_carry:
5400   
5401   /****************************************************
5402    * now CARRY contains the result of the comparison: *
5403    * SUBWF sets CARRY iff                             *
5404    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5405    * (F=left, W=right)                                *
5406    ****************************************************/
5407
5408   if (performedLt) {
5409     if (result && AOP_TYPE(result) != AOP_CRY) {
5410       // value will be stored
5411       emitTOGC;
5412     } else {
5413       // value wil only be used in the following genSkipc()
5414       rIfx.condition ^= 1;
5415     }
5416   } // if
5417
5418 correct_result_in_carry:
5419
5420   // assign result to variable (if neccessary)
5421   if (result && AOP_TYPE(result) != AOP_CRY) {
5422     //DEBUGpc ("assign result");
5423     size = AOP_SIZE(result);
5424     while (size--) {
5425       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5426     } // while
5427     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5428   } // if (result)
5429
5430   // perform conditional jump
5431   if (ifx) {
5432     //DEBUGpc ("generate control flow");
5433     genSkipc (&rIfx);
5434     ifx->generated = 1;
5435   } // if
5436 }
5437
5438 #elif 1         /* } */
5439                 /* { */
5440       /* original code */
5441 static void genCmp (operand *left,operand *right,
5442                     operand *result, iCode *ifx, int sign)
5443 {
5444   int size; //, offset = 0 ;
5445   unsigned long lit = 0L,i = 0;
5446   resolvedIfx rFalseIfx;
5447   //  resolvedIfx rTrueIfx;
5448   symbol *truelbl;
5449   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5450 /*
5451   if(ifx) {
5452     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5453     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5454   }
5455 */
5456
5457   FENTRY;
5458   
5459   resolveIfx(&rFalseIfx,ifx);
5460   truelbl  = newiTempLabel(NULL);
5461   size = max(AOP_SIZE(left),AOP_SIZE(right));
5462
5463   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5464
5465 #define _swapp
5466
5467   /* if literal is on the right then swap with left */
5468   if ((AOP_TYPE(right) == AOP_LIT)) {
5469     operand *tmp = right ;
5470     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5471     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5472 #ifdef _swapp
5473
5474     lit = (lit - 1) & mask;
5475     right = left;
5476     left = tmp;
5477     rFalseIfx.condition ^= 1;
5478 #endif
5479
5480   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5481     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5482   }
5483
5484
5485   //if(IC_TRUE(ifx) == NULL)
5486   /* if left & right are bit variables */
5487   if (AOP_TYPE(left) == AOP_CRY &&
5488       AOP_TYPE(right) == AOP_CRY ) {
5489     assert (0 && "bit variables used in genCmp");
5490     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5491     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5492   } else {
5493     /* subtract right from left if at the
5494        end the carry flag is set then we know that
5495        left is greater than right */
5496
5497     symbol *lbl  = newiTempLabel(NULL);
5498
5499 #if 0
5500         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5501                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5502 #endif
5503
5504 #ifndef _swapp
5505     if(AOP_TYPE(right) == AOP_LIT) {
5506
5507       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5508
5509       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5510
5511       /* special cases */
5512
5513       if(lit == 0) {
5514
5515         if(sign != 0) 
5516           genSkipCond(&rFalseIfx,left,size-1,7);
5517         else 
5518           /* no need to compare to 0...*/
5519           /* NOTE: this is a de-generate compare that most certainly 
5520            *       creates some dead code. */
5521           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5522
5523         if(ifx) ifx->generated = 1;
5524         return;
5525
5526       }
5527       size--;
5528
5529       if(size == 0) {
5530         //i = (lit >> (size*8)) & 0xff;
5531         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5532         
5533         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5534
5535         i = ((0-lit) & 0xff);
5536         if(sign) {
5537           if( i == 0x81) { 
5538             /* lit is 0x7f, all signed chars are less than
5539              * this except for 0x7f itself */
5540             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5541             genSkipz2(&rFalseIfx,0);
5542           } else {
5543             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5544             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5545             genSkipc(&rFalseIfx);
5546           }
5547
5548         } else {
5549           if(lit == 1) {
5550             genSkipz2(&rFalseIfx,1);
5551           } else {
5552             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5553             genSkipc(&rFalseIfx);
5554           }
5555         }
5556
5557         if(ifx) ifx->generated = 1;
5558         return;
5559       }
5560
5561       /* chars are out of the way. now do ints and longs */
5562
5563
5564       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5565         
5566       /* special cases */
5567
5568       if(sign) {
5569
5570         if(lit == 0) {
5571           genSkipCond(&rFalseIfx,left,size,7);
5572           if(ifx) ifx->generated = 1;
5573           return;
5574         }
5575
5576         if(lit <0x100) {
5577           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5578
5579           //rFalseIfx.condition ^= 1;
5580           //genSkipCond(&rFalseIfx,left,size,7);
5581           //rFalseIfx.condition ^= 1;
5582
5583           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5584           if(rFalseIfx.condition)
5585             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5586           else
5587             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5588
5589           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5590           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5591           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5592
5593           while(size > 1)
5594             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5595
5596           if(rFalseIfx.condition) {
5597             emitSKPZ;
5598             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5599
5600           } else {
5601             emitSKPNZ;
5602           }
5603
5604           genSkipc(&rFalseIfx);
5605           pic16_emitpLabel(truelbl->key);
5606           if(ifx) ifx->generated = 1;
5607           return;
5608
5609         }
5610
5611         if(size == 1) {
5612
5613           if( (lit & 0xff) == 0) {
5614             /* lower byte is zero */
5615             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5616             i = ((lit >> 8) & 0xff) ^0x80;
5617             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5618             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5619             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5620             genSkipc(&rFalseIfx);
5621
5622
5623             if(ifx) ifx->generated = 1;
5624             return;
5625
5626           }
5627         } else {
5628           /* Special cases for signed longs */
5629           if( (lit & 0xffffff) == 0) {
5630             /* lower byte is zero */
5631             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5632             i = ((lit >> 8*3) & 0xff) ^0x80;
5633             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5634             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5635             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5636             genSkipc(&rFalseIfx);
5637
5638
5639             if(ifx) ifx->generated = 1;
5640             return;
5641
5642           }
5643
5644         }
5645
5646
5647         if(lit & (0x80 << (size*8))) {
5648           /* lit is negative */
5649           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5650
5651           //genSkipCond(&rFalseIfx,left,size,7);
5652
5653           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5654
5655           if(rFalseIfx.condition)
5656             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5657           else
5658             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5659
5660
5661         } else {
5662           /* lit is positive */
5663           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5664           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5665           if(rFalseIfx.condition)
5666             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5667           else
5668             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5669
5670         }
5671
5672         /*
5673           This works, but is only good for ints.
5674           It also requires a "known zero" register.
5675           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5676           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5677           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5678           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5679           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5680           genSkipc(&rFalseIfx);
5681
5682           pic16_emitpLabel(truelbl->key);
5683           if(ifx) ifx->generated = 1;
5684           return;
5685         **/
5686           
5687         /* There are no more special cases, so perform a general compare */
5688   
5689         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5690         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5691
5692         while(size--) {
5693
5694           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5695           emitSKPNZ;
5696           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5697         }
5698         //rFalseIfx.condition ^= 1;
5699         genSkipc(&rFalseIfx);
5700
5701         pic16_emitpLabel(truelbl->key);
5702
5703         if(ifx) ifx->generated = 1;
5704         return;
5705
5706
5707       }
5708
5709
5710       /* sign is out of the way. So now do an unsigned compare */
5711       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5712
5713
5714       /* General case - compare to an unsigned literal on the right.*/
5715
5716       i = (lit >> (size*8)) & 0xff;
5717       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5718       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5719       while(size--) {
5720         i = (lit >> (size*8)) & 0xff;
5721
5722         if(i) {
5723           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5724           emitSKPNZ;
5725           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5726         } else {
5727           /* this byte of the lit is zero, 
5728            *if it's not the last then OR in the variable */
5729           if(size)
5730             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5731         }
5732       }
5733
5734
5735       pic16_emitpLabel(lbl->key);
5736 //      pic16_emitpLabel(truelbl->key);
5737       //if(emitFinalCheck)
5738       genSkipc(&rFalseIfx);
5739       if(sign)
5740         pic16_emitpLabel(truelbl->key);
5741
5742       if(ifx) ifx->generated = 1;
5743       return;
5744
5745
5746     }
5747 #endif  // _swapp
5748
5749     if(AOP_TYPE(left) == AOP_LIT) {
5750       //symbol *lbl = newiTempLabel(NULL);
5751
5752       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5753
5754
5755       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5756
5757       /* Special cases */
5758       if((lit == 0) && (sign == 0)){
5759
5760         size--;
5761         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5762         while(size) 
5763           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5764
5765         genSkipz2(&rFalseIfx,0);
5766         if(ifx) ifx->generated = 1;
5767         return;
5768       }
5769
5770       if(size==1) {
5771         /* Special cases */
5772         lit &= 0xff;
5773         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5774           /* degenerate compare can never be true */
5775           if(rFalseIfx.condition == 0)
5776             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5777
5778           if(ifx) ifx->generated = 1;
5779           return;
5780         }
5781
5782         if(sign) {
5783           /* signed comparisons to a literal byte */
5784
5785           int lp1 = (lit+1) & 0xff;
5786
5787           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5788           switch (lp1) {
5789           case 0:
5790             rFalseIfx.condition ^= 1;
5791             genSkipCond(&rFalseIfx,right,0,7);
5792             break;
5793           case 0x7f:
5794             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5795             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5796             genSkipz2(&rFalseIfx,1);
5797             break;
5798           default:
5799             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5800             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5801             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5802             rFalseIfx.condition ^= 1;
5803             genSkipc(&rFalseIfx);
5804             break;
5805           }
5806         } else {
5807           /* unsigned comparisons to a literal byte */
5808
5809           switch(lit & 0xff ) {
5810           case 0:
5811             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5812             genSkipz2(&rFalseIfx,0);
5813             break;
5814           case 0x7f:
5815             rFalseIfx.condition ^= 1;
5816             genSkipCond(&rFalseIfx,right,0,7);
5817             break;
5818
5819           default:
5820             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5821             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5822             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5823             rFalseIfx.condition ^= 1;
5824             if (AOP_TYPE(result) == AOP_CRY)
5825               genSkipc(&rFalseIfx);
5826             else {
5827               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5828               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5829             }         
5830             break;
5831           }
5832         }
5833
5834         if(ifx) ifx->generated = 1;
5835         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5836                 goto check_carry;
5837         return;
5838
5839       } else {
5840
5841         /* Size is greater than 1 */
5842
5843         if(sign) {
5844           int lp1 = lit+1;
5845
5846           size--;
5847
5848           if(lp1 == 0) {
5849             /* this means lit = 0xffffffff, or -1 */
5850
5851
5852             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5853             rFalseIfx.condition ^= 1;
5854             genSkipCond(&rFalseIfx,right,size,7);
5855             if(ifx) ifx->generated = 1;
5856
5857             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5858               goto check_carry;
5859
5860             return;
5861           }
5862
5863           if(lit == 0) {
5864             int s = size;
5865
5866             if(rFalseIfx.condition) {
5867               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5868               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5869             }
5870
5871             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5872             while(size--)
5873               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5874
5875
5876             emitSKPZ;
5877             if(rFalseIfx.condition) {
5878               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5879               pic16_emitpLabel(truelbl->key);
5880             }else {
5881               rFalseIfx.condition ^= 1;
5882               genSkipCond(&rFalseIfx,right,s,7);
5883             }
5884
5885             if(ifx) ifx->generated = 1;
5886
5887             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5888               goto check_carry;
5889
5890             return;
5891           }
5892
5893           if((size == 1) &&  (0 == (lp1&0xff))) {
5894             /* lower byte of signed word is zero */
5895             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5896             i = ((lp1 >> 8) & 0xff) ^0x80;
5897             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5898             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5899             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5900
5901             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5902               emitTOGC;
5903               if(ifx) ifx->generated = 1;
5904               goto check_carry;
5905             } else {
5906               rFalseIfx.condition ^= 1;
5907               genSkipc(&rFalseIfx);
5908               if(ifx) ifx->generated = 1;
5909             }
5910
5911             return;
5912           }
5913
5914           if(lit & (0x80 << (size*8))) {
5915             /* Lit is less than zero */
5916             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5917             //rFalseIfx.condition ^= 1;
5918             //genSkipCond(&rFalseIfx,left,size,7);
5919             //rFalseIfx.condition ^= 1;
5920             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5921             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5922
5923             if(rFalseIfx.condition)
5924               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5925             else
5926               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5927
5928
5929           } else {
5930             /* Lit is greater than or equal to zero */
5931             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5932             //rFalseIfx.condition ^= 1;
5933             //genSkipCond(&rFalseIfx,right,size,7);
5934             //rFalseIfx.condition ^= 1;
5935
5936             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5937             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5938
5939             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5940             if(rFalseIfx.condition)
5941               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5942             else
5943               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5944
5945           }
5946
5947           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5948           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5949
5950           while(size--) {
5951
5952             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5953             emitSKPNZ;
5954             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5955           }
5956           rFalseIfx.condition ^= 1;
5957           //rFalseIfx.condition = 1;
5958           genSkipc(&rFalseIfx);
5959
5960           pic16_emitpLabel(truelbl->key);
5961
5962           if(ifx) ifx->generated = 1;
5963
5964
5965           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5966             goto check_carry;
5967
5968           return;
5969           // end of if (sign)
5970         } else {
5971
5972           /* compare word or long to an unsigned literal on the right.*/
5973
5974
5975           size--;
5976           if(lit < 0xff) {
5977             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5978             switch (lit) {
5979             case 0:
5980               break; /* handled above */
5981 /*
5982             case 0xff:
5983               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5984               while(size--)
5985                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5986               genSkipz2(&rFalseIfx,0);
5987               break;
5988 */
5989             default:
5990               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5991               while(--size)
5992                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5993
5994               emitSKPZ;
5995               if(rFalseIfx.condition)
5996                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5997               else
5998                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5999
6000
6001               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6002               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6003
6004               rFalseIfx.condition ^= 1;
6005               genSkipc(&rFalseIfx);
6006             }
6007
6008             pic16_emitpLabel(truelbl->key);
6009
6010             if(ifx) ifx->generated = 1;
6011
6012             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6013               goto check_carry;
6014
6015             return;
6016           }
6017
6018
6019           lit++;
6020           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6021           i = (lit >> (size*8)) & 0xff;
6022
6023           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6024           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6025
6026           while(size--) {
6027             i = (lit >> (size*8)) & 0xff;
6028
6029             if(i) {
6030               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6031               emitSKPNZ;
6032               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6033             } else {
6034               /* this byte of the lit is zero, 
6035                * if it's not the last then OR in the variable */
6036               if(size)
6037                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6038             }
6039           }
6040
6041
6042           pic16_emitpLabel(lbl->key);
6043
6044           rFalseIfx.condition ^= 1;
6045
6046           genSkipc(&rFalseIfx);
6047         }
6048
6049         if(sign)
6050           pic16_emitpLabel(truelbl->key);
6051         if(ifx) ifx->generated = 1;
6052
6053             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6054               goto check_carry;
6055
6056         return;
6057       }
6058     }
6059     /* Compare two variables */
6060
6061     DEBUGpic16_emitcode(";sign","%d",sign);
6062
6063     size--;
6064     if(sign) {
6065       /* Sigh. thus sucks... */
6066       if(size) {
6067         pCodeOp *pctemp;
6068         
6069         pctemp = pic16_popGetTempReg(1);
6070         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6071         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6072         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6073         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6074         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6075         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6076         pic16_popReleaseTempReg(pctemp, 1);
6077       } else {
6078         /* Signed char comparison */
6079         /* Special thanks to Nikolai Golovchenko for this snippet */
6080         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6081         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6082         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6083         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6084         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6085         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6086
6087         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6088         genSkipc(&rFalseIfx);
6089           
6090         if(ifx) ifx->generated = 1;
6091
6092             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6093               goto check_carry;
6094
6095         return;
6096       }
6097
6098     } else {
6099
6100       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6101       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6102     }
6103
6104
6105     /* The rest of the bytes of a multi-byte compare */
6106     while (size) {
6107
6108       emitSKPZ;
6109       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6110       size--;
6111
6112       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6113       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6114
6115
6116     }
6117
6118     pic16_emitpLabel(lbl->key);
6119
6120     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6121     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6122         (AOP_TYPE(result) == AOP_REG)) {
6123       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6124       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6125     } else {
6126       genSkipc(&rFalseIfx);
6127     }         
6128     //genSkipc(&rFalseIfx);
6129     if(ifx) ifx->generated = 1;
6130
6131
6132             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6133               goto check_carry;
6134
6135     return;
6136
6137   }
6138
6139 check_carry:
6140   if ((AOP_TYPE(result) != AOP_CRY) 
6141         && AOP_SIZE(result)) {
6142     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6143
6144     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6145
6146     pic16_outBitC(result);
6147   } else {
6148     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6149     /* if the result is used in the next
6150        ifx conditional branch then generate
6151        code a little differently */
6152     if (ifx )
6153       genIfxJump (ifx,"c");
6154     else
6155       pic16_outBitC(result);
6156     /* leave the result in acc */
6157   }
6158
6159 }
6160
6161 #elif 0 /* VR version of genCmp() */    /* } else { */
6162
6163 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6164 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6165         operand *result, int offset, int invert_op)
6166 {
6167   /* add code here */
6168   
6169   /* check condition, > or < ?? */
6170   if(rIfx->condition != 0)invert_op ^= 1;
6171   
6172   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6173
6174   if(!ifx)invert_op ^= 1;
6175
6176   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6177       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6178   
6179   /* do selection */
6180   if(!invert_op)return POC_CPFSGT;
6181   else return POC_CPFSLT;
6182 }
6183
6184 static int compareAopfirstpass=1;
6185
6186 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6187             operand *oper, int offset, operand *result,
6188             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6189             symbol *tlbl)
6190 {
6191   int op;
6192   symbol *truelbl;
6193
6194   /* invert if there is a result to be loaded, in order to fit,
6195    * SETC/CLRC sequence */
6196   if(AOP_SIZE(result))invert_op ^= 1;
6197
6198 //  if(sign && !offset)invert_op ^= 1;
6199   
6200 //  if(sign)invert_op ^= 1;
6201   
6202   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6203
6204   if(AOP_SIZE(result) && compareAopfirstpass) {
6205     if(!ifx) {
6206       if(pcop2)
6207         pic16_emitpcode(POC_SETF, pcop2);
6208       else
6209         emitSETC;
6210     } else {
6211       if(pcop2)
6212         pic16_emitpcode(POC_CLRF, pcop2);
6213       else
6214         emitCLRC;
6215     }
6216   }
6217
6218   compareAopfirstpass = 0;
6219
6220       /* there is a bug when comparing operands with size > 1,
6221        * because higher bytes can be equal and test should be performed
6222        * to the next lower byte, current algorithm, considers operands
6223        * inequal in these cases! -- VR 20041107 */
6224
6225     
6226   if(pcop)
6227     pic16_emitpcode(op, pcop);
6228   else
6229     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6230
6231
6232   if((!sign || !offset) && AOP_SIZE(result)) {
6233     if(!ifx) {
6234       if(pcop2)
6235         pic16_emitpcode(POC_CLRF, pcop2);
6236         else
6237         emitCLRC;
6238     } else {
6239       if(pcop2)
6240         pic16_emitpcode(POC_SETF, pcop2);
6241       else
6242         emitSETC;
6243     }
6244     
6245     /* don't emit final branch (offset == 0) */
6246     if(offset) {
6247
6248       if(pcop2)
6249         pic16_emitpcode(POC_RRCF, pcop2);
6250
6251       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6252     }
6253   } else {
6254     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6255       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6256             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6257
6258       truelbl = newiTempLabel( NULL );
6259       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6260       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6261         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6262       else
6263         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6264       pic16_emitpLabel(truelbl->key);
6265     } else {
6266       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6267     }
6268   }
6269 }
6270
6271 static void genCmp (operand *left, operand *right,
6272                     operand *result, iCode *ifx, int sign)
6273 {
6274   int size, cmpop=1;
6275   long lit = 0L;
6276   resolvedIfx rFalseIfx;
6277   symbol *falselbl, *tlbl;
6278
6279     FENTRY;
6280     
6281     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6282
6283     resolveIfx(&rFalseIfx, ifx);
6284     size = max(AOP_SIZE(left), AOP_SIZE(right));
6285     
6286     /* if left & right are bit variables */
6287     if(AOP_TYPE(left) == AOP_CRY
6288       && AOP_TYPE(right) == AOP_CRY ) {
6289
6290         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6291         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6292         
6293         werror(W_POSSBUG2, __FILE__, __LINE__);
6294         exit(EXIT_FAILURE);
6295     }
6296     
6297     /* if literal is on the right then swap with left */
6298     if((AOP_TYPE(right) == AOP_LIT)) {
6299       operand *tmp = right ;
6300 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6301
6302         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6303
6304 //      lit = (lit - 1) & mask;
6305         right = left;
6306         left = tmp;
6307         rFalseIfx.condition ^= 1;               /* reverse compare */
6308     } else
6309     if ((AOP_TYPE(left) == AOP_LIT)) {
6310       /* float compares are handled by support functions */
6311       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6312     }
6313
6314     /* actual comparing algorithm */
6315 //    size = AOP_SIZE( right );
6316
6317     falselbl = newiTempLabel( NULL );
6318     if(AOP_TYPE(left) == AOP_LIT) {
6319       /* compare to literal */
6320       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6321       
6322       if(sign) {
6323         pCodeOp *pct, *pct2;
6324         symbol *tlbl1;
6325
6326         /* signed compare */
6327         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6328
6329         /* using PRODL:PRODH as a temporary register here */
6330         pct = pic16_popCopyReg(&pic16_pc_prodl);
6331         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6332         tlbl = newiTempLabel( NULL );
6333         
6334         /* first compare signs:
6335          *  a. if both are positive, compare just like unsigned
6336          *  b. if both are negative, invert cmpop, compare just like unsigned
6337          *  c. if different signs, determine the result directly */
6338
6339         size--;
6340
6341 #if 1
6342         /* { */
6343         tlbl1 = newiTempLabel( NULL );
6344 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6345
6346         if(lit > 0) {
6347
6348           /* literal is zero or positive:
6349            *  a. if carry is zero, too, continue compare,
6350            *  b. if carry is set, then continue depending on cmpop ^ condition:
6351            *    1. '<' return false (literal < variable),
6352            *    2. '>' return true (literal > variable) */
6353 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6354           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6355           
6356           
6357           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6358           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6359         } else 
6360         if(lit < 0) {
6361           
6362           /* literal is negative:
6363            *  a. if carry is set, too, continue compare,
6364            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6365            *    1. '<' return true (literal < variable),
6366            *    2. '>' return false (literal > variable) */
6367 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6368           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6369           
6370           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6371           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6372         }
6373 #if 1
6374         else {
6375           /* lit == 0 */
6376           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6377           
6378           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6379           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6380         }
6381 #endif
6382         
6383         
6384         pic16_emitpLabel( tlbl1->key );
6385 #endif  /* } */
6386
6387         compareAopfirstpass=1;
6388 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6389 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6390 //        pic16_emitpcode(POC_MOVWF, pct);
6391
6392 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6393         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6394 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6395         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6396
6397         /* generic case */        
6398           while( size-- ) {
6399 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6400 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6401 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6402 //            pic16_emitpcode(POC_MOVWF, pct);
6403
6404 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6405             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6406             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6407 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6408 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6409           }
6410         
6411         if(ifx)ifx->generated = 1;
6412
6413         if(AOP_SIZE(result)) {
6414           pic16_emitpLabel(tlbl->key);
6415           pic16_emitpLabel(falselbl->key);
6416           pic16_outBitOp( result, pct2 );
6417         } else {
6418           pic16_emitpLabel(tlbl->key);
6419         }
6420       } else {
6421
6422         /* unsigned compare */      
6423         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6424     
6425         compareAopfirstpass=1;
6426         while(size--) {
6427           
6428           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6429           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6430
6431         }
6432         if(ifx)ifx->generated = 1;
6433
6434         if(AOP_SIZE(result)) {
6435           pic16_emitpLabel(falselbl->key);
6436           pic16_outBitC( result );
6437         }
6438
6439       }
6440     } else {
6441       /* compare registers */
6442       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6443
6444
6445       if(sign) {
6446         pCodeOp *pct, *pct2;
6447         
6448         /* signed compare */
6449         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6450
6451         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6452         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6453         tlbl = newiTempLabel( NULL );
6454         
6455         compareAopfirstpass=1;
6456
6457         size--;
6458         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6459 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6460         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6461         pic16_emitpcode(POC_MOVWF, pct);
6462
6463         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6464 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6465         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6466
6467         /* WREG already holds left + 0x80 */
6468         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6469         
6470         while( size-- ) {
6471           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6472 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6473           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6474           pic16_emitpcode(POC_MOVWF, pct);
6475                 
6476           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6477 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6478           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6479
6480           /* WREG already holds left + 0x80 */
6481           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6482 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6483         }
6484         
6485         if(ifx)ifx->generated = 1;
6486
6487         if(AOP_SIZE(result)) {
6488           pic16_emitpLabel(tlbl->key);
6489           pic16_emitpLabel(falselbl->key);
6490           pic16_outBitOp( result, pct2 );
6491         } else {
6492           pic16_emitpLabel(tlbl->key);
6493         }
6494
6495       } else {
6496         /* unsigned compare */      
6497         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6498
6499         compareAopfirstpass=1;
6500         while(size--) {
6501           
6502           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6503           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6504
6505         }
6506
6507         if(ifx)ifx->generated = 1;
6508         if(AOP_SIZE(result)) {
6509
6510           pic16_emitpLabel(falselbl->key);
6511           pic16_outBitC( result );
6512         }
6513
6514       }
6515     }
6516 }
6517
6518 #endif  /* } */
6519
6520
6521
6522 /*-----------------------------------------------------------------*/
6523 /* genCmpGt :- greater than comparison                             */
6524 /*-----------------------------------------------------------------*/
6525 static void genCmpGt (iCode *ic, iCode *ifx)
6526 {
6527   operand *left, *right, *result;
6528   sym_link *letype , *retype;
6529   int sign ;
6530
6531     FENTRY;
6532     
6533     left = IC_LEFT(ic);
6534     right= IC_RIGHT(ic);
6535     result = IC_RESULT(ic);
6536
6537     letype = getSpec(operandType(left));
6538     retype =getSpec(operandType(right));
6539     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6540     /* assign the amsops */
6541     pic16_aopOp (left,ic,FALSE);
6542     pic16_aopOp (right,ic,FALSE);
6543     pic16_aopOp (result,ic,TRUE);
6544
6545     genCmp(right, left, result, ifx, sign);
6546
6547     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6548     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6549     pic16_freeAsmop(result,NULL,ic,TRUE); 
6550 }
6551
6552 /*-----------------------------------------------------------------*/
6553 /* genCmpLt - less than comparisons                                */
6554 /*-----------------------------------------------------------------*/
6555 static void genCmpLt (iCode *ic, iCode *ifx)
6556 {
6557   operand *left, *right, *result;
6558   sym_link *letype , *retype;
6559   int sign ;
6560
6561     FENTRY;
6562
6563     left = IC_LEFT(ic);
6564     right= IC_RIGHT(ic);
6565     result = IC_RESULT(ic);
6566
6567     letype = getSpec(operandType(left));
6568     retype =getSpec(operandType(right));
6569     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6570
6571     /* assign the amsops */
6572     pic16_aopOp (left,ic,FALSE);
6573     pic16_aopOp (right,ic,FALSE);
6574     pic16_aopOp (result,ic,TRUE);
6575
6576     genCmp(left, right, result, ifx, sign);
6577
6578     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6579     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6580     pic16_freeAsmop(result,NULL,ic,TRUE); 
6581 }
6582
6583 #if 0
6584 // not needed ATM
6585 // FIXME reenable literal optimisation when the pic16 port is stable
6586
6587 /*-----------------------------------------------------------------*/
6588 /* genc16bit2lit - compare a 16 bit value to a literal             */
6589 /*-----------------------------------------------------------------*/
6590 static void genc16bit2lit(operand *op, int lit, int offset)
6591 {
6592   int i;
6593
6594   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6595   if( (lit&0xff) == 0) 
6596     i=1;
6597   else
6598     i=0;
6599
6600   switch( BYTEofLONG(lit,i)) { 
6601   case 0:
6602     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6603     break;
6604   case 1:
6605     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6606     break;
6607   case 0xff:
6608     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6609     break;
6610   default:
6611     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6612     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6613   }
6614
6615   i ^= 1;
6616
6617   switch( BYTEofLONG(lit,i)) { 
6618   case 0:
6619     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6620     break;
6621   case 1:
6622     emitSKPNZ;
6623     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6624     break;
6625   case 0xff:
6626     emitSKPNZ;
6627     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6628     break;
6629   default:
6630     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6631     emitSKPNZ;
6632     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6633
6634   }
6635
6636 }
6637 #endif
6638
6639 #if 0
6640 // not needed ATM
6641 /*-----------------------------------------------------------------*/
6642 /* gencjneshort - compare and jump if not equal                    */
6643 /*-----------------------------------------------------------------*/
6644 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6645 {
6646   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6647   int offset = 0;
6648   int res_offset = 0;  /* the result may be a different size then left or right */
6649   int res_size = AOP_SIZE(result);
6650   resolvedIfx rIfx;
6651   symbol *lbl, *lbl_done;
6652
6653   unsigned long lit = 0L;
6654   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6655
6656   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6657   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6658   if(result)
6659     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6660   resolveIfx(&rIfx,ifx);
6661   lbl =  newiTempLabel(NULL);
6662   lbl_done =  newiTempLabel(NULL);
6663
6664
6665   /* if the left side is a literal or 
6666      if the right is in a pointer register and left 
6667      is not */
6668   if ((AOP_TYPE(left) == AOP_LIT) || 
6669       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6670     operand *t = right;
6671     right = left;
6672     left = t;
6673   }
6674   if(AOP_TYPE(right) == AOP_LIT)
6675     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6676
6677   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6678     preserve_result = 1;
6679
6680   if(result && !preserve_result)
6681     {
6682       int i;
6683       for(i = 0; i < AOP_SIZE(result); i++)
6684         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6685     }
6686
6687
6688   /* if the right side is a literal then anything goes */
6689   if (AOP_TYPE(right) == AOP_LIT &&
6690       AOP_TYPE(left) != AOP_DIR ) {
6691     switch(size) {
6692     case 2:
6693       genc16bit2lit(left, lit, 0);
6694       emitSKPZ;
6695       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6696       break;
6697     default:
6698       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6699       while (size--) {
6700         if(lit & 0xff) {
6701           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6702           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6703         } else {
6704           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6705         }
6706
6707         emitSKPZ;
6708         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6709         offset++;
6710         if(res_offset < res_size-1)
6711           res_offset++;
6712         lit >>= 8;
6713       }
6714       break;
6715     }
6716   }
6717
6718   /* if the right side is in a register or in direct space or
6719      if the left is a pointer register & right is not */    
6720   else if (AOP_TYPE(right) == AOP_REG ||
6721            AOP_TYPE(right) == AOP_DIR || 
6722            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6723            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6724     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6725     int lbl_key = lbl->key;
6726
6727     if(result) {
6728       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6729       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6730     }else {
6731       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6732       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6733               __FUNCTION__,__LINE__);
6734       return;
6735     }
6736    
6737 /*     switch(size) { */
6738 /*     case 2: */
6739 /*       genc16bit2lit(left, lit, 0); */
6740 /*       emitSKPNZ; */
6741 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6742 /*       break; */
6743 /*     default: */
6744     while (size--) {
6745       int emit_skip=1;
6746       if((AOP_TYPE(left) == AOP_DIR) && 
6747          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6748
6749         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6750         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6751
6752       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6753             
6754         switch (lit & 0xff) {
6755         case 0:
6756           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6757           break;
6758         case 1:
6759           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6760           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6761           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6762           emit_skip=0;
6763           break;
6764         case 0xff:
6765           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6766           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6767           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6768           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6769           emit_skip=0;
6770           break;
6771         default:
6772           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6773           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6774         }
6775         lit >>= 8;
6776
6777       } else {
6778         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6779       }
6780       if(emit_skip) {
6781         if(AOP_TYPE(result) == AOP_CRY) {
6782           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6783           if(rIfx.condition)
6784             emitSKPNZ;
6785           else
6786             emitSKPZ;
6787           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6788         } else {
6789           /* fix me. probably need to check result size too */
6790           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6791           if(rIfx.condition)
6792             emitSKPZ;
6793           else
6794             emitSKPNZ;
6795           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6796           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6797         }
6798         if(ifx)
6799           ifx->generated=1;
6800       }
6801       emit_skip++;
6802       offset++;
6803       if(res_offset < res_size-1)
6804         res_offset++;
6805     }
6806 /*       break; */
6807 /*     } */
6808   } else if(AOP_TYPE(right) == AOP_REG &&
6809             AOP_TYPE(left) != AOP_DIR){
6810
6811     while(size--) {
6812       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6813       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6814       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6815       if(rIfx.condition)
6816         emitSKPNZ;
6817       else
6818         emitSKPZ;
6819       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6820       offset++;
6821       if(res_offset < res_size-1)
6822         res_offset++;
6823     }
6824       
6825   }else{
6826     /* right is a pointer reg need both a & b */
6827     while(size--) {
6828       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6829       if(strcmp(l,"b"))
6830         pic16_emitcode("mov","b,%s",l);
6831       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6832       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6833       offset++;
6834     }
6835   }
6836
6837   if(result && preserve_result)
6838     {
6839       int i;
6840       for(i = 0; i < AOP_SIZE(result); i++)
6841         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6842     }
6843
6844   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6845
6846   if(result && preserve_result)
6847     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6848
6849   if(!rIfx.condition)
6850     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6851
6852   pic16_emitpLabel(lbl->key);
6853
6854   if(result && preserve_result)
6855     {
6856       int i;
6857       for(i = 0; i < AOP_SIZE(result); i++)
6858         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6859
6860       pic16_emitpLabel(lbl_done->key);
6861    }
6862
6863   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6864
6865   if(ifx)
6866     ifx->generated = 1;
6867 }
6868 #endif
6869
6870 #if 0
6871 /*-----------------------------------------------------------------*/
6872 /* gencjne - compare and jump if not equal                         */
6873 /*-----------------------------------------------------------------*/
6874 static void gencjne(operand *left, operand *right, iCode *ifx)
6875 {
6876     symbol *tlbl  = newiTempLabel(NULL);
6877
6878     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6879     gencjneshort(left, right, lbl);
6880
6881     pic16_emitcode("mov","a,%s",one);
6882     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6883     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6884     pic16_emitcode("clr","a");
6885     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6886
6887     pic16_emitpLabel(lbl->key);
6888     pic16_emitpLabel(tlbl->key);
6889
6890 }
6891 #endif
6892
6893
6894 /*-----------------------------------------------------------------*/
6895 /* is_LitOp - check if operand has to be treated as literal        */
6896 /*-----------------------------------------------------------------*/
6897 static bool is_LitOp(operand *op)
6898 {
6899   return ((AOP_TYPE(op) == AOP_LIT)
6900       || ( (AOP_TYPE(op) == AOP_PCODE)
6901           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6902               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6903 }
6904
6905 /*-----------------------------------------------------------------*/
6906 /* is_LitAOp - check if operand has to be treated as literal        */
6907 /*-----------------------------------------------------------------*/
6908 static bool is_LitAOp(asmop *aop)
6909 {
6910   return ((aop->type == AOP_LIT)
6911       || ( (aop->type == AOP_PCODE)
6912           && ( (aop->aopu.pcop->type == PO_LITERAL)
6913               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6914 }
6915
6916
6917
6918 /*-----------------------------------------------------------------*/
6919 /* genCmpEq - generates code for equal to                          */
6920 /*-----------------------------------------------------------------*/
6921 static void genCmpEq (iCode *ic, iCode *ifx)
6922 {
6923   operand *left, *right, *result;
6924   symbol *falselbl = newiTempLabel(NULL);
6925   symbol *donelbl = newiTempLabel(NULL);
6926
6927   int preserve_result = 0;
6928   int generate_result = 0;
6929   int i=0;
6930   unsigned long lit = -1;
6931
6932   FENTRY;
6933   
6934   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6935   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6936   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6937  
6938   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6939
6940   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6941     {
6942       werror(W_POSSBUG2, __FILE__, __LINE__);
6943       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6944       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6945       goto release;
6946     }
6947
6948   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6949     {
6950       operand *tmp = right ;
6951       right = left;
6952       left = tmp;
6953     }
6954
6955   if (AOP_TYPE(right) == AOP_LIT) {
6956     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6957   }
6958
6959   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6960     preserve_result = 1;
6961
6962   if(result && AOP_SIZE(result))
6963     generate_result = 1;
6964
6965   if(generate_result && !preserve_result)
6966     {
6967       for(i = 0; i < AOP_SIZE(result); i++)
6968         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6969     }
6970
6971   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6972   for(i=0; i < AOP_SIZE(left); i++)
6973     {
6974       if(AOP_TYPE(left) != AOP_ACC)
6975         {
6976           if(is_LitOp(left))
6977             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6978           else
6979             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6980         }
6981       if(is_LitOp(right)) {
6982         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6983           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6984         }
6985       } else
6986         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6987
6988       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6989     }
6990
6991   // result == true
6992
6993   if(generate_result && preserve_result)
6994     {
6995       for(i = 0; i < AOP_SIZE(result); i++)
6996         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6997     }
6998
6999   if(generate_result)
7000     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7001
7002   if(generate_result && preserve_result)
7003     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7004
7005   if(ifx && IC_TRUE(ifx))
7006     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7007
7008   if(ifx && IC_FALSE(ifx))
7009     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7010
7011   pic16_emitpLabel(falselbl->key);
7012
7013   // result == false
7014
7015   if(ifx && IC_FALSE(ifx))
7016     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7017
7018   if(generate_result && preserve_result)
7019     {
7020       for(i = 0; i < AOP_SIZE(result); i++)
7021         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7022     }
7023
7024   pic16_emitpLabel(donelbl->key);
7025
7026   if(ifx)
7027     ifx->generated = 1;
7028
7029 release:
7030   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7031   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7032   pic16_freeAsmop(result,NULL,ic,TRUE);
7033
7034 }
7035
7036
7037 #if 0
7038 // old version kept for reference
7039
7040 /*-----------------------------------------------------------------*/
7041 /* genCmpEq - generates code for equal to                          */
7042 /*-----------------------------------------------------------------*/
7043 static void genCmpEq (iCode *ic, iCode *ifx)
7044 {
7045     operand *left, *right, *result;
7046     unsigned long lit = 0L;
7047     int size,offset=0;
7048     symbol *falselbl  = newiTempLabel(NULL);
7049
7050
7051     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7052
7053     if(ifx)
7054       DEBUGpic16_emitcode ("; ifx is non-null","");
7055     else
7056       DEBUGpic16_emitcode ("; ifx is null","");
7057
7058     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7059     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7060     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7061
7062     size = max(AOP_SIZE(left),AOP_SIZE(right));
7063
7064     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7065
7066     /* if literal, literal on the right or 
7067     if the right is in a pointer register and left 
7068     is not */
7069     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7070         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7071       operand *tmp = right ;
7072       right = left;
7073       left = tmp;
7074     }
7075
7076
7077     if(ifx && !AOP_SIZE(result)){
7078         symbol *tlbl;
7079         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7080         /* if they are both bit variables */
7081         if (AOP_TYPE(left) == AOP_CRY &&
7082             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7083                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7084             if(AOP_TYPE(right) == AOP_LIT){
7085                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7086                 if(lit == 0L){
7087                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7088                     pic16_emitcode("cpl","c");
7089                 } else if(lit == 1L) {
7090                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7091                 } else {
7092                     pic16_emitcode("clr","c");
7093                 }
7094                 /* AOP_TYPE(right) == AOP_CRY */
7095             } else {
7096                 symbol *lbl = newiTempLabel(NULL);
7097                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7098                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7099                 pic16_emitcode("cpl","c");
7100                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7101             }
7102             /* if true label then we jump if condition
7103             supplied is true */
7104             tlbl = newiTempLabel(NULL);
7105             if ( IC_TRUE(ifx) ) {
7106                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7107                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7108             } else {
7109                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7110                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7111             }
7112             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7113
7114                 {
7115                 /* left and right are both bit variables, result is carry */
7116                         resolvedIfx rIfx;
7117               
7118                         resolveIfx(&rIfx,ifx);
7119
7120                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7121                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7122                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7123                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7124                         genSkipz2(&rIfx,0);
7125                 }
7126         } else {
7127
7128                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7129
7130                         /* They're not both bit variables. Is the right a literal? */
7131                         if(AOP_TYPE(right) == AOP_LIT) {
7132                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7133             
7134                         switch(size) {
7135
7136                                 case 1:
7137                                         switch(lit & 0xff) {
7138                                                 case 1:
7139                                                                 if ( IC_TRUE(ifx) ) {
7140                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7141                                                                         emitSKPNZ;
7142                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7143                                                                 } else {
7144                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7145                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7146                                                                 }
7147                                                                 break;
7148                                                 case 0xff:
7149                                                                 if ( IC_TRUE(ifx) ) {
7150                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7151                                                                         emitSKPNZ;
7152                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7153                                                                 } else {
7154                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7155                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7156                                                                 }
7157                                                                 break;
7158                                                 default:
7159                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7160                                                                 if(lit)
7161                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7162                                                                 genSkip(ifx,'z');
7163                                         } // switch lit
7164
7165
7166                                         /* end of size == 1 */
7167                                         break;
7168               
7169                                 case 2:
7170                                         genc16bit2lit(left,lit,offset);
7171                                         genSkip(ifx,'z');
7172                                         break;
7173                                         /* end of size == 2 */
7174
7175                                 default:
7176                                         /* size is 4 */
7177                                         if(lit==0) {
7178                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7179                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7180                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7181                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7182                                                 genSkip(ifx,'z');
7183                                         } else {
7184                                                 /* search for patterns that can be optimized */
7185
7186                                                 genc16bit2lit(left,lit,0);
7187                                                 lit >>= 16;
7188                                                 if(lit) {
7189                                                                 if(IC_TRUE(ifx))
7190                                                                 emitSKPZ; // if hi word unequal
7191                                                                 else
7192                                                                 emitSKPNZ; // if hi word equal
7193                                                                 // fail early
7194                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7195                                                         genc16bit2lit(left,lit,2);
7196                                                         genSkip(ifx,'z');
7197                                                 } else {
7198                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7199                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7200                                                         genSkip(ifx,'z');
7201                                                 }
7202                                         }
7203                                                 pic16_emitpLabel(falselbl->key);
7204                                                 break;
7205
7206                         } // switch size
7207           
7208                         ifx->generated = 1;
7209                         goto release ;
7210             
7211
7212           } else if(AOP_TYPE(right) == AOP_CRY ) {
7213             /* we know the left is not a bit, but that the right is */
7214             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7215             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7216                       pic16_popGet(AOP(right),offset));
7217             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7218
7219             /* if the two are equal, then W will be 0 and the Z bit is set
7220              * we could test Z now, or go ahead and check the high order bytes if
7221              * the variable we're comparing is larger than a byte. */
7222
7223             while(--size)
7224               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7225
7226             if ( IC_TRUE(ifx) ) {
7227               emitSKPNZ;
7228               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7229               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7230             } else {
7231               emitSKPZ;
7232               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7233               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7234             }
7235
7236           } else {
7237             /* They're both variables that are larger than bits */
7238             int s = size;
7239
7240             tlbl = newiTempLabel(NULL);
7241
7242             while(size--) {
7243               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7244               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7245
7246               if ( IC_TRUE(ifx) ) {
7247                 if(size) {
7248                   emitSKPZ;
7249                 
7250                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7251
7252                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7253                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7254                 } else {
7255                   emitSKPNZ;
7256
7257                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7258
7259
7260                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7261                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7262                 }
7263               } else {
7264                 emitSKPZ;
7265
7266                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7267
7268                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7269                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7270               }
7271               offset++;
7272             }
7273             if(s>1 && IC_TRUE(ifx)) {
7274               pic16_emitpLabel(tlbl->key);
7275               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7276             }
7277           }
7278         }
7279         /* mark the icode as generated */
7280         ifx->generated = 1;
7281         goto release ;
7282     }
7283
7284     /* if they are both bit variables */
7285     if (AOP_TYPE(left) == AOP_CRY &&
7286         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7287         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7288         if(AOP_TYPE(right) == AOP_LIT){
7289             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7290             if(lit == 0L){
7291                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7292                 pic16_emitcode("cpl","c");
7293             } else if(lit == 1L) {
7294                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7295             } else {
7296                 pic16_emitcode("clr","c");
7297             }
7298             /* AOP_TYPE(right) == AOP_CRY */
7299         } else {
7300             symbol *lbl = newiTempLabel(NULL);
7301             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7302             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7303             pic16_emitcode("cpl","c");
7304             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7305         }
7306         /* c = 1 if egal */
7307         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7308             pic16_outBitC(result);
7309             goto release ;
7310         }
7311         if (ifx) {
7312             genIfxJump (ifx,"c");
7313             goto release ;
7314         }
7315         /* if the result is used in an arithmetic operation
7316         then put the result in place */
7317         pic16_outBitC(result);
7318     } else {
7319       
7320       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7321       gencjne(left,right,result,ifx);
7322 /*
7323       if(ifx) 
7324         gencjne(left,right,newiTempLabel(NULL));
7325       else {
7326         if(IC_TRUE(ifx)->key)
7327           gencjne(left,right,IC_TRUE(ifx)->key);
7328         else
7329           gencjne(left,right,IC_FALSE(ifx)->key);
7330         ifx->generated = 1;
7331         goto release ;
7332       }
7333       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7334         pic16_aopPut(AOP(result),"a",0);
7335         goto release ;
7336       }
7337
7338       if (ifx) {
7339         genIfxJump (ifx,"a");
7340         goto release ;
7341       }
7342 */
7343       /* if the result is used in an arithmetic operation
7344          then put the result in place */
7345 /*
7346       if (AOP_TYPE(result) != AOP_CRY) 
7347         pic16_outAcc(result);
7348 */
7349       /* leave the result in acc */
7350     }
7351
7352 release:
7353     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7354     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7355     pic16_freeAsmop(result,NULL,ic,TRUE);
7356 }
7357 #endif
7358
7359 /*-----------------------------------------------------------------*/
7360 /* ifxForOp - returns the icode containing the ifx for operand     */
7361 /*-----------------------------------------------------------------*/
7362 static iCode *ifxForOp ( operand *op, iCode *ic )
7363 {
7364   FENTRY2;
7365
7366     /* if true symbol then needs to be assigned */
7367     if (IS_TRUE_SYMOP(op))
7368         return NULL ;
7369
7370     /* if this has register type condition and
7371     the next instruction is ifx with the same operand
7372     and live to of the operand is upto the ifx only then */
7373     if (ic->next
7374         && ic->next->op == IFX
7375         && IC_COND(ic->next)->key == op->key
7376         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7377         ) {
7378                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7379           return ic->next;
7380     }
7381
7382     /*
7383     if (ic->next &&
7384         ic->next->op == IFX &&
7385         IC_COND(ic->next)->key == op->key) {
7386       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7387       return ic->next;
7388     }
7389     */
7390
7391     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7392     if (ic->next &&
7393         ic->next->op == IFX)
7394       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7395
7396     if (ic->next &&
7397         ic->next->op == IFX &&
7398         IC_COND(ic->next)->key == op->key) {
7399       DEBUGpic16_emitcode ("; "," key is okay");
7400       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7401                            OP_SYMBOL(op)->liveTo,
7402                            ic->next->seq);
7403     }
7404
7405 #if 0
7406     /* the code below is completely untested
7407      * it just allows ulong2fs.c compile -- VR */
7408          
7409     ic = ic->next;
7410     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7411                                         __FILE__, __FUNCTION__, __LINE__);
7412         
7413     /* if this has register type condition and
7414     the next instruction is ifx with the same operand
7415     and live to of the operand is upto the ifx only then */
7416     if (ic->next &&
7417         ic->next->op == IFX &&
7418         IC_COND(ic->next)->key == op->key &&
7419         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7420         return ic->next;
7421
7422     if (ic->next &&
7423         ic->next->op == IFX &&
7424         IC_COND(ic->next)->key == op->key) {
7425       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7426       return ic->next;
7427     }
7428
7429     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7430                                         __FILE__, __FUNCTION__, __LINE__);
7431
7432 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7433 #endif
7434
7435     return NULL;
7436 }
7437 /*-----------------------------------------------------------------*/
7438 /* genAndOp - for && operation                                     */
7439 /*-----------------------------------------------------------------*/
7440 static void genAndOp (iCode *ic)
7441 {
7442   operand *left,*right, *result;
7443 /*     symbol *tlbl; */
7444
7445     FENTRY;
7446
7447     /* note here that && operations that are in an
7448     if statement are taken away by backPatchLabels
7449     only those used in arthmetic operations remain */
7450     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7451     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7452     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7453
7454     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7455
7456     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7457     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7458     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7459
7460     /* if both are bit variables */
7461 /*     if (AOP_TYPE(left) == AOP_CRY && */
7462 /*         AOP_TYPE(right) == AOP_CRY ) { */
7463 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7464 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7465 /*         pic16_outBitC(result); */
7466 /*     } else { */
7467 /*         tlbl = newiTempLabel(NULL); */
7468 /*         pic16_toBoolean(left);     */
7469 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7470 /*         pic16_toBoolean(right); */
7471 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7472 /*         pic16_outBitAcc(result); */
7473 /*     } */
7474
7475     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7476     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7477     pic16_freeAsmop(result,NULL,ic,TRUE);
7478 }
7479
7480
7481 /*-----------------------------------------------------------------*/
7482 /* genOrOp - for || operation                                      */
7483 /*-----------------------------------------------------------------*/
7484 /*
7485   tsd pic port -
7486   modified this code, but it doesn't appear to ever get called
7487 */
7488
7489 static void genOrOp (iCode *ic)
7490 {
7491   operand *left,*right, *result;
7492   symbol *tlbl;
7493
7494     FENTRY;  
7495
7496   /* note here that || operations that are in an
7497     if statement are taken away by backPatchLabels
7498     only those used in arthmetic operations remain */
7499     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7500     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7501     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7502
7503     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7504
7505     /* if both are bit variables */
7506     if (AOP_TYPE(left) == AOP_CRY &&
7507         AOP_TYPE(right) == AOP_CRY ) {
7508       pic16_emitcode("clrc","");
7509       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7510                AOP(left)->aopu.aop_dir,
7511                AOP(left)->aopu.aop_dir);
7512       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7513                AOP(right)->aopu.aop_dir,
7514                AOP(right)->aopu.aop_dir);
7515       pic16_emitcode("setc","");
7516
7517     } else {
7518         tlbl = newiTempLabel(NULL);
7519         pic16_toBoolean(left);
7520         emitSKPZ;
7521         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7522         pic16_toBoolean(right);
7523         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7524
7525         pic16_outBitAcc(result);
7526     }
7527
7528     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7529     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7530     pic16_freeAsmop(result,NULL,ic,TRUE);            
7531 }
7532
7533 /*-----------------------------------------------------------------*/
7534 /* isLiteralBit - test if lit == 2^n                               */
7535 /*-----------------------------------------------------------------*/
7536 static int isLiteralBit(unsigned long lit)
7537 {
7538     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7539     0x100L,0x200L,0x400L,0x800L,
7540     0x1000L,0x2000L,0x4000L,0x8000L,
7541     0x10000L,0x20000L,0x40000L,0x80000L,
7542     0x100000L,0x200000L,0x400000L,0x800000L,
7543     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7544     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7545     int idx;
7546     
7547     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7548     for(idx = 0; idx < 32; idx++)
7549         if(lit == pw[idx])
7550             return idx+1;
7551     return 0;
7552 }
7553
7554 /*-----------------------------------------------------------------*/
7555 /* continueIfTrue -                                                */
7556 /*-----------------------------------------------------------------*/
7557 static void continueIfTrue (iCode *ic)
7558 {
7559   FENTRY;
7560   if(IC_TRUE(ic))
7561     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7562   ic->generated = 1;
7563 }
7564
7565 /*-----------------------------------------------------------------*/
7566 /* jmpIfTrue -                                                     */
7567 /*-----------------------------------------------------------------*/
7568 static void jumpIfTrue (iCode *ic)
7569 {
7570   FENTRY;
7571   if(!IC_TRUE(ic))
7572     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7573   ic->generated = 1;
7574 }
7575
7576 /*-----------------------------------------------------------------*/
7577 /* jmpTrueOrFalse -                                                */
7578 /*-----------------------------------------------------------------*/
7579 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7580 {
7581   // ugly but optimized by peephole
7582   FENTRY;
7583   if(IC_TRUE(ic)){
7584     symbol *nlbl = newiTempLabel(NULL);
7585       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7586       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7587       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7588       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7589   } else {
7590     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7591     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7592   }
7593   ic->generated = 1;
7594 }
7595
7596 /*-----------------------------------------------------------------*/
7597 /* genAnd  - code for and                                          */
7598 /*-----------------------------------------------------------------*/
7599 static void genAnd (iCode *ic, iCode *ifx)
7600 {
7601   operand *left, *right, *result;
7602   int size, offset=0;  
7603   unsigned long lit = 0L;
7604   int bytelit = 0;
7605   resolvedIfx rIfx;
7606
7607     FENTRY;
7608     
7609   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7610   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7611   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7612
7613   resolveIfx(&rIfx,ifx);
7614
7615   /* if left is a literal & right is not then exchange them */
7616   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7617       AOP_NEEDSACC(left)) {
7618     operand *tmp = right ;
7619     right = left;
7620     left = tmp;
7621   }
7622
7623   /* if result = right then exchange them */
7624   if(pic16_sameRegs(AOP(result),AOP(right))){
7625     operand *tmp = right ;
7626     right = left;
7627     left = tmp;
7628   }
7629
7630   /* if right is bit then exchange them */
7631   if (AOP_TYPE(right) == AOP_CRY &&
7632       AOP_TYPE(left) != AOP_CRY){
7633     operand *tmp = right ;
7634     right = left;
7635     left = tmp;
7636   }
7637   if(AOP_TYPE(right) == AOP_LIT)
7638     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7639
7640   size = AOP_SIZE(result);
7641
7642   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7643
7644   // if(bit & yy)
7645   // result = bit & yy;
7646   if (AOP_TYPE(left) == AOP_CRY){
7647     // c = bit & literal;
7648     if(AOP_TYPE(right) == AOP_LIT){
7649       if(lit & 1) {
7650         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7651           // no change
7652           goto release;
7653         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7654       } else {
7655         // bit(result) = 0;
7656         if(size && (AOP_TYPE(result) == AOP_CRY)){
7657           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7658           goto release;
7659         }
7660         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7661           jumpIfTrue(ifx);
7662           goto release;
7663         }
7664         pic16_emitcode("clr","c");
7665       }
7666     } else {
7667       if (AOP_TYPE(right) == AOP_CRY){
7668         // c = bit & bit;
7669         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7670         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7671       } else {
7672         // c = bit & val;
7673         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7674         // c = lsb
7675         pic16_emitcode("rrc","a");
7676         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7677       }
7678     }
7679     // bit = c
7680     // val = c
7681     if(size)
7682       pic16_outBitC(result);
7683     // if(bit & ...)
7684     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7685       genIfxJump(ifx, "c");           
7686     goto release ;
7687   }
7688
7689   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7690   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7691   if((AOP_TYPE(right) == AOP_LIT) &&
7692      (AOP_TYPE(result) == AOP_CRY) &&
7693      (AOP_TYPE(left) != AOP_CRY)){
7694     int posbit = isLiteralBit(lit);
7695     /* left &  2^n */
7696     if(posbit){
7697       posbit--;
7698       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7699       // bit = left & 2^n
7700       if(size)
7701         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7702       // if(left &  2^n)
7703       else{
7704         if(ifx){
7705 /*
7706           if(IC_TRUE(ifx)) {
7707             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7708             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7709           } else {
7710             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7711             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7712           }
7713 */
7714         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7715         size = AOP_SIZE(left);
7716
7717         {
7718           int bp = posbit, ofs=0;
7719           
7720             while(bp > 7) {
7721               bp -= 8;
7722               ofs++;
7723             }
7724
7725           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7726                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7727
7728         }
7729 /*
7730           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7731                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7732 */
7733           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7734           
7735           ifx->generated = 1;
7736         }
7737         goto release;
7738       }
7739     } else {
7740       symbol *tlbl = newiTempLabel(NULL);
7741       int sizel = AOP_SIZE(left);
7742
7743       if(size)
7744         emitSETC;
7745
7746       while(sizel--) {
7747         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7748
7749           /* patch provided by Aaron Colwell */
7750           if((posbit = isLiteralBit(bytelit)) != 0) {
7751               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7752                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7753                                                 (posbit-1),0, PO_GPR_REGISTER));
7754
7755               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7756 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7757           } else {
7758               if (bytelit == 0xff) {
7759                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7760                    * a peephole could optimize it out -- VR */
7761                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7762               } else {
7763                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7764                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7765               }
7766
7767               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7768                             pic16_popGetLabel(tlbl->key));
7769           }
7770         
7771 #if 0
7772           /* old code, left here for reference -- VR 09/2004 */
7773           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7774           // byte ==  2^n ?
7775           if((posbit = isLiteralBit(bytelit)) != 0)
7776             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7777           else{
7778             if(bytelit != 0x0FFL)
7779               pic16_emitcode("anl","a,%s",
7780                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7781             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7782           }
7783 #endif
7784         }
7785         offset++;
7786       }
7787       // bit = left & literal
7788       if(size) {
7789         emitCLRC;
7790         pic16_emitpLabel(tlbl->key);
7791       }
7792       // if(left & literal)
7793       else {
7794         if(ifx) {
7795           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7796           ifx->generated = 1;
7797         }
7798         pic16_emitpLabel(tlbl->key);
7799         goto release;
7800       }
7801     }
7802
7803     pic16_outBitC(result);
7804     goto release ;
7805   }
7806
7807   /* if left is same as result */
7808   if(pic16_sameRegs(AOP(result),AOP(left))){
7809     int know_W = -1;
7810     for(;size--; offset++,lit>>=8) {
7811       if(AOP_TYPE(right) == AOP_LIT){
7812         switch(lit & 0xff) {
7813         case 0x00:
7814           /*  and'ing with 0 has clears the result */
7815 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7816           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7817           break;
7818         case 0xff:
7819           /* and'ing with 0xff is a nop when the result and left are the same */
7820           break;
7821
7822         default:
7823           {
7824             int p = pic16_my_powof2( (~lit) & 0xff );
7825             if(p>=0) {
7826               /* only one bit is set in the literal, so use a bcf instruction */
7827 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7828               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7829
7830             } else {
7831               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7832               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7833               if(know_W != (lit&0xff))
7834                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7835               know_W = lit &0xff;
7836               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7837             }
7838           }    
7839         }
7840       } else {
7841         if (AOP_TYPE(left) == AOP_ACC) {
7842           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7843         } else {                    
7844           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7845           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7846
7847         }
7848       }
7849     }
7850
7851   } else {
7852     // left & result in different registers
7853     if(AOP_TYPE(result) == AOP_CRY){
7854       // result = bit
7855       // if(size), result in bit
7856       // if(!size && ifx), conditional oper: if(left & right)
7857       symbol *tlbl = newiTempLabel(NULL);
7858       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7859       if(size)
7860         pic16_emitcode("setb","c");
7861       while(sizer--){
7862         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7863         pic16_emitcode("anl","a,%s",
7864                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7865         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7866         offset++;
7867       }
7868       if(size){
7869         CLRC;
7870         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7871         pic16_outBitC(result);
7872       } else if(ifx)
7873         jmpTrueOrFalse(ifx, tlbl);
7874     } else {
7875       for(;(size--);offset++) {
7876         // normal case
7877         // result = left & right
7878         if(AOP_TYPE(right) == AOP_LIT){
7879           int t = (lit >> (offset*8)) & 0x0FFL;
7880           switch(t) { 
7881           case 0x00:
7882             pic16_emitcode("clrf","%s",
7883                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7884             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7885             break;
7886           case 0xff:
7887             pic16_emitcode("movf","%s,w",
7888                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7889             pic16_emitcode("movwf","%s",
7890                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7891             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7892             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7893             break;
7894           default:
7895             pic16_emitcode("movlw","0x%x",t);
7896             pic16_emitcode("andwf","%s,w",
7897                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7898             pic16_emitcode("movwf","%s",
7899                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7900               
7901             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7902             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7903             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7904           }
7905           continue;
7906         }
7907
7908         if (AOP_TYPE(left) == AOP_ACC) {
7909           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7910           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7911         } else {
7912           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7913           pic16_emitcode("andwf","%s,w",
7914                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7915           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7916           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7917         }
7918         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7919         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7920       }
7921     }
7922   }
7923
7924   release :
7925     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7926   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7927   pic16_freeAsmop(result,NULL,ic,TRUE);     
7928 }
7929
7930 /*-----------------------------------------------------------------*/
7931 /* genOr  - code for or                                            */
7932 /*-----------------------------------------------------------------*/
7933 static void genOr (iCode *ic, iCode *ifx)
7934 {
7935     operand *left, *right, *result;
7936     int size, offset=0;
7937     unsigned long lit = 0L;
7938
7939     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7940     FENTRY;
7941
7942     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7943     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7944     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7945
7946     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7947
7948     /* if left is a literal & right is not then exchange them */
7949     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7950         AOP_NEEDSACC(left)) {
7951         operand *tmp = right ;
7952         right = left;
7953         left = tmp;
7954     }
7955
7956     /* if result = right then exchange them */
7957     if(pic16_sameRegs(AOP(result),AOP(right))){
7958         operand *tmp = right ;
7959         right = left;
7960         left = tmp;
7961     }
7962
7963     /* if right is bit then exchange them */
7964     if (AOP_TYPE(right) == AOP_CRY &&
7965         AOP_TYPE(left) != AOP_CRY){
7966         operand *tmp = right ;
7967         right = left;
7968         left = tmp;
7969     }
7970
7971     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7972
7973     if(AOP_TYPE(right) == AOP_LIT)
7974         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7975
7976     size = AOP_SIZE(result);
7977
7978     // if(bit | yy)
7979     // xx = bit | yy;
7980     if (AOP_TYPE(left) == AOP_CRY){
7981         if(AOP_TYPE(right) == AOP_LIT){
7982             // c = bit & literal;
7983             if(lit){
7984                 // lit != 0 => result = 1
7985                 if(AOP_TYPE(result) == AOP_CRY){
7986                   if(size)
7987                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7988                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7989                   //     AOP(result)->aopu.aop_dir,
7990                   //     AOP(result)->aopu.aop_dir);
7991                     else if(ifx)
7992                         continueIfTrue(ifx);
7993                     goto release;
7994                 }
7995             } else {
7996                 // lit == 0 => result = left
7997                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7998                     goto release;
7999                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8000             }
8001         } else {
8002             if (AOP_TYPE(right) == AOP_CRY){
8003               if(pic16_sameRegs(AOP(result),AOP(left))){
8004                 // c = bit | bit;
8005                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8006                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8007                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8008
8009                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8010                          AOP(result)->aopu.aop_dir,
8011                          AOP(result)->aopu.aop_dir);
8012                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8013                          AOP(right)->aopu.aop_dir,
8014                          AOP(right)->aopu.aop_dir);
8015                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8016                          AOP(result)->aopu.aop_dir,
8017                          AOP(result)->aopu.aop_dir);
8018               } else {
8019                 if( AOP_TYPE(result) == AOP_ACC) {
8020                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8021                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8022                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8023                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8024
8025                 } else {
8026
8027                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8028                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8029                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8030                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8031
8032                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8033                                  AOP(result)->aopu.aop_dir,
8034                                  AOP(result)->aopu.aop_dir);
8035                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8036                                  AOP(right)->aopu.aop_dir,
8037                                  AOP(right)->aopu.aop_dir);
8038                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8039                                  AOP(left)->aopu.aop_dir,
8040                                  AOP(left)->aopu.aop_dir);
8041                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8042                                  AOP(result)->aopu.aop_dir,
8043                                  AOP(result)->aopu.aop_dir);
8044                 }
8045               }
8046             } else {
8047                 // c = bit | val;
8048                 symbol *tlbl = newiTempLabel(NULL);
8049                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8050
8051
8052                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8053                 if( AOP_TYPE(right) == AOP_ACC) {
8054                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8055                   emitSKPNZ;
8056                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8057                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8058                 }
8059
8060
8061
8062                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8063                     pic16_emitcode(";XXX setb","c");
8064                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8065                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8066                 pic16_toBoolean(right);
8067                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8068                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8069                     jmpTrueOrFalse(ifx, tlbl);
8070                     goto release;
8071                 } else {
8072                     CLRC;
8073                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8074                 }
8075             }
8076         }
8077         // bit = c
8078         // val = c
8079         if(size)
8080             pic16_outBitC(result);
8081         // if(bit | ...)
8082         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8083             genIfxJump(ifx, "c");           
8084         goto release ;
8085     }
8086
8087     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8088     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8089     if((AOP_TYPE(right) == AOP_LIT) &&
8090        (AOP_TYPE(result) == AOP_CRY) &&
8091        (AOP_TYPE(left) != AOP_CRY)){
8092         if(lit){
8093           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8094             // result = 1
8095             if(size)
8096                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8097             else 
8098                 continueIfTrue(ifx);
8099             goto release;
8100         } else {
8101           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8102             // lit = 0, result = boolean(left)
8103             if(size)
8104                 pic16_emitcode(";XXX setb","c");
8105             pic16_toBoolean(right);
8106             if(size){
8107                 symbol *tlbl = newiTempLabel(NULL);
8108                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8109                 CLRC;
8110                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8111             } else {
8112                 genIfxJump (ifx,"a");
8113                 goto release;
8114             }
8115         }
8116         pic16_outBitC(result);
8117         goto release ;
8118     }
8119
8120     /* if left is same as result */
8121     if(pic16_sameRegs(AOP(result),AOP(left))){
8122       int know_W = -1;
8123       for(;size--; offset++,lit>>=8) {
8124         if(AOP_TYPE(right) == AOP_LIT){
8125           if((lit & 0xff) == 0)
8126             /*  or'ing with 0 has no effect */
8127             continue;
8128           else {
8129             int p = pic16_my_powof2(lit & 0xff);
8130             if(p>=0) {
8131               /* only one bit is set in the literal, so use a bsf instruction */
8132               pic16_emitpcode(POC_BSF,
8133                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8134             } else {
8135               if(know_W != (lit & 0xff))
8136                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8137               know_W = lit & 0xff;
8138               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8139             }
8140                     
8141           }
8142         } else {
8143           if (AOP_TYPE(left) == AOP_ACC) {
8144             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8145 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8146           } else {                  
8147             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8148             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8149
8150 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8151 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8152
8153           }
8154         }
8155       }
8156     } else {
8157         // left & result in different registers
8158         if(AOP_TYPE(result) == AOP_CRY){
8159             // result = bit
8160             // if(size), result in bit
8161             // if(!size && ifx), conditional oper: if(left | right)
8162             symbol *tlbl = newiTempLabel(NULL);
8163             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8164             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8165
8166
8167             if(size)
8168                 pic16_emitcode(";XXX setb","c");
8169             while(sizer--){
8170                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8171                 pic16_emitcode(";XXX orl","a,%s",
8172                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8173                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8174                 offset++;
8175             }
8176             if(size){
8177                 CLRC;
8178                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8179                 pic16_outBitC(result);
8180             } else if(ifx)
8181                 jmpTrueOrFalse(ifx, tlbl);
8182         } else for(;(size--);offset++){
8183           // normal case
8184           // result = left & right
8185           if(AOP_TYPE(right) == AOP_LIT){
8186             int t = (lit >> (offset*8)) & 0x0FFL;
8187             switch(t) { 
8188             case 0x00:
8189               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8190               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8191
8192 //            pic16_emitcode("movf","%s,w",
8193 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8194 //            pic16_emitcode("movwf","%s",
8195 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8196               break;
8197             default:
8198               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8199               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8200               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8201
8202 //            pic16_emitcode("movlw","0x%x",t);
8203 //            pic16_emitcode("iorwf","%s,w",
8204 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8205 //            pic16_emitcode("movwf","%s",
8206 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8207               
8208             }
8209             continue;
8210           }
8211
8212           // faster than result <- left, anl result,right
8213           // and better if result is SFR
8214           if (AOP_TYPE(left) == AOP_ACC) {
8215             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8216 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8217           } else {
8218             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8219             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8220
8221 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8222 //          pic16_emitcode("iorwf","%s,w",
8223 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8224           }
8225           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8226 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8227         }
8228     }
8229
8230 release :
8231     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8232     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8233     pic16_freeAsmop(result,NULL,ic,TRUE);     
8234 }
8235
8236 /*-----------------------------------------------------------------*/
8237 /* genXor - code for xclusive or                                   */
8238 /*-----------------------------------------------------------------*/
8239 static void genXor (iCode *ic, iCode *ifx)
8240 {
8241   operand *left, *right, *result;
8242   int size, offset=0;
8243   unsigned long lit = 0L;
8244
8245   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8246   FENTRY;
8247
8248   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8249   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8250   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8251
8252   /* if left is a literal & right is not ||
8253      if left needs acc & right does not */
8254   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8255       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8256     operand *tmp = right ;
8257     right = left;
8258     left = tmp;
8259   }
8260
8261   /* if result = right then exchange them */
8262   if(pic16_sameRegs(AOP(result),AOP(right))){
8263     operand *tmp = right ;
8264     right = left;
8265     left = tmp;
8266   }
8267
8268   /* if right is bit then exchange them */
8269   if (AOP_TYPE(right) == AOP_CRY &&
8270       AOP_TYPE(left) != AOP_CRY){
8271     operand *tmp = right ;
8272     right = left;
8273     left = tmp;
8274   }
8275   if(AOP_TYPE(right) == AOP_LIT)
8276     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8277
8278   size = AOP_SIZE(result);
8279
8280   // if(bit ^ yy)
8281   // xx = bit ^ yy;
8282   if (AOP_TYPE(left) == AOP_CRY){
8283     if(AOP_TYPE(right) == AOP_LIT){
8284       // c = bit & literal;
8285       if(lit>>1){
8286         // lit>>1  != 0 => result = 1
8287         if(AOP_TYPE(result) == AOP_CRY){
8288           if(size)
8289             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8290             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8291           else if(ifx)
8292             continueIfTrue(ifx);
8293           goto release;
8294         }
8295         pic16_emitcode("setb","c");
8296       } else{
8297         // lit == (0 or 1)
8298         if(lit == 0){
8299           // lit == 0, result = left
8300           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8301             goto release;
8302           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8303         } else{
8304           // lit == 1, result = not(left)
8305           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8306             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8307             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8308             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8309             goto release;
8310           } else {
8311             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8312             pic16_emitcode("cpl","c");
8313           }
8314         }
8315       }
8316
8317     } else {
8318       // right != literal
8319       symbol *tlbl = newiTempLabel(NULL);
8320       if (AOP_TYPE(right) == AOP_CRY){
8321         // c = bit ^ bit;
8322         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8323       }
8324       else{
8325         int sizer = AOP_SIZE(right);
8326         // c = bit ^ val
8327         // if val>>1 != 0, result = 1
8328         pic16_emitcode("setb","c");
8329         while(sizer){
8330           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8331           if(sizer == 1)
8332             // test the msb of the lsb
8333             pic16_emitcode("anl","a,#0xfe");
8334           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8335           sizer--;
8336         }
8337         // val = (0,1)
8338         pic16_emitcode("rrc","a");
8339       }
8340       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8341       pic16_emitcode("cpl","c");
8342       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8343     }
8344     // bit = c
8345     // val = c
8346     if(size)
8347       pic16_outBitC(result);
8348     // if(bit | ...)
8349     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8350       genIfxJump(ifx, "c");           
8351     goto release ;
8352   }
8353
8354   if(pic16_sameRegs(AOP(result),AOP(left))){
8355     /* if left is same as result */
8356     for(;size--; offset++) {
8357       if(AOP_TYPE(right) == AOP_LIT){
8358         int t  = (lit >> (offset*8)) & 0x0FFL;
8359         if(t == 0x00L)
8360           continue;
8361         else
8362           if (IS_AOP_PREG(left)) {
8363             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8364             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8365             pic16_aopPut(AOP(result),"a",offset);
8366           } else {
8367             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8368             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8369             pic16_emitcode("xrl","%s,%s",
8370                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8371                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8372           }
8373       } else {
8374         if (AOP_TYPE(left) == AOP_ACC)
8375           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8376         else {
8377           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8378           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8379 /*
8380           if (IS_AOP_PREG(left)) {
8381             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8382             pic16_aopPut(AOP(result),"a",offset);
8383           } else
8384             pic16_emitcode("xrl","%s,a",
8385                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8386 */
8387         }
8388       }
8389     }
8390   } else {
8391     // left & result in different registers
8392     if(AOP_TYPE(result) == AOP_CRY){
8393       // result = bit
8394       // if(size), result in bit
8395       // if(!size && ifx), conditional oper: if(left ^ right)
8396       symbol *tlbl = newiTempLabel(NULL);
8397       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8398       if(size)
8399         pic16_emitcode("setb","c");
8400       while(sizer--){
8401         if((AOP_TYPE(right) == AOP_LIT) &&
8402            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8403           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8404         } else {
8405           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8406           pic16_emitcode("xrl","a,%s",
8407                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8408         }
8409         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8410         offset++;
8411       }
8412       if(size){
8413         CLRC;
8414         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8415         pic16_outBitC(result);
8416       } else if(ifx)
8417         jmpTrueOrFalse(ifx, tlbl);
8418     } else for(;(size--);offset++){
8419       // normal case
8420       // result = left & right
8421       if(AOP_TYPE(right) == AOP_LIT){
8422         int t = (lit >> (offset*8)) & 0x0FFL;
8423         switch(t) { 
8424         case 0x00:
8425           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8426           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8427           pic16_emitcode("movf","%s,w",
8428                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8429           pic16_emitcode("movwf","%s",
8430                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8431           break;
8432         case 0xff:
8433           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8434           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8435           pic16_emitcode("comf","%s,w",
8436                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8437           pic16_emitcode("movwf","%s",
8438                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8439           break;
8440         default:
8441           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8442           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8443           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8444           pic16_emitcode("movlw","0x%x",t);
8445           pic16_emitcode("xorwf","%s,w",
8446                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8447           pic16_emitcode("movwf","%s",
8448                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8449
8450         }
8451         continue;
8452       }
8453
8454       // faster than result <- left, anl result,right
8455       // and better if result is SFR
8456       if (AOP_TYPE(left) == AOP_ACC) {
8457         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8458         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8459       } else {
8460         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8461         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8462         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8463         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8464       }
8465       if ( AOP_TYPE(result) != AOP_ACC){
8466         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8467         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8468       }
8469     }
8470   }
8471
8472   release :
8473     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8474   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8475   pic16_freeAsmop(result,NULL,ic,TRUE);     
8476 }
8477
8478 /*-----------------------------------------------------------------*/
8479 /* genInline - write the inline code out                           */
8480 /*-----------------------------------------------------------------*/
8481 static void genInline (iCode *ic)
8482 {
8483   char *buffer, *bp, *bp1;
8484     
8485         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8486
8487         _G.inLine += (!options.asmpeep);
8488
8489         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8490         strcpy(buffer,IC_INLINE(ic));
8491         
8492         while((bp1=strstr(bp, "\\n"))) {
8493           *bp1++ = '\n';
8494           *bp1++ = ' ';
8495           bp = bp1;
8496         }
8497         bp = bp1 = buffer;
8498
8499 #if 0
8500   /* This is an experimental code for #pragma inline
8501      and is temporarily disabled for 2.5.0 release */
8502         if(asmInlineMap)
8503         {
8504           symbol *sym;
8505           char *s;
8506           char *cbuf;
8507           int cblen;
8508
8509             cbuf = Safe_strdup(buffer);
8510             cblen = strlen(buffer)+1;
8511             memset(cbuf, 0, cblen);
8512
8513             bp = buffer;
8514             bp1 = cbuf;
8515             while(*bp) {
8516               if(*bp != '%')*bp1++ = *bp++;
8517               else {
8518                 int i;
8519
8520                   bp++;
8521                   i = *bp - '0';
8522                   if(i>elementsInSet(asmInlineMap))break;
8523                   
8524                   bp++;
8525                   s = indexSet(asmInlineMap, i);
8526                   DEBUGpc("searching symbol s = `%s'", s);
8527                   sym = findSym(SymbolTab, NULL, s);
8528
8529                   if(sym->reqv) {
8530                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8531                   } else {
8532                     strcat(bp1, sym->rname);
8533                   }
8534                   
8535                   while(*bp1)bp1++;
8536               }
8537               
8538               if(strlen(bp1) > cblen - 16) {
8539                 int i = strlen(cbuf);
8540                 cblen += 50;
8541                 cbuf = realloc(cbuf, cblen);
8542                 memset(cbuf+i, 0, 50);
8543                 bp1 = cbuf + i;
8544               }
8545             }
8546             
8547             free(buffer);
8548             buffer = Safe_strdup( cbuf );
8549             free(cbuf);
8550             
8551             bp = bp1 = buffer;
8552         }
8553 #endif  /* 0 */
8554
8555         /* emit each line as a code */
8556         while (*bp) {
8557                 if (*bp == '\n') {
8558                         *bp++ = '\0';
8559
8560                         if(*bp1)
8561                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8562                         bp1 = bp;
8563                 } else {
8564                         if (*bp == ':') {
8565                                 bp++;
8566                                 *bp = '\0';
8567                                 bp++;
8568
8569                                 /* print label, use this special format with NULL directive
8570                                  * to denote that the argument should not be indented with tab */
8571                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8572                                 bp1 = bp;
8573                         } if (*bp == ';') {
8574                                 /* advance to end of line (prevent splitting of comments at ':' */
8575                                 while (*bp && *bp != '\n') {
8576                                         bp++;
8577                                 } // while
8578                         } else
8579                                 bp++;
8580                 }
8581         }
8582
8583         if ((bp1 != bp) && *bp1)
8584                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8585
8586
8587     Safe_free(buffer);
8588
8589     _G.inLine -= (!options.asmpeep);
8590 }
8591
8592 /*-----------------------------------------------------------------*/
8593 /* genRRC - rotate right with carry                                */
8594 /*-----------------------------------------------------------------*/
8595 static void genRRC (iCode *ic)
8596 {
8597   operand *left , *result ;
8598   int size, offset = 0, same;
8599
8600   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8601
8602   /* rotate right with carry */
8603   left = IC_LEFT(ic);
8604   result=IC_RESULT(ic);
8605   pic16_aopOp (left,ic,FALSE);
8606   pic16_aopOp (result,ic,TRUE);
8607
8608   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8609
8610   same = pic16_sameRegs(AOP(result),AOP(left));
8611
8612   size = AOP_SIZE(result);    
8613
8614   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8615
8616   /* get the lsb and put it into the carry */
8617   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8618
8619   offset = 0 ;
8620
8621   while(size--) {
8622
8623     if(same) {
8624       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8625     } else {
8626       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8627       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8628     }
8629
8630     offset++;
8631   }
8632
8633   pic16_freeAsmop(left,NULL,ic,TRUE);
8634   pic16_freeAsmop(result,NULL,ic,TRUE);
8635 }
8636
8637 /*-----------------------------------------------------------------*/
8638 /* genRLC - generate code for rotate left with carry               */
8639 /*-----------------------------------------------------------------*/
8640 static void genRLC (iCode *ic)
8641 {    
8642   operand *left , *result ;
8643   int size, offset = 0;
8644   int same;
8645
8646   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8647   /* rotate right with carry */
8648   left = IC_LEFT(ic);
8649   result=IC_RESULT(ic);
8650   pic16_aopOp (left,ic,FALSE);
8651   pic16_aopOp (result,ic,TRUE);
8652
8653   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8654
8655   same = pic16_sameRegs(AOP(result),AOP(left));
8656
8657   /* move it to the result */
8658   size = AOP_SIZE(result);    
8659
8660   /* get the msb and put it into the carry */
8661   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8662
8663   offset = 0 ;
8664
8665   while(size--) {
8666
8667     if(same) {
8668       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8669     } else {
8670       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8671       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8672     }
8673
8674     offset++;
8675   }
8676
8677
8678   pic16_freeAsmop(left,NULL,ic,TRUE);
8679   pic16_freeAsmop(result,NULL,ic,TRUE);
8680 }
8681
8682
8683 /* gpasm can get the highest order bit with HIGH/UPPER
8684  * so the following probably is not needed -- VR */
8685  
8686 /*-----------------------------------------------------------------*/
8687 /* genGetHbit - generates code get highest order bit               */
8688 /*-----------------------------------------------------------------*/
8689 static void genGetHbit (iCode *ic)
8690 {
8691     operand *left, *result;
8692     left = IC_LEFT(ic);
8693     result=IC_RESULT(ic);
8694     pic16_aopOp (left,ic,FALSE);
8695     pic16_aopOp (result,ic,FALSE);
8696
8697     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8698     /* get the highest order byte into a */
8699     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8700     if(AOP_TYPE(result) == AOP_CRY){
8701         pic16_emitcode("rlc","a");
8702         pic16_outBitC(result);
8703     }
8704     else{
8705         pic16_emitcode("rl","a");
8706         pic16_emitcode("anl","a,#0x01");
8707         pic16_outAcc(result);
8708     }
8709
8710
8711     pic16_freeAsmop(left,NULL,ic,TRUE);
8712     pic16_freeAsmop(result,NULL,ic,TRUE);
8713 }
8714
8715 #if 0
8716 /*-----------------------------------------------------------------*/
8717 /* AccRol - rotate left accumulator by known count                 */
8718 /*-----------------------------------------------------------------*/
8719 static void AccRol (int shCount)
8720 {
8721     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8722     shCount &= 0x0007;              // shCount : 0..7
8723     switch(shCount){
8724         case 0 :
8725             break;
8726         case 1 :
8727             pic16_emitcode("rl","a");
8728             break;
8729         case 2 :
8730             pic16_emitcode("rl","a");
8731             pic16_emitcode("rl","a");
8732             break;
8733         case 3 :
8734             pic16_emitcode("swap","a");
8735             pic16_emitcode("rr","a");
8736             break;
8737         case 4 :
8738             pic16_emitcode("swap","a");
8739             break;
8740         case 5 :
8741             pic16_emitcode("swap","a");
8742             pic16_emitcode("rl","a");
8743             break;
8744         case 6 :
8745             pic16_emitcode("rr","a");
8746             pic16_emitcode("rr","a");
8747             break;
8748         case 7 :
8749             pic16_emitcode("rr","a");
8750             break;
8751     }
8752 }
8753 #endif
8754
8755 /*-----------------------------------------------------------------*/
8756 /* AccLsh - left shift accumulator by known count                  */
8757 /*-----------------------------------------------------------------*/
8758 static void AccLsh (int shCount, int doMask)
8759 {
8760         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8761         switch(shCount){
8762                 case 0 :
8763                         return;
8764                         break;
8765                 case 1 :
8766                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8767                         break;
8768                 case 2 :
8769                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8770                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8771                         break;
8772                 case 3 :
8773                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8774                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8775                         break;
8776                 case 4 :
8777                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8778                         break;
8779                 case 5 :
8780                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8781                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8782                         break;
8783                 case 6 :
8784                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8785                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8786                         break;
8787                 case 7 :
8788                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8789                         break;
8790         }
8791         if (doMask) {
8792                 /* no masking is required in genPackBits */
8793                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8794         }
8795 }
8796
8797 /*-----------------------------------------------------------------*/
8798 /* AccRsh - right shift accumulator by known count                 */
8799 /*-----------------------------------------------------------------*/
8800 static void AccRsh (int shCount, int andmask)
8801 {
8802         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8803         switch(shCount){
8804                 case 0 :
8805                         return; break;
8806                 case 1 :
8807                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8808                         break;
8809                 case 2 :
8810                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8811                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8812                         break;
8813                 case 3 :
8814                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8815                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8816                         break;
8817                 case 4 :
8818                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8819                         break;
8820                 case 5 :
8821                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8822                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8823                         break;
8824                 case 6 :
8825                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8826                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8827                         break;
8828                 case 7 :
8829                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8830                         break;
8831         }
8832         
8833         if(andmask)
8834                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8835         else
8836                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8837 }
8838
8839 #if 0
8840 /*-----------------------------------------------------------------*/
8841 /* AccSRsh - signed right shift accumulator by known count                 */
8842 /*-----------------------------------------------------------------*/
8843 static void AccSRsh (int shCount)
8844 {
8845     symbol *tlbl ;
8846     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8847     if(shCount != 0){
8848         if(shCount == 1){
8849             pic16_emitcode("mov","c,acc.7");
8850             pic16_emitcode("rrc","a");
8851         } else if(shCount == 2){
8852             pic16_emitcode("mov","c,acc.7");
8853             pic16_emitcode("rrc","a");
8854             pic16_emitcode("mov","c,acc.7");
8855             pic16_emitcode("rrc","a");
8856         } else {
8857             tlbl = newiTempLabel(NULL);
8858             /* rotate right accumulator */
8859             AccRol(8 - shCount);
8860             /* and kill the higher order bits */
8861             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8862             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8863             pic16_emitcode("orl","a,#0x%02x",
8864                      (unsigned char)~SRMask[shCount]);
8865             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8866         }
8867     }
8868 }
8869 #endif
8870
8871 /*-----------------------------------------------------------------*/
8872 /* shiftR1Left2Result - shift right one byte from left to result   */
8873 /*-----------------------------------------------------------------*/
8874 static void shiftR1Left2ResultSigned (operand *left, int offl,
8875                                 operand *result, int offr,
8876                                 int shCount)
8877 {
8878   int same;
8879
8880   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8881
8882   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8883
8884   switch(shCount) {
8885   case 1:
8886     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8887     if(same) 
8888       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8889     else {
8890       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8891       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8892     }
8893
8894     break;
8895   case 2:
8896
8897     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8898     if(same) 
8899       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8900     else {
8901       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8902       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8903     }
8904     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8905     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8906
8907     break;
8908
8909   case 3:
8910     if(same)
8911       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8912     else {
8913       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8914       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8915     }
8916
8917     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8918     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8919     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8920
8921     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8922     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8923
8924     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8925     break;
8926
8927   case 4:
8928     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8929     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8930     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8931     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8932     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8933     break;
8934   case 5:
8935     if(same) {
8936       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8937     } else {
8938       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8939       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8940     }
8941     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8942     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8943     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8944     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8945     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8946     break;
8947
8948   case 6:
8949     if(same) {
8950       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8951       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8952       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8953       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8954       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8955       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8956     } else {
8957       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8958       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8959       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8960       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8961       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8962     }
8963     break;
8964
8965   case 7:
8966     if(same) {
8967       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8968       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8969       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8970       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8971     } else {
8972       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8973       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8974       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8975     }
8976
8977   default:
8978     break;
8979   }
8980 }
8981
8982 /*-----------------------------------------------------------------*/
8983 /* shiftR1Left2Result - shift right one byte from left to result   */
8984 /*-----------------------------------------------------------------*/
8985 static void shiftR1Left2Result (operand *left, int offl,
8986                                 operand *result, int offr,
8987                                 int shCount, int sign)
8988 {
8989   int same;
8990
8991   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8992
8993   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8994
8995   /* Copy the msb into the carry if signed. */
8996   if(sign) {
8997     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8998     return;
8999   }
9000
9001
9002
9003   switch(shCount) {
9004   case 1:
9005     emitCLRC;
9006     if(same) 
9007       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9008     else {
9009       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9010       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9011     }
9012     break;
9013   case 2:
9014     emitCLRC;
9015     if(same) {
9016       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9017     } else {
9018       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9019       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9020     }
9021     emitCLRC;
9022     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9023
9024     break;
9025   case 3:
9026     if(same)
9027       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9028     else {
9029       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9030       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9031     }
9032
9033     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9034     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9035     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9036     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9037     break;
9038       
9039   case 4:
9040     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9041     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9042     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9043     break;
9044
9045   case 5:
9046     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9047     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9048     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9049     //emitCLRC;
9050     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9051
9052     break;
9053   case 6:
9054
9055     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9056     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9057     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9058     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9059     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9060     break;
9061
9062   case 7:
9063
9064     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9065     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9066     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9067
9068     break;
9069
9070   default:
9071     break;
9072   }
9073 }
9074
9075 /*-----------------------------------------------------------------*/
9076 /* shiftL1Left2Result - shift left one byte from left to result    */
9077 /*-----------------------------------------------------------------*/
9078 static void shiftL1Left2Result (operand *left, int offl,
9079                                 operand *result, int offr, int shCount)
9080 {
9081   int same;
9082
9083   //    char *l;
9084   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9085
9086   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9087   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9088     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9089     //    MOVA(l);
9090     /* shift left accumulator */
9091     //AccLsh(shCount, 1); // don't comment out just yet...
9092   //    pic16_aopPut(AOP(result),"a",offr);
9093
9094   switch(shCount) {
9095   case 1:
9096     /* Shift left 1 bit position */
9097     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9098     if(same) {
9099       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9100     } else {
9101       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9102       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9103     }
9104     break;
9105   case 2:
9106     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9107     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9108     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9109     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9110     break;
9111   case 3:
9112     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9113     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9114     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9115     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9116     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9117     break;
9118   case 4:
9119     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9120     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9121     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9122     break;
9123   case 5:
9124     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9125     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9126     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9127     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9128     break;
9129   case 6:
9130     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9131     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9132     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9133     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9134     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9135     break;
9136   case 7:
9137     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9138     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9139     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9140     break;
9141
9142   default:
9143     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9144   }
9145
9146 }
9147
9148 /*-----------------------------------------------------------------*/
9149 /* movLeft2Result - move byte from left to result                  */
9150 /*-----------------------------------------------------------------*/
9151 static void movLeft2Result (operand *left, int offl,
9152                             operand *result, int offr)
9153 {
9154   char *l;
9155   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9156   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9157     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9158
9159     if (*l == '@' && (IS_AOP_PREG(result))) {
9160       pic16_emitcode("mov","a,%s",l);
9161       pic16_aopPut(AOP(result),"a",offr);
9162     } else {
9163       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9164       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9165     }
9166   }
9167 }
9168
9169 /*-----------------------------------------------------------------*/
9170 /* shiftL2Left2Result - shift left two bytes from left to result   */
9171 /*-----------------------------------------------------------------*/
9172 static void shiftL2Left2Result (operand *left, int offl,
9173                                 operand *result, int offr, int shCount)
9174 {
9175   int same = pic16_sameRegs(AOP(result), AOP(left));
9176   int i;
9177
9178   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9179
9180   if (same && (offl != offr)) { // shift bytes
9181     if (offr > offl) {
9182        for(i=1;i>-1;i--) {
9183          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9184          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9185        }
9186     } else { // just treat as different later on
9187                 same = 0;
9188     }
9189   }
9190
9191   if(same) {
9192     switch(shCount) {
9193     case 0:
9194       break;
9195     case 1:
9196     case 2:
9197     case 3:
9198
9199       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9200       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9201       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9202
9203       while(--shCount) {
9204                 emitCLRC;
9205                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9206                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9207       }
9208
9209       break;
9210     case 4:
9211     case 5:
9212       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9213       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9214       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9215       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9216       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9217       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9218       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9219       if(shCount >=5) {
9220                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9221                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9222       }
9223       break;
9224     case 6:
9225       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9226       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9227       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9228       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9229       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9230       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9231       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9232       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9233       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9234       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9235       break;
9236     case 7:
9237       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9238       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9239       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9240       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9241       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9242     }
9243
9244   } else {
9245     switch(shCount) {
9246     case 0:
9247       break;
9248     case 1:
9249     case 2:
9250     case 3:
9251       /* note, use a mov/add for the shift since the mov has a
9252          chance of getting optimized out */
9253       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9254       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9255       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9256       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9257       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9258
9259       while(--shCount) {
9260                 emitCLRC;
9261                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9262                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9263       }
9264       break;
9265
9266     case 4:
9267     case 5:
9268       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9269       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9270       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9271       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9272       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9273       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9274       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9275       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9276
9277
9278       if(shCount == 5) {
9279                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9280                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9281       }
9282       break;
9283     case 6:
9284       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9285       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9286       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9287       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9288
9289       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9290       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9291       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9292       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9293       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9294       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9295       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9296       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9297       break;
9298     case 7:
9299       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9300       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9301       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9302       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9303       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9304     }
9305   }
9306
9307 }
9308 /*-----------------------------------------------------------------*/
9309 /* shiftR2Left2Result - shift right two bytes from left to result  */
9310 /*-----------------------------------------------------------------*/
9311 static void shiftR2Left2Result (operand *left, int offl,
9312                                 operand *result, int offr,
9313                                 int shCount, int sign)
9314 {
9315   int same = pic16_sameRegs(AOP(result), AOP(left));
9316   int i;
9317   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9318
9319   if (same && (offl != offr)) { // shift right bytes
9320     if (offr < offl) {
9321        for(i=0;i<2;i++) {
9322          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9323          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9324        }
9325     } else { // just treat as different later on
9326                 same = 0;
9327     }
9328   }
9329
9330   switch(shCount) {
9331   case 0:
9332     break;
9333   case 1:
9334   case 2:
9335   case 3:
9336     /* obtain sign from left operand */
9337     if(sign)
9338       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9339     else
9340       emitCLRC;
9341
9342     if(same) {
9343       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9344       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9345     } else {
9346       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9347       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9348       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9349       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9350     }
9351
9352     while(--shCount) {
9353       if(sign)
9354         /* now get sign from already assigned result (avoid BANKSEL) */
9355         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9356       else
9357         emitCLRC;
9358       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9359       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9360     }
9361     break;
9362   case 4:
9363   case 5:
9364     if(same) {
9365
9366       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9367       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9368       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9369
9370       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9371       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9372       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9373       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9374     } else {
9375       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9376       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9377       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9378
9379       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9380       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9381       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9382       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9383       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9384     }
9385
9386     if(shCount >=5) {
9387       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9388       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9389     }
9390
9391     if(sign) {
9392       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9393       pic16_emitpcode(POC_BTFSC, 
9394                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9395       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9396     }
9397
9398     break;
9399
9400   case 6:
9401     if(same) {
9402
9403       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9404       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9405
9406       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9407       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9408       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9409       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9410       if(sign) {
9411         pic16_emitpcode(POC_BTFSC, 
9412                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9413         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9414       }
9415       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9416       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9417       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9418       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9419     } else {
9420       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9421       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9422       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9423       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9424       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9425       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9426       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9427       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9428       if(sign) {
9429         pic16_emitpcode(POC_BTFSC, 
9430                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9431         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9432       }
9433       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9434       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9435
9436         
9437     }
9438
9439     break;
9440   case 7:
9441     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9442     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9443     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9444     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9445     if(sign) {
9446       emitSKPNC;
9447       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9448     } else 
9449       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9450   }
9451 }
9452
9453
9454 /*-----------------------------------------------------------------*/
9455 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9456 /*-----------------------------------------------------------------*/
9457 static void shiftLLeftOrResult (operand *left, int offl,
9458                                 operand *result, int offr, int shCount)
9459 {
9460     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9461
9462     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9463     /* shift left accumulator */
9464     AccLsh(shCount, 1);
9465     /* or with result */
9466     /* back to result */
9467     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9468 }
9469
9470 /*-----------------------------------------------------------------*/
9471 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9472 /*-----------------------------------------------------------------*/
9473 static void shiftRLeftOrResult (operand *left, int offl,
9474                                 operand *result, int offr, int shCount)
9475 {
9476     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9477     
9478     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9479     /* shift right accumulator */
9480     AccRsh(shCount, 1);
9481     /* or with result */
9482     /* back to result */
9483     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9484 }
9485
9486 /*-----------------------------------------------------------------*/
9487 /* genlshOne - left shift a one byte quantity by known count       */
9488 /*-----------------------------------------------------------------*/
9489 static void genlshOne (operand *result, operand *left, int shCount)
9490 {       
9491     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9492     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9493 }
9494
9495 /*-----------------------------------------------------------------*/
9496 /* genlshTwo - left shift two bytes by known amount != 0           */
9497 /*-----------------------------------------------------------------*/
9498 static void genlshTwo (operand *result,operand *left, int shCount)
9499 {
9500     int size;
9501     
9502     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9503     size = pic16_getDataSize(result);
9504
9505     /* if shCount >= 8 */
9506     if (shCount >= 8) {
9507         shCount -= 8 ;
9508
9509         if (size > 1){
9510             if (shCount)
9511                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9512             else 
9513                 movLeft2Result(left, LSB, result, MSB16);
9514         }
9515         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9516     }
9517
9518     /*  1 <= shCount <= 7 */
9519     else {  
9520         if(size == 1)
9521             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9522         else 
9523             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9524     }
9525 }
9526
9527 /*-----------------------------------------------------------------*/
9528 /* shiftLLong - shift left one long from left to result            */
9529 /* offr = LSB or MSB16                                             */
9530 /*-----------------------------------------------------------------*/
9531 static void shiftLLong (operand *left, operand *result, int offr )
9532 {
9533     int size = AOP_SIZE(result);
9534     int same = pic16_sameRegs(AOP(left),AOP(result));
9535         int i;
9536
9537     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9538
9539         if (same && (offr == MSB16)) { //shift one byte
9540                 for(i=size-1;i>=MSB16;i--) {
9541                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9542                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9543                 }
9544         } else {
9545                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9546         }
9547         
9548     if (size > LSB+offr ){
9549                 if (same) {
9550                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9551                 } else {
9552                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9553                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9554                 }
9555          }
9556
9557     if(size > MSB16+offr){
9558                 if (same) {
9559                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9560                 } else {
9561                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9562                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9563                 }
9564     }
9565
9566     if(size > MSB24+offr){
9567                 if (same) {
9568                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9569                 } else {
9570                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9571                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9572                 }
9573     }
9574
9575     if(size > MSB32+offr){
9576                 if (same) {
9577                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9578                 } else {
9579                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9580                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9581                 }
9582     }
9583     if(offr != LSB)
9584                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9585
9586 }
9587
9588 /*-----------------------------------------------------------------*/
9589 /* genlshFour - shift four byte by a known amount != 0             */
9590 /*-----------------------------------------------------------------*/
9591 static void genlshFour (operand *result, operand *left, int shCount)
9592 {
9593     int size;
9594
9595     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9596     size = AOP_SIZE(result);
9597
9598     /* if shifting more that 3 bytes */
9599     if (shCount >= 24 ) {
9600         shCount -= 24;
9601         if (shCount)
9602             /* lowest order of left goes to the highest
9603             order of the destination */
9604             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9605         else
9606             movLeft2Result(left, LSB, result, MSB32);
9607
9608                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9609                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9610                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9611
9612         return;
9613     }
9614
9615     /* more than two bytes */
9616     else if ( shCount >= 16 ) {
9617         /* lower order two bytes goes to higher order two bytes */
9618         shCount -= 16;
9619         /* if some more remaining */
9620         if (shCount)
9621             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9622         else {
9623             movLeft2Result(left, MSB16, result, MSB32);
9624             movLeft2Result(left, LSB, result, MSB24);
9625         }
9626                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9627                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9628         return;
9629     }    
9630
9631     /* if more than 1 byte */
9632     else if ( shCount >= 8 ) {
9633         /* lower order three bytes goes to higher order  three bytes */
9634         shCount -= 8;
9635         if(size == 2){
9636             if(shCount)
9637                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9638             else
9639                 movLeft2Result(left, LSB, result, MSB16);
9640         }
9641         else{   /* size = 4 */
9642             if(shCount == 0){
9643                 movLeft2Result(left, MSB24, result, MSB32);
9644                 movLeft2Result(left, MSB16, result, MSB24);
9645                 movLeft2Result(left, LSB, result, MSB16);
9646                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9647             }
9648             else if(shCount == 1)
9649                 shiftLLong(left, result, MSB16);
9650             else{
9651                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9652                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9653                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9654                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9655             }
9656         }
9657     }
9658
9659     /* 1 <= shCount <= 7 */
9660     else if(shCount <= 3)
9661     { 
9662         shiftLLong(left, result, LSB);
9663         while(--shCount >= 1)
9664             shiftLLong(result, result, LSB);
9665     }
9666     /* 3 <= shCount <= 7, optimize */
9667     else{
9668         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9669         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9670         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9671     }
9672 }
9673
9674 /*-----------------------------------------------------------------*/
9675 /* genLeftShiftLiteral - left shifting by known count              */
9676 /*-----------------------------------------------------------------*/
9677 void pic16_genLeftShiftLiteral (operand *left,
9678                                  operand *right,
9679                                  operand *result,
9680                                  iCode *ic)
9681 {    
9682     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9683     int size;
9684
9685     FENTRY;
9686     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9687     pic16_freeAsmop(right,NULL,ic,TRUE);
9688
9689     pic16_aopOp(left,ic,FALSE);
9690     pic16_aopOp(result,ic,TRUE);
9691
9692     size = getSize(operandType(result));
9693
9694 #if VIEW_SIZE
9695     pic16_emitcode("; shift left ","result %d, left %d",size,
9696              AOP_SIZE(left));
9697 #endif
9698
9699     /* I suppose that the left size >= result size */
9700     if(shCount == 0){
9701         while(size--){
9702             movLeft2Result(left, size, result, size);
9703         }
9704     }
9705
9706     else if(shCount >= (size * 8))
9707         while(size--)
9708             pic16_aopPut(AOP(result),zero,size);
9709     else{
9710         switch (size) {
9711             case 1:
9712                 genlshOne (result,left,shCount);
9713                 break;
9714
9715             case 2:
9716             case 3:
9717                 genlshTwo (result,left,shCount);
9718                 break;
9719
9720             case 4:
9721                 genlshFour (result,left,shCount);
9722                 break;
9723         }
9724     }
9725     pic16_freeAsmop(left,NULL,ic,TRUE);
9726     pic16_freeAsmop(result,NULL,ic,TRUE);
9727 }
9728
9729 /*-----------------------------------------------------------------*
9730  * genMultiAsm - repeat assembly instruction for size of register.
9731  * if endian == 1, then the high byte (i.e base address + size of 
9732  * register) is used first else the low byte is used first;
9733  *-----------------------------------------------------------------*/
9734 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9735 {
9736
9737   int offset = 0;
9738
9739   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9740
9741   if(!reg)
9742     return;
9743
9744   if(!endian) {
9745     endian = 1;
9746   } else {
9747     endian = -1;
9748     offset = size-1;
9749   }
9750
9751   while(size--) {
9752     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9753     offset += endian;
9754   }
9755
9756 }
9757
9758 #if !(USE_GENERIC_SIGNED_SHIFT)
9759 /*-----------------------------------------------------------------*/
9760 /* genLeftShift - generates code for left shifting                 */
9761 /*-----------------------------------------------------------------*/
9762 static void genLeftShift (iCode *ic)
9763 {
9764   operand *left,*right, *result;
9765   int size, offset;
9766 //  char *l;
9767   symbol *tlbl , *tlbl1;
9768   pCodeOp *pctemp;
9769
9770   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9771
9772   right = IC_RIGHT(ic);
9773   left  = IC_LEFT(ic);
9774   result = IC_RESULT(ic);
9775
9776   pic16_aopOp(right,ic,FALSE);
9777
9778   /* if the shift count is known then do it 
9779      as efficiently as possible */
9780   if (AOP_TYPE(right) == AOP_LIT) {
9781     pic16_genLeftShiftLiteral (left,right,result,ic);
9782     return ;
9783   }
9784
9785   /* shift count is unknown then we have to form
9786    * a loop. Get the loop count in WREG : Note: we take
9787    * only the lower order byte since shifting
9788    * more than 32 bits make no sense anyway, ( the
9789    * largest size of an object can be only 32 bits ) */
9790   
9791   pic16_aopOp(left,ic,FALSE);
9792   pic16_aopOp(result,ic,FALSE);
9793
9794   /* now move the left to the result if they are not the
9795    * same, and if size > 1,
9796    * and if right is not same to result (!!!) -- VR */
9797   if (!pic16_sameRegs(AOP(left),AOP(result))
9798       && (AOP_SIZE(result) > 1)) {
9799
9800     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9801
9802     size = AOP_SIZE(result);
9803     offset=0;
9804     while (size--) {
9805
9806 #if 0
9807       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9808       if (*l == '@' && (IS_AOP_PREG(result))) {
9809
9810           pic16_emitcode("mov","a,%s",l);
9811           pic16_aopPut(AOP(result),"a",offset);
9812       } else
9813 #endif
9814       {
9815         /* we don't know if left is a literal or a register, take care -- VR */
9816         pic16_mov2f(AOP(result), AOP(left), offset);
9817       }
9818       offset++;
9819     }
9820   }
9821
9822   size = AOP_SIZE(result);
9823
9824   /* if it is only one byte then */
9825   if (size == 1) {
9826     if(optimized_for_speed) {
9827       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9828       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9829       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9830       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9831       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9832       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9833       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9834       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9835       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9836       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9837       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9838       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9839     } else {
9840
9841       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9842
9843       tlbl = newiTempLabel(NULL);
9844
9845 #if 1
9846       /* this is already done, why change it? */
9847       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9848                 pic16_mov2f(AOP(result), AOP(left), 0);
9849       }
9850 #endif
9851
9852       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9853       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9854       pic16_emitpLabel(tlbl->key);
9855       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9856       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9857       emitSKPC;
9858       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9859     }
9860     goto release ;
9861   }
9862     
9863   if (pic16_sameRegs(AOP(left),AOP(result))) {
9864
9865     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9866     
9867     tlbl = newiTempLabel(NULL);
9868     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9869     genMultiAsm(POC_RRCF, result, size,1);
9870     pic16_emitpLabel(tlbl->key);
9871     genMultiAsm(POC_RLCF, result, size,0);
9872     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9873     emitSKPC;
9874     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9875     goto release;
9876   }
9877
9878   //tlbl = newiTempLabel(NULL);
9879   //offset = 0 ;   
9880   //tlbl1 = newiTempLabel(NULL);
9881
9882   //reAdjustPreg(AOP(result));    
9883     
9884   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9885   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9886   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9887   //MOVA(l);
9888   //pic16_emitcode("add","a,acc");         
9889   //pic16_aopPut(AOP(result),"a",offset++);
9890   //while (--size) {
9891   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9892   //  MOVA(l);
9893   //  pic16_emitcode("rlc","a");         
9894   //  pic16_aopPut(AOP(result),"a",offset++);
9895   //}
9896   //reAdjustPreg(AOP(result));
9897
9898   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9899   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9900
9901
9902   tlbl = newiTempLabel(NULL);
9903   tlbl1= newiTempLabel(NULL);
9904
9905   size = AOP_SIZE(result);
9906   offset = 1;
9907
9908   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9909
9910   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9911
9912   /* offset should be 0, 1 or 3 */
9913   
9914   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9915   emitSKPNZ;
9916   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9917
9918   pic16_emitpcode(POC_MOVWF, pctemp);
9919
9920
9921   pic16_emitpLabel(tlbl->key);
9922
9923   emitCLRC;
9924   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9925   while(--size)
9926     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9927
9928   pic16_emitpcode(POC_DECFSZ,  pctemp);
9929   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9930   pic16_emitpLabel(tlbl1->key);
9931
9932   pic16_popReleaseTempReg(pctemp,1);
9933
9934
9935  release:
9936   pic16_freeAsmop (right,NULL,ic,TRUE);
9937   pic16_freeAsmop(left,NULL,ic,TRUE);
9938   pic16_freeAsmop(result,NULL,ic,TRUE);
9939 }
9940 #endif
9941
9942
9943 #if 0
9944 #error old code (left here for reference)
9945 /*-----------------------------------------------------------------*/
9946 /* genLeftShift - generates code for left shifting                 */
9947 /*-----------------------------------------------------------------*/
9948 static void genLeftShift (iCode *ic)
9949 {
9950   operand *left,*right, *result;
9951   int size, offset;
9952   char *l;
9953   symbol *tlbl , *tlbl1;
9954   pCodeOp *pctemp;
9955
9956   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9957
9958   right = IC_RIGHT(ic);
9959   left  = IC_LEFT(ic);
9960   result = IC_RESULT(ic);
9961
9962   pic16_aopOp(right,ic,FALSE);
9963
9964   /* if the shift count is known then do it 
9965      as efficiently as possible */
9966   if (AOP_TYPE(right) == AOP_LIT) {
9967     pic16_genLeftShiftLiteral (left,right,result,ic);
9968     return ;
9969   }
9970
9971   /* shift count is unknown then we have to form 
9972      a loop get the loop count in B : Note: we take
9973      only the lower order byte since shifting
9974      more that 32 bits make no sense anyway, ( the
9975      largest size of an object can be only 32 bits ) */  
9976
9977     
9978   pic16_aopOp(left,ic,FALSE);
9979   pic16_aopOp(result,ic,FALSE);
9980
9981   /* now move the left to the result if they are not the
9982      same */
9983   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9984       AOP_SIZE(result) > 1) {
9985
9986     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9987
9988     size = AOP_SIZE(result);
9989     offset=0;
9990     while (size--) {
9991       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9992       if (*l == '@' && (IS_AOP_PREG(result))) {
9993
9994         pic16_emitcode("mov","a,%s",l);
9995         pic16_aopPut(AOP(result),"a",offset);
9996       } else {
9997
9998         /* we don't know if left is a literal or a register, take care -- VR */
9999         pic16_mov2f(AOP(result), AOP(left), offset);
10000       }
10001       offset++;
10002     }
10003   }
10004
10005   size = AOP_SIZE(result);
10006
10007   /* if it is only one byte then */
10008   if (size == 1) {
10009     if(optimized_for_speed) {
10010       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10011       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10012       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10013       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10014       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10015       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10016       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10017       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10018       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10019       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10020       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10021       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10022     } else {
10023
10024       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10025
10026       tlbl = newiTempLabel(NULL);
10027       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10028                 pic16_mov2f(AOP(result), AOP(left), 0);
10029                 
10030 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10031 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10032       }
10033
10034       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10035       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10036       pic16_emitpLabel(tlbl->key);
10037       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10038       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10039       emitSKPC;
10040       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10041     }
10042     goto release ;
10043   }
10044     
10045   if (pic16_sameRegs(AOP(left),AOP(result))) {
10046
10047     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10048     
10049     tlbl = newiTempLabel(NULL);
10050     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10051     genMultiAsm(POC_RRCF, result, size,1);
10052     pic16_emitpLabel(tlbl->key);
10053     genMultiAsm(POC_RLCF, result, size,0);
10054     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10055     emitSKPC;
10056     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10057     goto release;
10058   }
10059
10060   //tlbl = newiTempLabel(NULL);
10061   //offset = 0 ;   
10062   //tlbl1 = newiTempLabel(NULL);
10063
10064   //reAdjustPreg(AOP(result));    
10065     
10066   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10067   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10068   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10069   //MOVA(l);
10070   //pic16_emitcode("add","a,acc");         
10071   //pic16_aopPut(AOP(result),"a",offset++);
10072   //while (--size) {
10073   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10074   //  MOVA(l);
10075   //  pic16_emitcode("rlc","a");         
10076   //  pic16_aopPut(AOP(result),"a",offset++);
10077   //}
10078   //reAdjustPreg(AOP(result));
10079
10080   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10081   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10082
10083
10084   tlbl = newiTempLabel(NULL);
10085   tlbl1= newiTempLabel(NULL);
10086
10087   size = AOP_SIZE(result);
10088   offset = 1;
10089
10090   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10091
10092   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10093
10094   /* offset should be 0, 1 or 3 */
10095   
10096   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10097   emitSKPNZ;
10098   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10099
10100   pic16_emitpcode(POC_MOVWF, pctemp);
10101
10102
10103   pic16_emitpLabel(tlbl->key);
10104
10105   emitCLRC;
10106   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10107   while(--size)
10108     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10109
10110   pic16_emitpcode(POC_DECFSZ,  pctemp);
10111   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10112   pic16_emitpLabel(tlbl1->key);
10113
10114   pic16_popReleaseTempReg(pctemp,1);
10115
10116
10117  release:
10118   pic16_freeAsmop (right,NULL,ic,TRUE);
10119   pic16_freeAsmop(left,NULL,ic,TRUE);
10120   pic16_freeAsmop(result,NULL,ic,TRUE);
10121 }
10122 #endif
10123
10124 /*-----------------------------------------------------------------*/
10125 /* genrshOne - right shift a one byte quantity by known count      */
10126 /*-----------------------------------------------------------------*/
10127 static void genrshOne (operand *result, operand *left,
10128                        int shCount, int sign)
10129 {
10130     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10131     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10132 }
10133
10134 /*-----------------------------------------------------------------*/
10135 /* genrshTwo - right shift two bytes by known amount != 0          */
10136 /*-----------------------------------------------------------------*/
10137 static void genrshTwo (operand *result,operand *left,
10138                        int shCount, int sign)
10139 {
10140   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10141   /* if shCount >= 8 */
10142   if (shCount >= 8) {
10143     shCount -= 8 ;
10144     if (shCount)
10145       shiftR1Left2Result(left, MSB16, result, LSB,
10146                          shCount, sign);
10147     else
10148       movLeft2Result(left, MSB16, result, LSB);
10149
10150     pic16_addSign (result, 1, sign);
10151   }
10152
10153   /*  1 <= shCount <= 7 */
10154   else
10155     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10156 }
10157
10158 /*-----------------------------------------------------------------*/
10159 /* shiftRLong - shift right one long from left to result           */
10160 /* offl = LSB or MSB16                                             */
10161 /*-----------------------------------------------------------------*/
10162 static void shiftRLong (operand *left, int offl,
10163                         operand *result, int sign)
10164 {
10165     int size = AOP_SIZE(result);
10166     int same = pic16_sameRegs(AOP(left),AOP(result));
10167     int i;
10168     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10169
10170         if (same && (offl == MSB16)) { //shift one byte right
10171                 for(i=MSB16;i<size;i++) {
10172                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10173                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10174                 }
10175         }
10176
10177     if(sign)
10178                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10179         else
10180                 emitCLRC;
10181
10182         if (same) {
10183                 if (offl == LSB)
10184                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10185         } else {
10186         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10187         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10188         }
10189
10190     if(offl == MSB16) {
10191         /* add sign of "a" */
10192         pic16_addSign(result, MSB32, sign);
10193         }
10194
10195         if (same) {
10196         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10197         } else {
10198         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10199         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10200         }
10201         
10202         if (same) {
10203         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10204         } else {
10205         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10206         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10207         }
10208
10209         if (same) {
10210         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10211         } else {
10212         if(offl == LSB){
10213                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10214                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10215         }
10216         }
10217 }
10218
10219 /*-----------------------------------------------------------------*/
10220 /* genrshFour - shift four byte by a known amount != 0             */
10221 /*-----------------------------------------------------------------*/
10222 static void genrshFour (operand *result, operand *left,
10223                         int shCount, int sign)
10224 {
10225   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10226   /* if shifting more that 3 bytes */
10227   if(shCount >= 24 ) {
10228     shCount -= 24;
10229     if(shCount)
10230       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10231     else
10232       movLeft2Result(left, MSB32, result, LSB);
10233
10234     pic16_addSign(result, MSB16, sign);
10235   }
10236   else if(shCount >= 16){
10237     shCount -= 16;
10238     if(shCount)
10239       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10240     else{
10241       movLeft2Result(left, MSB24, result, LSB);
10242       movLeft2Result(left, MSB32, result, MSB16);
10243     }
10244     pic16_addSign(result, MSB24, sign);
10245   }
10246   else if(shCount >= 8){
10247     shCount -= 8;
10248     if(shCount == 1)
10249       shiftRLong(left, MSB16, result, sign);
10250     else if(shCount == 0){
10251       movLeft2Result(left, MSB16, result, LSB);
10252       movLeft2Result(left, MSB24, result, MSB16);
10253       movLeft2Result(left, MSB32, result, MSB24);
10254       pic16_addSign(result, MSB32, sign);
10255     }
10256     else{ //shcount >= 2
10257       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10258       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10259       /* the last shift is signed */
10260       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10261       pic16_addSign(result, MSB32, sign);
10262     }
10263   }
10264   else{   /* 1 <= shCount <= 7 */
10265     if(shCount <= 2){
10266       shiftRLong(left, LSB, result, sign);
10267       if(shCount == 2)
10268         shiftRLong(result, LSB, result, sign);
10269     }
10270     else{
10271       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10272       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10273       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10274     }
10275   }
10276 }
10277
10278 /*-----------------------------------------------------------------*/
10279 /* genRightShiftLiteral - right shifting by known count            */
10280 /*-----------------------------------------------------------------*/
10281 static void genRightShiftLiteral (operand *left,
10282                                   operand *right,
10283                                   operand *result,
10284                                   iCode *ic,
10285                                   int sign)
10286 {    
10287   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10288   int lsize,res_size;
10289
10290   pic16_freeAsmop(right,NULL,ic,TRUE);
10291
10292   pic16_aopOp(left,ic,FALSE);
10293   pic16_aopOp(result,ic,TRUE);
10294
10295   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10296
10297 #if VIEW_SIZE
10298   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10299                  AOP_SIZE(left));
10300 #endif
10301
10302   lsize = pic16_getDataSize(left);
10303   res_size = pic16_getDataSize(result);
10304   /* test the LEFT size !!! */
10305
10306   /* I suppose that the left size >= result size */
10307   if(shCount == 0){
10308     assert (res_size <= lsize);
10309     while (res_size--) {
10310       pic16_mov2f (AOP(result), AOP(left), res_size);
10311     } // for
10312   }
10313
10314   else if(shCount >= (lsize * 8)){
10315
10316     if(res_size == 1) {
10317       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10318       if(sign) {
10319         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10320         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10321       }
10322     } else {
10323
10324       if(sign) {
10325         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10326         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10327         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10328         while(res_size--)
10329           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10330
10331       } else {
10332
10333         while(res_size--)
10334           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10335       }
10336     }
10337   } else {
10338
10339     switch (res_size) {
10340     case 1:
10341       genrshOne (result,left,shCount,sign);
10342       break;
10343
10344     case 2:
10345       genrshTwo (result,left,shCount,sign);
10346       break;
10347
10348     case 4:
10349       genrshFour (result,left,shCount,sign);
10350       break;
10351     default :
10352       break;
10353     }
10354
10355   }
10356
10357   pic16_freeAsmop(left,NULL,ic,TRUE);
10358   pic16_freeAsmop(result,NULL,ic,TRUE);
10359 }
10360
10361 #if !(USE_GENERIC_SIGNED_SHIFT)
10362 /*-----------------------------------------------------------------*/
10363 /* genSignedRightShift - right shift of signed number              */
10364 /*-----------------------------------------------------------------*/
10365 static void genSignedRightShift (iCode *ic)
10366 {
10367   operand *right, *left, *result;
10368   int size, offset;
10369   //  char *l;
10370   symbol *tlbl, *tlbl1 ;
10371   pCodeOp *pctemp;
10372
10373   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10374
10375   /* we do it the hard way put the shift count in b
10376      and loop thru preserving the sign */
10377   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10378
10379   right = IC_RIGHT(ic);
10380   left  = IC_LEFT(ic);
10381   result = IC_RESULT(ic);
10382
10383   pic16_aopOp(right,ic,FALSE);  
10384   pic16_aopOp(left,ic,FALSE);
10385   pic16_aopOp(result,ic,FALSE);
10386
10387
10388   if ( AOP_TYPE(right) == AOP_LIT) {
10389     genRightShiftLiteral (left,right,result,ic,1);
10390     return ;
10391   }
10392   /* shift count is unknown then we have to form 
10393      a loop get the loop count in B : Note: we take
10394      only the lower order byte since shifting
10395      more that 32 bits make no sense anyway, ( the
10396      largest size of an object can be only 32 bits ) */  
10397
10398   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10399   //pic16_emitcode("inc","b");
10400   //pic16_freeAsmop (right,NULL,ic,TRUE);
10401   //pic16_aopOp(left,ic,FALSE);
10402   //pic16_aopOp(result,ic,FALSE);
10403
10404   /* now move the left to the result if they are not the
10405      same */
10406   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10407       AOP_SIZE(result) > 1) {
10408
10409     size = AOP_SIZE(result);
10410     offset=0;
10411     while (size--) { 
10412       /*
10413         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10414         if (*l == '@' && IS_AOP_PREG(result)) {
10415
10416         pic16_emitcode("mov","a,%s",l);
10417         pic16_aopPut(AOP(result),"a",offset);
10418         } else
10419         pic16_aopPut(AOP(result),l,offset);
10420       */
10421       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10422       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10423
10424       offset++;
10425     }
10426   }
10427
10428   /* mov the highest order bit to OVR */    
10429   tlbl = newiTempLabel(NULL);
10430   tlbl1= newiTempLabel(NULL);
10431
10432   size = AOP_SIZE(result);
10433   offset = size - 1;
10434
10435   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10436
10437   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10438
10439   /* offset should be 0, 1 or 3 */
10440   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10441   emitSKPNZ;
10442   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10443
10444   pic16_emitpcode(POC_MOVWF, pctemp);
10445
10446
10447   pic16_emitpLabel(tlbl->key);
10448
10449   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10450   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10451
10452   while(--size) {
10453     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10454   }
10455
10456   pic16_emitpcode(POC_DECFSZ,  pctemp);
10457   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10458   pic16_emitpLabel(tlbl1->key);
10459
10460   pic16_popReleaseTempReg(pctemp,1);
10461 #if 0
10462   size = AOP_SIZE(result);
10463   offset = size - 1;
10464   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10465   pic16_emitcode("rlc","a");
10466   pic16_emitcode("mov","ov,c");
10467   /* if it is only one byte then */
10468   if (size == 1) {
10469     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10470     MOVA(l);
10471     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10472     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10473     pic16_emitcode("mov","c,ov");
10474     pic16_emitcode("rrc","a");
10475     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10476     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10477     pic16_aopPut(AOP(result),"a",0);
10478     goto release ;
10479   }
10480
10481   reAdjustPreg(AOP(result));
10482   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10483   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10484   pic16_emitcode("mov","c,ov");
10485   while (size--) {
10486     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10487     MOVA(l);
10488     pic16_emitcode("rrc","a");         
10489     pic16_aopPut(AOP(result),"a",offset--);
10490   }
10491   reAdjustPreg(AOP(result));
10492   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10493   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10494
10495  release:
10496 #endif
10497
10498   pic16_freeAsmop(left,NULL,ic,TRUE);
10499   pic16_freeAsmop(result,NULL,ic,TRUE);
10500   pic16_freeAsmop(right,NULL,ic,TRUE);
10501 }
10502 #endif
10503
10504 #if !(USE_GENERIC_SIGNED_SHIFT)
10505 #warning This implementation of genRightShift() is incomplete!
10506 /*-----------------------------------------------------------------*/
10507 /* genRightShift - generate code for right shifting                */
10508 /*-----------------------------------------------------------------*/
10509 static void genRightShift (iCode *ic)
10510 {
10511     operand *right, *left, *result;
10512     sym_link *letype ;
10513     int size, offset;
10514     char *l;
10515     symbol *tlbl, *tlbl1 ;
10516
10517     /* if signed then we do it the hard way preserve the
10518     sign bit moving it inwards */
10519     letype = getSpec(operandType(IC_LEFT(ic)));
10520     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10521
10522     if (!SPEC_USIGN(letype)) {
10523         genSignedRightShift (ic);
10524         return ;
10525     }
10526
10527     /* signed & unsigned types are treated the same : i.e. the
10528     signed is NOT propagated inwards : quoting from the
10529     ANSI - standard : "for E1 >> E2, is equivalent to division
10530     by 2**E2 if unsigned or if it has a non-negative value,
10531     otherwise the result is implementation defined ", MY definition
10532     is that the sign does not get propagated */
10533
10534     right = IC_RIGHT(ic);
10535     left  = IC_LEFT(ic);
10536     result = IC_RESULT(ic);
10537
10538     pic16_aopOp(right,ic,FALSE);
10539
10540     /* if the shift count is known then do it 
10541     as efficiently as possible */
10542     if (AOP_TYPE(right) == AOP_LIT) {
10543         genRightShiftLiteral (left,right,result,ic, 0);
10544         return ;
10545     }
10546
10547     /* shift count is unknown then we have to form 
10548     a loop get the loop count in B : Note: we take
10549     only the lower order byte since shifting
10550     more that 32 bits make no sense anyway, ( the
10551     largest size of an object can be only 32 bits ) */  
10552
10553     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10554     pic16_emitcode("inc","b");
10555     pic16_aopOp(left,ic,FALSE);
10556     pic16_aopOp(result,ic,FALSE);
10557
10558     /* now move the left to the result if they are not the
10559     same */
10560     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10561         AOP_SIZE(result) > 1) {
10562
10563         size = AOP_SIZE(result);
10564         offset=0;
10565         while (size--) {
10566             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10567             if (*l == '@' && IS_AOP_PREG(result)) {
10568
10569                 pic16_emitcode("mov","a,%s",l);
10570                 pic16_aopPut(AOP(result),"a",offset);
10571             } else
10572                 pic16_aopPut(AOP(result),l,offset);
10573             offset++;
10574         }
10575     }
10576
10577     tlbl = newiTempLabel(NULL);
10578     tlbl1= newiTempLabel(NULL);
10579     size = AOP_SIZE(result);
10580     offset = size - 1;
10581
10582     /* if it is only one byte then */
10583     if (size == 1) {
10584
10585       tlbl = newiTempLabel(NULL);
10586       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10587         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10588         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10589       }
10590
10591       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10592       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10593       pic16_emitpLabel(tlbl->key);
10594       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10595       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10596       emitSKPC;
10597       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10598
10599       goto release ;
10600     }
10601
10602     reAdjustPreg(AOP(result));
10603     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10604     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10605     CLRC;
10606     while (size--) {
10607         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10608         MOVA(l);
10609         pic16_emitcode("rrc","a");         
10610         pic16_aopPut(AOP(result),"a",offset--);
10611     }
10612     reAdjustPreg(AOP(result));
10613
10614     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10615     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10616
10617 release:
10618     pic16_freeAsmop(left,NULL,ic,TRUE);
10619     pic16_freeAsmop (right,NULL,ic,TRUE);
10620     pic16_freeAsmop(result,NULL,ic,TRUE);
10621 }
10622 #endif
10623
10624 #if (USE_GENERIC_SIGNED_SHIFT)
10625 /*-----------------------------------------------------------------*/
10626 /* genGenericShift - generates code for left or right shifting     */
10627 /*-----------------------------------------------------------------*/
10628 static void genGenericShift (iCode *ic, int isShiftLeft) {
10629   operand *left,*right, *result;
10630   int offset;
10631   int sign, signedCount;
10632   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10633   PIC_OPCODE pos_shift, neg_shift;
10634
10635   FENTRY;
10636
10637   right = IC_RIGHT(ic);
10638   left  = IC_LEFT(ic);
10639   result = IC_RESULT(ic);
10640
10641   pic16_aopOp(right,ic,FALSE);
10642   pic16_aopOp(left,ic,FALSE);
10643   pic16_aopOp(result,ic,TRUE);
10644
10645   sign = !SPEC_USIGN(operandType (left));
10646   signedCount = !SPEC_USIGN(operandType (right));
10647
10648   /* if the shift count is known then do it 
10649      as efficiently as possible */
10650   if (AOP_TYPE(right) == AOP_LIT) {
10651     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10652     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10653     // we should modify right->aopu.aop_lit here!
10654     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10655     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10656     if (isShiftLeft)
10657       pic16_genLeftShiftLiteral (left,right,result,ic);
10658     else
10659       genRightShiftLiteral (left,right,result,ic, sign);
10660
10661     goto release;
10662   } // if (right is literal)
10663
10664   /* shift count is unknown then we have to form a loop.
10665    * Note: we take only the lower order byte since shifting
10666    * more than 32 bits make no sense anyway, ( the
10667    * largest size of an object can be only 32 bits )
10668    * Note: we perform arithmetic shifts if the left operand is
10669    * signed and we do an (effective) right shift, i. e. we
10670    * shift in the sign bit from the left. */
10671    
10672   label_complete = newiTempLabel ( NULL );
10673   label_loop_pos = newiTempLabel ( NULL );
10674   label_loop_neg = NULL;
10675   label_negative = NULL;
10676   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10677   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10678
10679   if (signedCount) {
10680     // additional labels needed
10681     label_loop_neg = newiTempLabel ( NULL );
10682     label_negative = newiTempLabel ( NULL );
10683   } // if
10684
10685   // copy source to result -- this will effectively truncate the left operand to the size of result!
10686   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10687   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10688   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10689     pic16_mov2f (AOP(result),AOP(left), offset);
10690   } // for
10691
10692   // if result is longer than left, fill with zeros (or sign)
10693   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10694     if (sign && AOP_SIZE(left) > 0) {
10695       // shift signed operand -- fill with sign
10696       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10697       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10698       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10699       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10700         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10701       } // for
10702     } else {
10703       // shift unsigned operand -- fill result with zeros
10704       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10705         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10706       } // for
10707     }
10708   } // if (size mismatch)
10709
10710   pic16_mov2w (AOP(right), 0);
10711   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10712   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10713   
10714 #if 0
10715   // perform a shift by one (shift count is positive)
10716   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10717   // 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])
10718   pic16_emitpLabel (label_loop_pos->key);
10719   emitCLRC;
10720   if (sign && (pos_shift == POC_RRCF)) {
10721     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10722     emitSETC;
10723   } // if
10724   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10725   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10726   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10727 #else
10728   // perform a shift by one (shift count is positive)
10729   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10730   // 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])
10731   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10732   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10733   emitCLRC;
10734   pic16_emitpLabel (label_loop_pos->key);
10735   if (sign && (pos_shift == POC_RRCF)) {
10736     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10737     emitSETC;
10738   } // if
10739   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10740   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10741   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10742   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10743 #endif
10744
10745   if (signedCount) {
10746     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10747
10748     pic16_emitpLabel (label_negative->key);
10749     // perform a shift by -1 (shift count is negative)
10750     // 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)
10751     emitCLRC;
10752     pic16_emitpLabel (label_loop_neg->key);
10753     if (sign && (neg_shift == POC_RRCF)) {
10754       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10755       emitSETC;
10756     } // if
10757     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10758     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10759     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10760     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10761   } // if (signedCount)
10762
10763   pic16_emitpLabel (label_complete->key);
10764
10765 release:
10766   pic16_freeAsmop (right,NULL,ic,TRUE);
10767   pic16_freeAsmop(left,NULL,ic,TRUE);
10768   pic16_freeAsmop(result,NULL,ic,TRUE);
10769 }
10770
10771 static void genLeftShift (iCode *ic) {
10772   genGenericShift (ic, 1);
10773 }
10774
10775 static void genRightShift (iCode *ic) {
10776   genGenericShift (ic, 0);
10777 }
10778 #endif
10779
10780
10781 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10782 void pic16_loadFSR0(operand *op, int lit)
10783 {
10784   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10785     if (AOP_TYPE(op) == AOP_LIT) {
10786       /* handle 12 bit integers correctly */
10787       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10788       if ((val & 0x0fff) != val) {
10789         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10790                 val, (val & 0x0fff) );
10791         val &= 0x0fff;
10792       }
10793       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10794     } else {
10795       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10796     }
10797   } else {
10798     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10799     // set up FSR0 with address of result
10800     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10801     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10802   }
10803 }
10804
10805 /*----------------------------------------------------------------*/
10806 /* pic16_derefPtr - move one byte from the location ptr points to */
10807 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10808 /*                  to the location ptr points to (doWrite != 0)   */
10809 /*----------------------------------------------------------------*/
10810 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10811 {
10812   if (!IS_PTR(operandType(ptr)))
10813   {
10814     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10815     else pic16_mov2w (AOP(ptr), 0);
10816     return;
10817   }
10818
10819   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10820   /* We might determine pointer type right here: */
10821   p_type = DCL_TYPE(operandType(ptr));
10822
10823   switch (p_type) {
10824     case FPOINTER:
10825     case POINTER:
10826       if (!fsr0_setup || !*fsr0_setup)
10827       {
10828         pic16_loadFSR0( ptr, 0 );
10829         if (fsr0_setup) *fsr0_setup = 1;
10830       }
10831       if (doWrite)
10832         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10833       else
10834         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10835       break;
10836
10837     case GPOINTER:
10838       if (AOP(ptr)->aopu.aop_reg[2]) {
10839         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10840         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10841         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10842         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10843         pic16_mov2w(AOP(ptr), 2);
10844         pic16_callGenericPointerRW(doWrite, 1);
10845       } else {
10846         // data pointer (just 2 byte given)
10847         if (!fsr0_setup || !*fsr0_setup)
10848         {
10849           pic16_loadFSR0( ptr, 0 );
10850           if (fsr0_setup) *fsr0_setup = 1;
10851         }
10852         if (doWrite)
10853           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10854         else
10855           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10856       }
10857       break;
10858
10859     default:
10860       assert (0 && "invalid pointer type specified");
10861       break;
10862   }
10863 }
10864
10865 /*-----------------------------------------------------------------*/
10866 /* genUnpackBits - generates code for unpacking bits               */
10867 /*-----------------------------------------------------------------*/
10868 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10869 {    
10870   int shCnt ;
10871   sym_link *etype, *letype;
10872   int blen=0, bstr=0;
10873   int lbstr;
10874   int same;
10875   pCodeOp *op;
10876
10877   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10878   etype = getSpec(operandType(result));
10879   letype = getSpec(operandType(left));
10880
10881   //    if(IS_BITFIELD(etype)) {
10882   blen = SPEC_BLEN(etype);
10883   bstr = SPEC_BSTR(etype);
10884   //    }
10885
10886   lbstr = SPEC_BSTR( letype );
10887
10888   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10889       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10890
10891 #if 1
10892   if((blen == 1) && (bstr < 8)
10893       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10894     /* it is a single bit, so use the appropriate bit instructions */
10895     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10896
10897     same = pic16_sameRegs(AOP(left),AOP(result));
10898     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10899     pic16_emitpcode(POC_CLRF, op);
10900
10901     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10902       /* workaround to reduce the extra lfsr instruction */
10903       pic16_emitpcode(POC_BTFSC,
10904           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10905     } else {
10906       assert (PIC_IS_DATA_PTR (operandType(left)));
10907       pic16_loadFSR0 (left, 0);
10908       pic16_emitpcode(POC_BTFSC,
10909           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10910     }
10911
10912     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10913       /* unsigned bitfields result in either 0 or 1 */
10914       pic16_emitpcode(POC_INCF, op);
10915     } else {
10916       /* signed bitfields result in either 0 or -1 */
10917       pic16_emitpcode(POC_DECF, op);
10918     }
10919     if (same) {
10920       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10921     }
10922
10923     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10924     return;
10925   }
10926
10927 #endif
10928
10929   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10930     // access symbol directly
10931     pic16_mov2w (AOP(left), 0);
10932   } else {
10933     pic16_derefPtr (left, ptype, 0, NULL);
10934   }
10935
10936   /* if we have bitdisplacement then it fits   */
10937   /* into this byte completely or if length is */
10938   /* less than a byte                          */
10939   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10940
10941     /* shift right acc */
10942     AccRsh(shCnt, 0);
10943
10944     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10945           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10946
10947     /* VR -- normally I would use the following, but since we use the hack,
10948      * to avoid the masking from AccRsh, why not mask it right now? */
10949
10950     /*
10951        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10952      */
10953
10954     /* extend signed bitfields to 8 bits */
10955     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10956     {
10957       assert (blen + bstr > 0);
10958       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10959       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10960     }
10961
10962     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10963
10964     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10965     return ;
10966   }
10967
10968   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10969   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10970   exit(EXIT_FAILURE);
10971
10972   return ;
10973 }
10974
10975
10976 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10977 {
10978   int size, offset = 0, leoffset=0 ;
10979
10980         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10981         pic16_aopOp(result, ic, TRUE);
10982
10983         FENTRY;
10984
10985         size = AOP_SIZE(result);
10986 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10987
10988
10989 #if 1
10990         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10991                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10992                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10993                 goto release;
10994         }
10995 #endif
10996
10997         if(AOP(left)->aopu.pcop->type == PO_DIR)
10998                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10999
11000         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11001
11002         while (size--) {
11003                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11004                 
11005 //              pic16_DumpOp("(result)",result);
11006                 if(is_LitAOp(AOP(result))) {
11007                         pic16_mov2w(AOP(left), offset); // patch 8
11008                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11009                 } else {
11010                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11011                                 pic16_popGet(AOP(left), offset), //patch 8
11012                                 pic16_popGet(AOP(result), offset)));
11013                 }
11014
11015                 offset++;
11016                 leoffset++;
11017         }
11018
11019 release:
11020     pic16_freeAsmop(result,NULL,ic,TRUE);
11021 }
11022
11023
11024
11025 /*-----------------------------------------------------------------*/
11026 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11027 /*-----------------------------------------------------------------*/
11028 static void genNearPointerGet (operand *left, 
11029                                operand *result, 
11030                                iCode *ic)
11031 {
11032 //  asmop *aop = NULL;
11033   //regs *preg = NULL ;
11034   sym_link *rtype, *retype;
11035   sym_link *ltype, *letype;
11036
11037     FENTRY;
11038     
11039     rtype = operandType(result);
11040     retype= getSpec(rtype);
11041     ltype = operandType(left);
11042     letype= getSpec(ltype);
11043     
11044     pic16_aopOp(left,ic,FALSE);
11045
11046 //    pic16_DumpOp("(left)",left);
11047 //    pic16_DumpOp("(result)",result);
11048
11049     /* if left is rematerialisable and
11050      * result is not bit variable type and
11051      * the left is pointer to data space i.e
11052      * lower 128 bytes of space */
11053     
11054     if (AOP_TYPE(left) == AOP_PCODE
11055       && !IS_BITFIELD(retype)
11056       && DCL_TYPE(ltype) == POINTER) {
11057
11058         genDataPointerGet (left,result,ic);
11059         pic16_freeAsmop(left, NULL, ic, TRUE);
11060         return ;
11061     }
11062     
11063     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11064     pic16_aopOp (result,ic,TRUE);
11065     
11066     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11067
11068 #if 1
11069     if(IS_BITFIELD( retype )
11070       && (SPEC_BLEN(operandType(result))==1)
11071     ) {
11072       iCode *nextic;
11073       pCodeOp *jop;
11074       int bitstrt, bytestrt;
11075
11076         /* if this is bitfield of size 1, see if we are checking the value
11077          * of a single bit in an if-statement,
11078          * if yes, then don't generate usual code, but execute the
11079          * genIfx directly -- VR */
11080
11081         nextic = ic->next;
11082
11083         /* CHECK: if next iCode is IFX
11084          * and current result operand is nextic's conditional operand
11085          * and current result operand live ranges ends at nextic's key number
11086          */
11087         if((nextic->op == IFX)
11088           && (result == IC_COND(nextic))
11089           && (OP_LIVETO(result) == nextic->seq)
11090           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
11091           ) {
11092             /* everything is ok then */
11093             /* find a way to optimize the genIfx iCode */
11094
11095             bytestrt = SPEC_BSTR(operandType(result))/8;
11096             bitstrt = SPEC_BSTR(operandType(result))%8;
11097             
11098             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11099
11100             genIfxpCOpJump(nextic, jop);
11101             
11102             pic16_freeAsmop(left, NULL, ic, TRUE);
11103             pic16_freeAsmop(result, NULL, ic, TRUE);
11104             return;
11105         }
11106     }
11107 #endif
11108
11109     /* if bitfield then unpack the bits */
11110     if (IS_BITFIELD(letype)) 
11111       genUnpackBits (result, left, NULL, POINTER);
11112     else {
11113       /* we have can just get the values */
11114       int size = AOP_SIZE(result);
11115       int offset = 0;   
11116         
11117       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11118
11119       pic16_loadFSR0( left, 0 );
11120
11121       while(size--) {
11122         if(size) {
11123           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11124                 pic16_popGet(AOP(result), offset++)));
11125         } else {
11126           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11127                 pic16_popGet(AOP(result), offset++)));
11128         }
11129       }
11130     }
11131
11132 #if 0
11133     /* now some housekeeping stuff */
11134     if (aop) {
11135       /* we had to allocate for this iCode */
11136       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11137       pic16_freeAsmop(NULL,aop,ic,TRUE);
11138     } else { 
11139       /* we did not allocate which means left
11140        * already in a pointer register, then
11141        * if size > 0 && this could be used again
11142        * we have to point it back to where it 
11143        * belongs */
11144       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11145       if (AOP_SIZE(result) > 1
11146         && !OP_SYMBOL(left)->remat
11147         && ( OP_SYMBOL(left)->liveTo > ic->seq
11148             || ic->depth )) {
11149 //        int size = AOP_SIZE(result) - 1;
11150 //        while (size--)
11151 //          pic16_emitcode("dec","%s",rname);
11152         }
11153     }
11154 #endif
11155
11156     /* done */
11157     pic16_freeAsmop(left,NULL,ic,TRUE);
11158     pic16_freeAsmop(result,NULL,ic,TRUE);
11159 }
11160
11161 /*-----------------------------------------------------------------*/
11162 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11163 /*-----------------------------------------------------------------*/
11164 static void genPagedPointerGet (operand *left, 
11165                                operand *result, 
11166                                iCode *ic)
11167 {
11168     asmop *aop = NULL;
11169     regs *preg = NULL ;
11170     char *rname ;
11171     sym_link *rtype, *retype;    
11172
11173     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11174
11175     rtype = operandType(result);
11176     retype= getSpec(rtype);
11177     
11178     pic16_aopOp(left,ic,FALSE);
11179
11180   /* if the value is already in a pointer register
11181        then don't need anything more */
11182     if (!AOP_INPREG(AOP(left))) {
11183         /* otherwise get a free pointer register */
11184         aop = newAsmop(0);
11185         preg = getFreePtr(ic,&aop,FALSE);
11186         pic16_emitcode("mov","%s,%s",
11187                 preg->name,
11188                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11189         rname = preg->name ;
11190     } else
11191         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11192     
11193     pic16_freeAsmop(left,NULL,ic,TRUE);
11194     pic16_aopOp (result,ic,TRUE);
11195
11196     /* if bitfield then unpack the bits */
11197     if (IS_BITFIELD(retype)) 
11198         genUnpackBits (result,left,rname,PPOINTER);
11199     else {
11200         /* we have can just get the values */
11201         int size = AOP_SIZE(result);
11202         int offset = 0 ;        
11203         
11204         while (size--) {
11205             
11206             pic16_emitcode("movx","a,@%s",rname);
11207             pic16_aopPut(AOP(result),"a",offset);
11208             
11209             offset++ ;
11210             
11211             if (size)
11212                 pic16_emitcode("inc","%s",rname);
11213         }
11214     }
11215
11216     /* now some housekeeping stuff */
11217     if (aop) {
11218         /* we had to allocate for this iCode */
11219         pic16_freeAsmop(NULL,aop,ic,TRUE);
11220     } else { 
11221         /* we did not allocate which means left
11222            already in a pointer register, then
11223            if size > 0 && this could be used again
11224            we have to point it back to where it 
11225            belongs */
11226         if (AOP_SIZE(result) > 1 &&
11227             !OP_SYMBOL(left)->remat &&
11228             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11229               ic->depth )) {
11230             int size = AOP_SIZE(result) - 1;
11231             while (size--)
11232                 pic16_emitcode("dec","%s",rname);
11233         }
11234     }
11235
11236     /* done */
11237     pic16_freeAsmop(result,NULL,ic,TRUE);
11238     
11239         
11240 }
11241
11242 #if 0
11243 /* This code is not adjusted to PIC16 and fails utterly.
11244  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11245
11246 /*-----------------------------------------------------------------*/
11247 /* genFarPointerGet - gget value from far space                    */
11248 /*-----------------------------------------------------------------*/
11249 static void genFarPointerGet (operand *left,
11250                               operand *result, iCode *ic)
11251 {
11252     int size, offset ;
11253     sym_link *retype = getSpec(operandType(result));
11254
11255     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11256
11257     pic16_aopOp(left,ic,FALSE);
11258
11259     /* if the operand is already in dptr 
11260     then we do nothing else we move the value to dptr */
11261     if (AOP_TYPE(left) != AOP_STR) {
11262         /* if this is remateriazable */
11263         if (AOP_TYPE(left) == AOP_IMMD)
11264             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11265         else { /* we need to get it byte by byte */
11266             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11267             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11268             if (options.model == MODEL_FLAT24)
11269             {
11270                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11271             }
11272         }
11273     }
11274     /* so dptr know contains the address */
11275     pic16_freeAsmop(left,NULL,ic,TRUE);
11276     pic16_aopOp(result,ic,TRUE);
11277
11278     /* if bit then unpack */
11279     if (IS_BITFIELD(retype)) 
11280         genUnpackBits(result,left,"dptr",FPOINTER);
11281     else {
11282         size = AOP_SIZE(result);
11283         offset = 0 ;
11284
11285         while (size--) {
11286             pic16_emitcode("movx","a,@dptr");
11287             pic16_aopPut(AOP(result),"a",offset++);
11288             if (size)
11289                 pic16_emitcode("inc","dptr");
11290         }
11291     }
11292
11293     pic16_freeAsmop(result,NULL,ic,TRUE);
11294 }
11295 #endif
11296
11297 #if 0
11298 /*-----------------------------------------------------------------*/
11299 /* genCodePointerGet - get value from code space                  */
11300 /*-----------------------------------------------------------------*/
11301 static void genCodePointerGet (operand *left,
11302                                 operand *result, iCode *ic)
11303 {
11304     int size, offset ;
11305     sym_link *retype = getSpec(operandType(result));
11306
11307     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11308
11309     pic16_aopOp(left,ic,FALSE);
11310
11311     /* if the operand is already in dptr 
11312     then we do nothing else we move the value to dptr */
11313     if (AOP_TYPE(left) != AOP_STR) {
11314         /* if this is remateriazable */
11315         if (AOP_TYPE(left) == AOP_IMMD)
11316             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11317         else { /* we need to get it byte by byte */
11318             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11319             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11320             if (options.model == MODEL_FLAT24)
11321             {
11322                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11323             }
11324         }
11325     }
11326     /* so dptr know contains the address */
11327     pic16_freeAsmop(left,NULL,ic,TRUE);
11328     pic16_aopOp(result,ic,FALSE);
11329
11330     /* if bit then unpack */
11331     if (IS_BITFIELD(retype)) 
11332         genUnpackBits(result,left,"dptr",CPOINTER);
11333     else {
11334         size = AOP_SIZE(result);
11335         offset = 0 ;
11336
11337         while (size--) {
11338             pic16_emitcode("clr","a");
11339             pic16_emitcode("movc","a,@a+dptr");
11340             pic16_aopPut(AOP(result),"a",offset++);
11341             if (size)
11342                 pic16_emitcode("inc","dptr");
11343         }
11344     }
11345
11346     pic16_freeAsmop(result,NULL,ic,TRUE);
11347 }
11348 #endif
11349
11350 #if 0
11351 /*-----------------------------------------------------------------*/
11352 /* genGenPointerGet - gget value from generic pointer space        */
11353 /*-----------------------------------------------------------------*/
11354 static void genGenPointerGet (operand *left,
11355                               operand *result, iCode *ic)
11356 {
11357   int size, offset, lit;
11358   sym_link *retype = getSpec(operandType(result));
11359
11360         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11361         pic16_aopOp(left,ic,FALSE);
11362         pic16_aopOp(result,ic,FALSE);
11363         size = AOP_SIZE(result);
11364
11365         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11366
11367         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11368
11369                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11370                 // load FSR0 from immediate
11371                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11372
11373 //              pic16_loadFSR0( left );
11374
11375                 offset = 0;
11376                 while(size--) {
11377                         if(size) {
11378                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11379                         } else {
11380                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11381                         }
11382                         offset++;
11383                 }
11384                 goto release;
11385
11386         }
11387         else { /* we need to get it byte by byte */
11388                 // set up FSR0 with address from left
11389                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11390                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11391                 
11392                 offset = 0 ;
11393
11394                 while(size--) {
11395                         if(size) {
11396                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11397                         } else {
11398                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11399                         }
11400                         offset++;
11401                 }
11402                 goto release;
11403         }
11404
11405   /* if bit then unpack */
11406         if (IS_BITFIELD(retype)) 
11407                 genUnpackBits(result,left,"BAD",GPOINTER);
11408
11409         release:
11410         pic16_freeAsmop(left,NULL,ic,TRUE);
11411         pic16_freeAsmop(result,NULL,ic,TRUE);
11412
11413 }
11414 #endif
11415
11416
11417 /*-----------------------------------------------------------------*/
11418 /* genGenPointerGet - gget value from generic pointer space        */
11419 /*-----------------------------------------------------------------*/
11420 static void genGenPointerGet (operand *left,
11421                               operand *result, iCode *ic)
11422 {
11423   int size, offset, lit;
11424   sym_link *letype = getSpec(operandType(left));
11425
11426     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11427     pic16_aopOp(left,ic,FALSE);
11428     pic16_aopOp(result,ic,TRUE);
11429     size = AOP_SIZE(result);
11430
11431     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11432   
11433     /* if bit then unpack */
11434     if (IS_BITFIELD(letype)) {
11435       genUnpackBits(result,left,"BAD",GPOINTER);
11436       goto release;
11437     }
11438
11439     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11440
11441       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11442       // load FSR0 from immediate
11443       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11444
11445       werror(W_POSSBUG2, __FILE__, __LINE__);
11446
11447       offset = 0;
11448       while(size--) {
11449         if(size) {
11450           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11451         } else {
11452           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11453         }
11454         offset++;
11455       }
11456
11457       goto release;
11458
11459     } else { /* we need to get it byte by byte */
11460
11461       /* set up WREG:PRODL:FSR0L with address from left */
11462       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11463       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11464       pic16_mov2w(AOP(left), 2);
11465       pic16_callGenericPointerRW(0, size);
11466       
11467       assignResultValue(result, size, 1);
11468       
11469       goto release;
11470     }
11471
11472 release:
11473   pic16_freeAsmop(left,NULL,ic,TRUE);
11474   pic16_freeAsmop(result,NULL,ic,TRUE);
11475 }
11476
11477 /*-----------------------------------------------------------------*/
11478 /* genConstPointerGet - get value from const generic pointer space */
11479 /*-----------------------------------------------------------------*/
11480 static void genConstPointerGet (operand *left,
11481                                 operand *result, iCode *ic)
11482 {
11483   //sym_link *retype = getSpec(operandType(result));
11484   // symbol *albl = newiTempLabel(NULL);        // patch 15
11485   // symbol *blbl = newiTempLabel(NULL);        //
11486   // PIC_OPCODE poc;                            // patch 15
11487   int size;
11488   int offset = 0;
11489
11490   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11491   pic16_aopOp(left,ic,FALSE);
11492   pic16_aopOp(result,ic,TRUE);
11493   size = AOP_SIZE(result);
11494
11495   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11496
11497   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11498
11499   // set up table pointer
11500   if( (AOP_TYPE(left) == AOP_PCODE) 
11501       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11502           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11503     {
11504       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11505       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11506       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11507       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11508       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11509       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11510   } else {
11511     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11512     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11513     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11514   }
11515
11516   while(size--) {
11517     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11518     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11519     offset++;
11520   }
11521     
11522   pic16_freeAsmop(left,NULL,ic,TRUE);
11523   pic16_freeAsmop(result,NULL,ic,TRUE);
11524 }
11525
11526
11527 /*-----------------------------------------------------------------*/
11528 /* genPointerGet - generate code for pointer get                   */
11529 /*-----------------------------------------------------------------*/
11530 static void genPointerGet (iCode *ic)
11531 {
11532   operand *left, *result ;
11533   sym_link *type, *etype;
11534   int p_type;
11535
11536     FENTRY;
11537     
11538     left = IC_LEFT(ic);
11539     result = IC_RESULT(ic) ;
11540
11541     /* depending on the type of pointer we need to
11542     move it to the correct pointer register */
11543     type = operandType(left);
11544     etype = getSpec(type);
11545
11546 #if 0
11547     if (IS_PTR_CONST(type))
11548 #else
11549     if (IS_CODEPTR(type))
11550 #endif
11551       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11552
11553     /* if left is of type of pointer then it is simple */
11554     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11555       p_type = DCL_TYPE(type);
11556     else {
11557       /* we have to go by the storage class */
11558       p_type = PTR_TYPE(SPEC_OCLS(etype));
11559
11560       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11561
11562       if (SPEC_OCLS(etype)->codesp ) {
11563         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11564         //p_type = CPOINTER ;   
11565       } else
11566       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11567         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11568         /*p_type = FPOINTER ;*/ 
11569       } else
11570       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11571         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11572         /* p_type = PPOINTER; */
11573       } else
11574       if (SPEC_OCLS(etype) == idata ) {
11575         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11576         /* p_type = IPOINTER; */
11577       } else {
11578         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11579         /* p_type = POINTER ; */
11580       }
11581     }
11582
11583     /* now that we have the pointer type we assign
11584     the pointer values */
11585     switch (p_type) {
11586       case POINTER:     
11587       case FPOINTER:
11588       case IPOINTER:
11589         genNearPointerGet (left,result,ic);
11590         break;
11591
11592       case PPOINTER:
11593         genPagedPointerGet(left,result,ic);
11594         break;
11595
11596 #if 0
11597       /* PICs do not support FAR pointers... */
11598       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11599       case FPOINTER:
11600         genFarPointerGet (left,result,ic);
11601         break;
11602 #endif
11603
11604       case CPOINTER:
11605         genConstPointerGet (left,result,ic);
11606         //pic16_emitcodePointerGet (left,result,ic);
11607         break;
11608
11609       case GPOINTER:
11610 #if 0
11611       if (IS_PTR_CONST(type))
11612         genConstPointerGet (left,result,ic);
11613       else
11614 #endif
11615         genGenPointerGet (left,result,ic);
11616       break;
11617
11618     default:
11619       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11620               "genPointerGet: illegal pointer type");
11621     
11622     }
11623 }
11624
11625 /*-----------------------------------------------------------------*/
11626 /* genPackBits - generates code for packed bit storage             */
11627 /*-----------------------------------------------------------------*/
11628 static void genPackBits (sym_link    *etype , operand *result,
11629                          operand *right ,
11630                          char *rname, int p_type)
11631 {
11632   int shCnt = 0 ;
11633   int offset = 0  ;
11634   int rLen = 0 ;
11635   int blen, bstr ;   
11636   int shifted_and_masked = 0;
11637   unsigned long lit = (unsigned long)-1;
11638   sym_link *retype;
11639
11640   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11641   blen = SPEC_BLEN(etype);
11642   bstr = SPEC_BSTR(etype);
11643
11644   retype = getSpec(operandType(right));
11645
11646   if(AOP_TYPE(right) == AOP_LIT) {
11647     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11648     
11649     if((blen == 1) && (bstr < 8)) {
11650       /* it is a single bit, so use the appropriate bit instructions */
11651
11652       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11653
11654       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11655         /* workaround to reduce the extra lfsr instruction */
11656         if(lit) {
11657           pic16_emitpcode(POC_BSF,
11658               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11659         } else {
11660           pic16_emitpcode(POC_BCF,
11661               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11662         }
11663       } else {
11664         if (PIC_IS_DATA_PTR(operandType(result))) {
11665           pic16_loadFSR0(result, 0);
11666           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11667               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11668         } else {
11669           /* get old value */
11670           pic16_derefPtr (result, p_type, 0, NULL);
11671           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11672               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11673           /* write back new value */
11674           pic16_derefPtr (result, p_type, 1, NULL);
11675         }
11676       }
11677
11678       return;
11679     }
11680     /* IORLW below is more efficient */
11681     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11682     lit = (lit & ((1UL << blen) - 1)) << bstr;
11683     shifted_and_masked = 1;
11684     offset++;
11685   } else
11686     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11687         && IS_BITFIELD(retype) 
11688         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11689         && (blen == 1)) {
11690       int rblen, rbstr;
11691
11692       rblen = SPEC_BLEN( retype );
11693       rbstr = SPEC_BSTR( retype );
11694
11695       if(IS_BITFIELD(etype)) {
11696         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11697         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11698       } else {
11699         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11700       }
11701
11702       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11703
11704       if(IS_BITFIELD(etype)) {
11705         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11706       } else {
11707         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11708       }
11709
11710       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11711
11712       return;
11713     } else {
11714       /* move right to W */
11715       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11716     }
11717
11718   /* if the bit length is less than or   */
11719   /* it exactly fits a byte then         */
11720   if((shCnt=SPEC_BSTR(etype))
11721       || SPEC_BLEN(etype) <= 8 )  {
11722     int fsr0_setup = 0;
11723
11724     if (blen != 8 || (bstr % 8) != 0) {
11725       // we need to combine the value with the old value
11726       if(!shifted_and_masked)
11727       {
11728         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11729
11730         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11731             SPEC_BSTR(etype), SPEC_BLEN(etype));
11732
11733         /* shift left acc, do NOT mask the result again */
11734         AccLsh(shCnt, 0);
11735
11736         /* using PRODH as a temporary register here */
11737         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11738       }
11739
11740       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11741         || IS_DIRECT(result)) {
11742         /* access symbol directly */
11743         pic16_mov2w (AOP(result), 0);
11744       } else {
11745         /* get old value */
11746         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11747       }
11748 #if 1
11749       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11750             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11751                             (unsigned char)(0xff >> (8-bstr))) ));
11752       if (!shifted_and_masked) {
11753         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11754       } else {
11755         /* We have the shifted and masked (literal) right value in `lit' */
11756         if (lit != 0)
11757           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11758       }
11759     } else { // if (blen == 8 && (bstr % 8) == 0)
11760         if (shifted_and_masked) {
11761             // move right (literal) to WREG (only case where right is not yet in WREG)
11762             pic16_mov2w(AOP(right), (bstr / 8));
11763         }
11764     }
11765
11766     /* write new value back */
11767     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11768         || IS_DIRECT(result)) {
11769       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11770     } else {
11771       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11772     }
11773 #endif
11774
11775     return;
11776   }
11777
11778
11779 #if 0
11780   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11781   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11782   exit(EXIT_FAILURE);
11783 #endif
11784
11785
11786   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11787   rLen = SPEC_BLEN(etype)-8;
11788
11789   /* now generate for lengths greater than one byte */
11790   while (1) {
11791     rLen -= 8 ;
11792     if (rLen <= 0 ) {
11793       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11794       break ;
11795     }
11796
11797     switch (p_type) {
11798       case POINTER:
11799         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11800         break;
11801
11802         /*
11803            case FPOINTER:
11804            MOVA(l);
11805            pic16_emitcode("movx","@dptr,a");
11806            break;
11807
11808            case GPOINTER:
11809            MOVA(l);
11810            DEBUGpic16_emitcode(";lcall","__gptrput");
11811            break;  
11812          */
11813       default:
11814         assert(0);
11815     }   
11816
11817
11818     pic16_mov2w(AOP(right), offset++);
11819   }
11820
11821   /* last last was not complete */
11822   if (rLen)   {
11823     /* save the byte & read byte */
11824     switch (p_type) {
11825       case POINTER:
11826         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11827         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11828         break;
11829
11830         /*
11831            case FPOINTER:
11832            pic16_emitcode ("mov","b,a");
11833            pic16_emitcode("movx","a,@dptr");
11834            break;
11835
11836            case GPOINTER:
11837            pic16_emitcode ("push","b");
11838            pic16_emitcode ("push","acc");
11839            pic16_emitcode ("lcall","__gptrget");
11840            pic16_emitcode ("pop","b");
11841            break;
11842          */
11843       default:
11844         assert(0);
11845     }
11846     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11847     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11848     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11849     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11850     //        pic16_emitcode ("orl","a,b");
11851   }
11852
11853   //    if (p_type == GPOINTER)
11854   //        pic16_emitcode("pop","b");
11855
11856   switch (p_type) {
11857
11858     case POINTER:
11859       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11860       //        pic16_emitcode("mov","@%s,a",rname);
11861       break;
11862       /*
11863          case FPOINTER:
11864          pic16_emitcode("movx","@dptr,a");
11865          break;
11866
11867          case GPOINTER:
11868          DEBUGpic16_emitcode(";lcall","__gptrput");
11869          break;                 
11870        */
11871     default:
11872       assert(0);
11873   }
11874
11875   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11876 }
11877
11878 /*-----------------------------------------------------------------*/
11879 /* genDataPointerSet - remat pointer to data space                 */
11880 /*-----------------------------------------------------------------*/
11881 static void genDataPointerSet(operand *right,
11882                               operand *result,
11883                               iCode *ic)
11884 {
11885   int size, offset = 0, resoffset=0 ;
11886
11887     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11888     pic16_aopOp(right,ic,FALSE);
11889
11890     size = AOP_SIZE(right);
11891
11892 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11893
11894 #if 0
11895     if ( AOP_TYPE(result) == AOP_PCODE) {
11896       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11897               AOP(result)->aopu.pcop->name,
11898                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11899               PCOR(AOP(result)->aopu.pcop)->instance:
11900               PCOI(AOP(result)->aopu.pcop)->offset);
11901     }
11902 #endif
11903
11904     if(AOP(result)->aopu.pcop->type == PO_DIR)
11905       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11906
11907     while (size--) {
11908       if (AOP_TYPE(right) == AOP_LIT) {
11909         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11910         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11911       } else {
11912         pic16_mov2w(AOP(right), offset);
11913         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11914       }
11915       offset++;
11916       resoffset++;
11917     }
11918
11919     pic16_freeAsmop(right,NULL,ic,TRUE);
11920 }
11921
11922
11923
11924 /*-----------------------------------------------------------------*/
11925 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11926 /*-----------------------------------------------------------------*/
11927 static void genNearPointerSet (operand *right,
11928                                operand *result, 
11929                                iCode *ic)
11930 {
11931   asmop *aop = NULL;
11932   sym_link *retype;
11933   sym_link *ptype = operandType(result);
11934   sym_link *resetype;
11935     
11936     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11937     retype= getSpec(operandType(right));
11938     resetype = getSpec(operandType(result));
11939   
11940     pic16_aopOp(result,ic,FALSE);
11941     
11942     /* if the result is rematerializable &
11943      * in data space & not a bit variable */
11944         
11945     /* and result is not a bit variable */
11946     if (AOP_TYPE(result) == AOP_PCODE
11947 //      && AOP_TYPE(result) == AOP_IMMD
11948       && DCL_TYPE(ptype) == POINTER
11949       && !IS_BITFIELD(retype)
11950       && !IS_BITFIELD(resetype)) {
11951
11952         genDataPointerSet (right,result,ic);
11953         pic16_freeAsmop(result,NULL,ic,TRUE);
11954       return;
11955     }
11956
11957     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11958     pic16_aopOp(right,ic,FALSE);
11959     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11960
11961     /* if bitfield then unpack the bits */
11962     if (IS_BITFIELD(resetype)) {
11963       genPackBits (resetype, result, right, NULL, POINTER);
11964     } else {
11965       /* we have can just get the values */
11966       int size = AOP_SIZE(right);
11967       int offset = 0 ;    
11968
11969         pic16_loadFSR0(result, 0);
11970             
11971         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11972         while (size--) {
11973           if (AOP_TYPE(right) == AOP_LIT) {
11974             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11975             if (size) {
11976               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11977             } else {
11978               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11979             }
11980           } else { // no literal
11981             if(size) {
11982               pic16_emitpcode(POC_MOVFF,
11983                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11984                   pic16_popCopyReg(&pic16_pc_postinc0)));
11985             } else {
11986               pic16_emitpcode(POC_MOVFF,
11987                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11988                   pic16_popCopyReg(&pic16_pc_indf0)));
11989             }
11990           }
11991           
11992           offset++;
11993         }
11994     }
11995
11996     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11997     /* now some housekeeping stuff */
11998     if (aop) {
11999       /* we had to allocate for this iCode */
12000       pic16_freeAsmop(NULL,aop,ic,TRUE);
12001     } else { 
12002       /* we did not allocate which means left
12003        * already in a pointer register, then
12004        * if size > 0 && this could be used again
12005        * we have to point it back to where it 
12006        * belongs */
12007       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12008       if (AOP_SIZE(right) > 1
12009         && !OP_SYMBOL(result)->remat
12010         && ( OP_SYMBOL(result)->liveTo > ic->seq
12011         || ic->depth )) {
12012
12013           int size = AOP_SIZE(right) - 1;
12014
12015             while (size--)
12016               pic16_emitcode("decf","fsr0,f");
12017               //pic16_emitcode("dec","%s",rname);
12018       }
12019     }
12020
12021     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12022     /* done */
12023 //release:
12024     pic16_freeAsmop(right,NULL,ic,TRUE);
12025     pic16_freeAsmop(result,NULL,ic,TRUE);
12026 }
12027
12028 /*-----------------------------------------------------------------*/
12029 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12030 /*-----------------------------------------------------------------*/
12031 static void genPagedPointerSet (operand *right,
12032                                operand *result, 
12033                                iCode *ic)
12034 {
12035     asmop *aop = NULL;
12036     regs *preg = NULL ;
12037     char *rname , *l;
12038     sym_link *retype;
12039        
12040     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12041
12042     retype= getSpec(operandType(right));
12043     
12044     pic16_aopOp(result,ic,FALSE);
12045     
12046     /* if the value is already in a pointer register
12047        then don't need anything more */
12048     if (!AOP_INPREG(AOP(result))) {
12049         /* otherwise get a free pointer register */
12050         aop = newAsmop(0);
12051         preg = getFreePtr(ic,&aop,FALSE);
12052         pic16_emitcode("mov","%s,%s",
12053                 preg->name,
12054                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12055         rname = preg->name ;
12056     } else
12057         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12058     
12059     pic16_freeAsmop(result,NULL,ic,TRUE);
12060     pic16_aopOp (right,ic,FALSE);
12061
12062     /* if bitfield then unpack the bits */
12063     if (IS_BITFIELD(retype)) 
12064         genPackBits (retype,result,right,rname,PPOINTER);
12065     else {
12066         /* we have can just get the values */
12067         int size = AOP_SIZE(right);
12068         int offset = 0 ;        
12069         
12070         while (size--) {
12071             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12072             
12073             MOVA(l);
12074             pic16_emitcode("movx","@%s,a",rname);
12075
12076             if (size)
12077                 pic16_emitcode("inc","%s",rname);
12078
12079             offset++;
12080         }
12081     }
12082     
12083     /* now some housekeeping stuff */
12084     if (aop) {
12085         /* we had to allocate for this iCode */
12086         pic16_freeAsmop(NULL,aop,ic,TRUE);
12087     } else { 
12088         /* we did not allocate which means left
12089            already in a pointer register, then
12090            if size > 0 && this could be used again
12091            we have to point it back to where it 
12092            belongs */
12093         if (AOP_SIZE(right) > 1 &&
12094             !OP_SYMBOL(result)->remat &&
12095             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12096               ic->depth )) {
12097             int size = AOP_SIZE(right) - 1;
12098             while (size--)
12099                 pic16_emitcode("dec","%s",rname);
12100         }
12101     }
12102
12103     /* done */
12104     pic16_freeAsmop(right,NULL,ic,TRUE);
12105     
12106         
12107 }
12108
12109 #if 0
12110 /* This code is not adjusted to PIC16 and fails utterly...
12111  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12112
12113 /*-----------------------------------------------------------------*/
12114 /* genFarPointerSet - set value from far space                     */
12115 /*-----------------------------------------------------------------*/
12116 static void genFarPointerSet (operand *right,
12117                               operand *result, iCode *ic)
12118 {
12119     int size, offset ;
12120     sym_link *retype = getSpec(operandType(right));
12121
12122     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12123     pic16_aopOp(result,ic,FALSE);
12124
12125     /* if the operand is already in dptr 
12126     then we do nothing else we move the value to dptr */
12127     if (AOP_TYPE(result) != AOP_STR) {
12128         /* if this is remateriazable */
12129         if (AOP_TYPE(result) == AOP_IMMD)
12130             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12131         else { /* we need to get it byte by byte */
12132             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12133             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12134             if (options.model == MODEL_FLAT24)
12135             {
12136                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12137             }
12138         }
12139     }
12140     /* so dptr know contains the address */
12141     pic16_freeAsmop(result,NULL,ic,TRUE);
12142     pic16_aopOp(right,ic,FALSE);
12143
12144     /* if bit then unpack */
12145     if (IS_BITFIELD(retype)) 
12146         genPackBits(retype,result,right,"dptr",FPOINTER);
12147     else {
12148         size = AOP_SIZE(right);
12149         offset = 0 ;
12150
12151         while (size--) {
12152             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12153             MOVA(l);
12154             pic16_emitcode("movx","@dptr,a");
12155             if (size)
12156                 pic16_emitcode("inc","dptr");
12157         }
12158     }
12159
12160     pic16_freeAsmop(right,NULL,ic,TRUE);
12161 }
12162 #endif
12163
12164 /*-----------------------------------------------------------------*/
12165 /* genGenPointerSet - set value from generic pointer space         */
12166 /*-----------------------------------------------------------------*/
12167 #if 0
12168 static void genGenPointerSet (operand *right,
12169                               operand *result, iCode *ic)
12170 {
12171         int i, size, offset, lit;
12172         sym_link *retype = getSpec(operandType(right));
12173
12174         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12175
12176         pic16_aopOp(result,ic,FALSE);
12177         pic16_aopOp(right,ic,FALSE);
12178         size = AOP_SIZE(right);
12179         offset = 0;
12180
12181         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12182
12183         /* if the operand is already in dptr 
12184                 then we do nothing else we move the value to dptr */
12185         if (AOP_TYPE(result) != AOP_STR) {
12186                 /* if this is remateriazable */
12187                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12188                 // WARNING: anythig until "else" is untested!
12189                 if (AOP_TYPE(result) == AOP_IMMD) {
12190                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12191                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12192                         // load FSR0 from immediate
12193                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12194                         offset = 0;
12195                         while(size--) {
12196                                 if(size) {
12197                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12198                                 } else {
12199                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12200                                 }
12201                                 offset++;
12202                         }
12203                         goto release;
12204                 }
12205                 else { /* we need to get it byte by byte */
12206                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12207                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12208
12209                         // set up FSR0 with address of result
12210                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12211                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12212
12213                         /* hack hack! see if this the FSR. If so don't load W */
12214                         if(AOP_TYPE(right) != AOP_ACC) {
12215
12216                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12217
12218                                 if(AOP_TYPE(right) == AOP_LIT)
12219                                 {
12220                                         // copy literal
12221                                         // note: pic16_popGet handles sign extension
12222                                         for(i=0;i<size;i++) {
12223                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12224                                                 if(i < size-1)
12225                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12226                                                 else
12227                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12228                                         }
12229                                 } else {
12230                                         // copy regs
12231
12232                                         for(i=0;i<size;i++) {
12233                                                 if(i < size-1)
12234                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12235                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12236                                                 else
12237                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12238                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12239                                         }
12240                                 }
12241                                 goto release;
12242                         } 
12243                         // right = ACC
12244                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12245                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12246                         goto release;
12247         } // if (AOP_TYPE(result) != AOP_IMMD)
12248
12249         } // if (AOP_TYPE(result) != AOP_STR)
12250         /* so dptr know contains the address */
12251
12252
12253         /* if bit then unpack */
12254         if (IS_BITFIELD(retype)) 
12255                 genPackBits(retype,result,right,"dptr",GPOINTER);
12256         else {
12257                 size = AOP_SIZE(right);
12258                 offset = 0 ;
12259
12260                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12261
12262                 // set up FSR0 with address of result
12263                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12264                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12265         
12266                 while (size--) {
12267                         if (AOP_TYPE(right) == AOP_LIT) {
12268                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12269                                 if (size) {
12270                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12271                                 } else {
12272                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12273                                 }
12274                         } else { // no literal
12275                                 if(size) {
12276                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12277                                 } else {
12278                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12279                                 }
12280                         }
12281                         offset++;
12282                 }
12283         }
12284
12285         release:
12286         pic16_freeAsmop(right,NULL,ic,TRUE);
12287         pic16_freeAsmop(result,NULL,ic,TRUE);
12288 }
12289 #endif
12290
12291 static void genGenPointerSet (operand *right,
12292                               operand *result, iCode *ic)
12293 {
12294   int size;
12295   sym_link *retype = getSpec(operandType(result));
12296
12297     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12298
12299     pic16_aopOp(result,ic,FALSE);
12300     pic16_aopOp(right,ic,FALSE);
12301     size = AOP_SIZE(right);
12302
12303     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12304
12305
12306     /* if bit then unpack */
12307     if (IS_BITFIELD(retype)) {
12308 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12309       genPackBits(retype,result,right,"dptr",GPOINTER);
12310       goto release;
12311     }
12312
12313     size = AOP_SIZE(right);
12314
12315     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12316
12317
12318     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12319
12320     /* value of right+0 is placed on stack, which will be retrieved
12321      * by the support function thus restoring the stack. The important
12322      * thing is that there is no need to manually restore stack pointer
12323      * here */
12324     pushaop(AOP(right), 0);
12325 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12326     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12327     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12328     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12329     
12330     /* load address to write to in WREG:FSR0H:FSR0L */
12331     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12332                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12333     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12334                                 pic16_popCopyReg(&pic16_pc_prodl)));
12335     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12336     
12337     pic16_callGenericPointerRW(1, size);
12338
12339 release:
12340     pic16_freeAsmop(right,NULL,ic,TRUE);
12341     pic16_freeAsmop(result,NULL,ic,TRUE);
12342 }
12343
12344 /*-----------------------------------------------------------------*/
12345 /* genPointerSet - stores the value into a pointer location        */
12346 /*-----------------------------------------------------------------*/
12347 static void genPointerSet (iCode *ic)
12348 {    
12349   operand *right, *result ;
12350   sym_link *type, *etype;
12351   int p_type;
12352
12353     FENTRY;
12354
12355     right = IC_RIGHT(ic);
12356     result = IC_RESULT(ic) ;
12357
12358     /* depending on the type of pointer we need to
12359     move it to the correct pointer register */
12360     type = operandType(result);
12361     etype = getSpec(type);
12362     
12363     /* if left is of type of pointer then it is simple */
12364     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12365         p_type = DCL_TYPE(type);
12366     }
12367     else {
12368         /* we have to go by the storage class */
12369         p_type = PTR_TYPE(SPEC_OCLS(etype));
12370
12371 /*      if (SPEC_OCLS(etype)->codesp ) { */
12372 /*          p_type = CPOINTER ;  */
12373 /*      } */
12374 /*      else */
12375 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12376 /*              p_type = FPOINTER ; */
12377 /*          else */
12378 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12379 /*                  p_type = PPOINTER ; */
12380 /*              else */
12381 /*                  if (SPEC_OCLS(etype) == idata ) */
12382 /*                      p_type = IPOINTER ; */
12383 /*                  else */
12384 /*                      p_type = POINTER ; */
12385     }
12386
12387     /* now that we have the pointer type we assign
12388     the pointer values */
12389     switch (p_type) {
12390       case POINTER:
12391       case FPOINTER:
12392       case IPOINTER:
12393         genNearPointerSet (right,result,ic);
12394         break;
12395
12396       case PPOINTER:
12397         genPagedPointerSet (right,result,ic);
12398         break;
12399
12400 #if 0
12401       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12402       case FPOINTER:
12403         genFarPointerSet (right,result,ic);
12404         break;
12405 #endif
12406         
12407       case GPOINTER:
12408         genGenPointerSet (right,result,ic);
12409         break;
12410
12411       default:
12412         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12413           "genPointerSet: illegal pointer type");
12414     }
12415 }
12416
12417 /*-----------------------------------------------------------------*/
12418 /* genIfx - generate code for Ifx statement                        */
12419 /*-----------------------------------------------------------------*/
12420 static void genIfx (iCode *ic, iCode *popIc)
12421 {
12422   operand *cond = IC_COND(ic);
12423   int isbit =0;
12424
12425     FENTRY;
12426
12427     pic16_aopOp(cond,ic,FALSE);
12428
12429     /* get the value into acc */
12430     if (AOP_TYPE(cond) != AOP_CRY)
12431       pic16_toBoolean(cond);
12432     else
12433       isbit = 1;
12434     /* the result is now in the accumulator */
12435     pic16_freeAsmop(cond,NULL,ic,TRUE);
12436
12437     /* if there was something to be popped then do it */
12438     if (popIc)
12439       genIpop(popIc);
12440
12441     /* if the condition is  a bit variable */
12442     if (isbit && IS_ITEMP(cond) && 
12443         SPIL_LOC(cond)) {
12444       genIfxJump(ic,"c");
12445       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12446     } else {
12447       if (isbit && !IS_ITEMP(cond))
12448         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12449         else
12450         genIfxJump(ic,"a");
12451     }
12452     ic->generated = 1;
12453 }
12454
12455 /*-----------------------------------------------------------------*/
12456 /* genAddrOf - generates code for address of                       */
12457 /*-----------------------------------------------------------------*/
12458 static void genAddrOf (iCode *ic)
12459 {
12460   operand *result, *left;
12461   int size;
12462   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12463   pCodeOp *pcop0, *pcop1, *pcop2;
12464
12465     FENTRY;
12466
12467     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12468
12469     sym = OP_SYMBOL( IC_LEFT(ic) );
12470     
12471     if(sym->onStack) {
12472       /* get address of symbol on stack */
12473       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12474 #if 0
12475       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12476                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12477 #endif
12478
12479       // operands on stack are accessible via "FSR2 + index" with index
12480       // starting at 2 for arguments and growing from 0 downwards for
12481       // local variables (index == 0 is not assigned so we add one here)
12482       {
12483         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12484
12485           if (soffs <= 0) {
12486             assert (soffs < 0);
12487             soffs++;
12488           } // if
12489
12490           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12491           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12492           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12493           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12494           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12495           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12496           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12497       }
12498
12499       goto release;
12500     }
12501         
12502 //      if(pic16_debug_verbose) {
12503 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12504 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12505 //      }
12506         
12507     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12508     size = AOP_SIZE(IC_RESULT(ic));
12509
12510     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12511     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12512     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12513         
12514     if (size == 3) {
12515       pic16_emitpcode(POC_MOVLW, pcop0);
12516       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12517       pic16_emitpcode(POC_MOVLW, pcop1);
12518       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12519       pic16_emitpcode(POC_MOVLW, pcop2);
12520       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12521     } else
12522     if (size == 2) {
12523       pic16_emitpcode(POC_MOVLW, pcop0);
12524       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12525       pic16_emitpcode(POC_MOVLW, pcop1);
12526     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12527     } else {
12528       pic16_emitpcode(POC_MOVLW, pcop0);
12529       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12530     }
12531
12532     pic16_freeAsmop(left, NULL, ic, FALSE);
12533 release:
12534     pic16_freeAsmop(result,NULL,ic,TRUE);
12535 }
12536
12537
12538 #if 0
12539 /*-----------------------------------------------------------------*/
12540 /* genFarFarAssign - assignment when both are in far space         */
12541 /*-----------------------------------------------------------------*/
12542 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12543 {
12544     int size = AOP_SIZE(right);
12545     int offset = 0;
12546     char *l ;
12547     /* first push the right side on to the stack */
12548     while (size--) {
12549         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12550         MOVA(l);
12551         pic16_emitcode ("push","acc");
12552     }
12553     
12554     pic16_freeAsmop(right,NULL,ic,FALSE);
12555     /* now assign DPTR to result */
12556     pic16_aopOp(result,ic,FALSE);
12557     size = AOP_SIZE(result);
12558     while (size--) {
12559         pic16_emitcode ("pop","acc");
12560         pic16_aopPut(AOP(result),"a",--offset);
12561     }
12562     pic16_freeAsmop(result,NULL,ic,FALSE);
12563         
12564 }
12565 #endif
12566
12567 /*-----------------------------------------------------------------*/
12568 /* genAssign - generate code for assignment                        */
12569 /*-----------------------------------------------------------------*/
12570 static void genAssign (iCode *ic)
12571 {
12572   operand *result, *right;
12573   sym_link *restype, *rtype;
12574   int size, offset,know_W;
12575   unsigned long lit = 0L;
12576
12577     result = IC_RESULT(ic);
12578     right  = IC_RIGHT(ic) ;
12579
12580     FENTRY;
12581   
12582     /* if they are the same */
12583     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12584       return ;
12585
12586     /* reversed order operands are aopOp'ed so that result operand
12587      * is effective in case right is a stack symbol. This maneauver
12588      * allows to use the _G.resDirect flag later */
12589      pic16_aopOp(result,ic,TRUE);
12590     pic16_aopOp(right,ic,FALSE);
12591
12592     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12593
12594     /* if they are the same registers */
12595     if (pic16_sameRegs(AOP(right),AOP(result)))
12596       goto release;
12597
12598     /* if the result is a bit */
12599     if (AOP_TYPE(result) == AOP_CRY) {
12600       /* if the right size is a literal then
12601          we know what the value is */
12602       if (AOP_TYPE(right) == AOP_LIT) {
12603           
12604         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12605             pic16_popGet(AOP(result),0));
12606
12607         if (((int) operandLitValue(right))) 
12608           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12609               AOP(result)->aopu.aop_dir,
12610               AOP(result)->aopu.aop_dir);
12611         else
12612           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12613               AOP(result)->aopu.aop_dir,
12614               AOP(result)->aopu.aop_dir);
12615         
12616         goto release;
12617       }
12618
12619       /* the right is also a bit variable */
12620       if (AOP_TYPE(right) == AOP_CRY) {
12621         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12622         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12623         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12624
12625         goto release ;
12626       }
12627
12628       /* we need to or */
12629       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12630       pic16_toBoolean(right);
12631       emitSKPZ;
12632       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12633       //pic16_aopPut(AOP(result),"a",0);
12634       goto release ;
12635     }
12636
12637     /* bit variables done */
12638     /* general case */
12639     size = AOP_SIZE(result);
12640     offset = 0 ;
12641
12642   /* bit variables done */
12643   /* general case */
12644   size = AOP_SIZE(result);
12645   restype = operandType(result);
12646   rtype = operandType(right);
12647   offset = 0 ;
12648
12649   if(AOP_TYPE(right) == AOP_LIT) {
12650     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12651     {
12652       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12653
12654       /* patch tag for literals that are cast to pointers */
12655       if (IS_CODEPTR(restype)) {
12656         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12657         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12658       } else {
12659         if (IS_GENPTR(restype))
12660         {
12661           if (IS_CODEPTR(rtype)) {
12662             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12663             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12664           } else if (PIC_IS_DATA_PTR(rtype)) {
12665             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12666             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12667           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12668             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12669           } else if (IS_PTR(rtype)) {
12670             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12671             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12672           }
12673         }
12674       }
12675     } else {
12676       union {
12677         unsigned long lit_int;
12678         float lit_float;
12679       } info;
12680
12681
12682       if(IS_FIXED16X16(operandType(right))) {
12683         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12684       } else {
12685         /* take care if literal is a float */
12686         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12687         lit = info.lit_int;
12688       }
12689     }
12690   }
12691
12692 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12693 //                      sizeof(unsigned long int), sizeof(float));
12694
12695
12696     if (AOP_TYPE(right) == AOP_REG) {
12697       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12698       while (size--) {
12699         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12700       } // while
12701       goto release;
12702     }
12703
12704     /* when do we have to read the program memory?
12705      * - if right itself is a symbol in code space
12706      *   (we don't care what it points to if it's a pointer)
12707      * - AND right is not a function (we would want its address)
12708      */
12709     if(AOP_TYPE(right) != AOP_LIT
12710       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12711       && !IS_FUNC(OP_SYM_TYPE(right))
12712       && !IS_ITEMP(right)) {
12713
12714       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12715       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12716       
12717       // set up table pointer
12718       if(is_LitOp(right)) {
12719 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12720         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12721         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12722         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12723         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12724         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12725         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12726       } else {
12727 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12728         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12729             pic16_popCopyReg(&pic16_pc_tblptrl)));
12730         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12731             pic16_popCopyReg(&pic16_pc_tblptrh)));
12732         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12733             pic16_popCopyReg(&pic16_pc_tblptru)));
12734       }
12735
12736       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12737       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12738       while(size--) {
12739         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12740         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12741             pic16_popGet(AOP(result),offset)));
12742         offset++;
12743       }
12744
12745       /* FIXME: for pointers we need to extend differently (according
12746        * to pointer type DATA/CODE/EEPROM/... :*/
12747       size = getSize(OP_SYM_TYPE(right));
12748       if(AOP_SIZE(result) > size) {
12749         size = AOP_SIZE(result) - size;
12750         while(size--) {
12751           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12752           offset++;
12753         }
12754       }
12755       goto release;
12756     }
12757
12758 #if 0
12759     /* VR - What is this?! */
12760     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12761       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12762       
12763       if(aopIdx(AOP(result),0) == 4) {
12764         /* this is a workaround to save value of right into wreg too,
12765          * value of wreg is going to be used later */
12766         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12767         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12768         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12769         goto release;
12770       } else
12771 //      assert(0);
12772       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12773     }
12774 #endif
12775
12776     size = AOP_SIZE(right);
12777     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12778     know_W=-1;
12779     while (size--) {
12780       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12781       if(AOP_TYPE(right) == AOP_LIT) {
12782         if(lit&0xff) {
12783           if(know_W != (lit&0xff))
12784             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12785           know_W = lit&0xff;
12786           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12787         } else
12788           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12789
12790         lit >>= 8;
12791
12792       } else if (AOP_TYPE(right) == AOP_CRY) {
12793         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12794         if(offset == 0) {
12795           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12796           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12797           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12798         }
12799       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12800         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12801         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12802       } else {
12803         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12804
12805         if(!_G.resDirect) {                                             /* use this aopForSym feature */
12806           if(AOP_TYPE(result) == AOP_ACC) {
12807             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12808           } else
12809             if(AOP_TYPE(right) == AOP_ACC) {
12810               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12811             } else {
12812               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12813             }
12814         }
12815       }
12816
12817       offset++;
12818     }
12819     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12820   
12821 release:
12822   pic16_freeAsmop (right,NULL,ic,FALSE);
12823   pic16_freeAsmop (result,NULL,ic,TRUE);
12824
12825
12826 /*-----------------------------------------------------------------*/
12827 /* genJumpTab - generates code for jump table                       */
12828 /*-----------------------------------------------------------------*/
12829 static void genJumpTab (iCode *ic)
12830 {
12831   symbol *jtab;
12832   char *l;
12833   pCodeOp *jt_offs;
12834   pCodeOp *jt_offs_hi;
12835   pCodeOp *jt_label;
12836
12837     FENTRY;
12838
12839     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12840     /* get the condition into accumulator */
12841     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12842     MOVA(l);
12843     /* multiply by three */
12844     pic16_emitcode("add","a,acc");
12845     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12846
12847     jtab = newiTempLabel(NULL);
12848     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12849     pic16_emitcode("jmp","@a+dptr");
12850     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12851
12852 #if 0
12853     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12854     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12855     emitSKPNC;
12856     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12857     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12858     pic16_emitpLabel(jtab->key);
12859
12860 #else
12861
12862     jt_offs = pic16_popGetTempReg(0);
12863     jt_offs_hi = pic16_popGetTempReg(1);
12864     jt_label = pic16_popGetLabel (jtab->key);
12865     //fprintf (stderr, "Creating jump table...\n");
12866
12867     // calculate offset into jump table (idx * sizeof (GOTO))
12868     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12869     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12870     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12871     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12872     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12873     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12874     pic16_emitpcode(POC_MOVWF , jt_offs);
12875
12876     // prepare PCLATx (set to first entry in jump table)
12877     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12878     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12879     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12880     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12881     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12882
12883     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12884     pic16_emitpcode(POC_ADDWF , jt_offs);
12885     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12886     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12887     emitSKPNC;
12888     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12889
12890     // release temporaries and prepare jump into table (new PCL --> WREG)
12891     pic16_emitpcode(POC_MOVFW , jt_offs);
12892     pic16_popReleaseTempReg (jt_offs_hi, 1);
12893     pic16_popReleaseTempReg (jt_offs, 0);
12894
12895     // jump into the table
12896     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12897
12898     pic16_emitpLabelFORCE(jtab->key);
12899 #endif
12900
12901     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12902 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12903
12904     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12905     /* now generate the jump labels */
12906     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12907          jtab = setNextItem(IC_JTLABELS(ic))) {
12908 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12909         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12910         
12911     }
12912     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12913
12914 }
12915
12916 /*-----------------------------------------------------------------*/
12917 /* genMixedOperation - gen code for operators between mixed types  */
12918 /*-----------------------------------------------------------------*/
12919 /*
12920   TSD - Written for the PIC port - but this unfortunately is buggy.
12921   This routine is good in that it is able to efficiently promote 
12922   types to different (larger) sizes. Unfortunately, the temporary
12923   variables that are optimized out by this routine are sometimes
12924   used in other places. So until I know how to really parse the 
12925   iCode tree, I'm going to not be using this routine :(.
12926 */
12927 static int genMixedOperation (iCode *ic)
12928 {
12929 #if 0
12930   operand *result = IC_RESULT(ic);
12931   sym_link *ctype = operandType(IC_LEFT(ic));
12932   operand *right = IC_RIGHT(ic);
12933   int ret = 0;
12934   int big,small;
12935   int offset;
12936
12937   iCode *nextic;
12938   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12939
12940   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12941
12942   nextic = ic->next;
12943   if(!nextic)
12944     return 0;
12945
12946   nextright = IC_RIGHT(nextic);
12947   nextleft  = IC_LEFT(nextic);
12948   nextresult = IC_RESULT(nextic);
12949
12950   pic16_aopOp(right,ic,FALSE);
12951   pic16_aopOp(result,ic,FALSE);
12952   pic16_aopOp(nextright,  nextic, FALSE);
12953   pic16_aopOp(nextleft,   nextic, FALSE);
12954   pic16_aopOp(nextresult, nextic, FALSE);
12955
12956   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12957
12958     operand *t = right;
12959     right = nextright;
12960     nextright = t; 
12961
12962     pic16_emitcode(";remove right +","");
12963
12964   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12965 /*
12966     operand *t = right;
12967     right = nextleft;
12968     nextleft = t; 
12969 */
12970     pic16_emitcode(";remove left +","");
12971   } else
12972     return 0;
12973
12974   big = AOP_SIZE(nextleft);
12975   small = AOP_SIZE(nextright);
12976
12977   switch(nextic->op) {
12978
12979   case '+':
12980     pic16_emitcode(";optimize a +","");
12981     /* if unsigned or not an integral type */
12982     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12983       pic16_emitcode(";add a bit to something","");
12984     } else {
12985
12986       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12987
12988       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12989         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12990         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12991       } else
12992         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12993
12994       offset = 0;
12995       while(--big) {
12996
12997         offset++;
12998
12999         if(--small) {
13000           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13001             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13002             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13003           }
13004
13005           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13006           emitSKPNC;
13007           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13008                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13009                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13010           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13011           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13012
13013         } else {
13014           pic16_emitcode("rlf","known_zero,w");
13015
13016           /*
13017             if right is signed
13018               btfsc  right,7
13019                addlw ff
13020           */
13021           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13022             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13023             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13024           } else {
13025             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13026           }
13027         }
13028       }
13029       ret = 1;
13030     }
13031   }
13032   ret = 1;
13033
13034 release:
13035   pic16_freeAsmop(right,NULL,ic,TRUE);
13036   pic16_freeAsmop(result,NULL,ic,TRUE);
13037   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13038   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13039   if(ret)
13040     nextic->generated = 1;
13041
13042   return ret;
13043 #else
13044   return 0;
13045 #endif
13046 }
13047 /*-----------------------------------------------------------------*/
13048 /* genCast - gen code for casting                                  */
13049 /*-----------------------------------------------------------------*/
13050 static void genCast (iCode *ic)
13051 {
13052   operand *result = IC_RESULT(ic);
13053   sym_link *ctype = operandType(IC_LEFT(ic));
13054   sym_link *rtype = operandType(IC_RIGHT(ic));
13055   sym_link *restype = operandType(IC_RESULT(ic));
13056   operand *right = IC_RIGHT(ic);
13057   int size, offset ;
13058
13059
13060     FENTRY;
13061
13062         /* if they are equivalent then do nothing */
13063 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13064 //              return ;
13065
13066         pic16_aopOp(result,ic,FALSE);
13067         pic16_aopOp(right,ic,FALSE) ;
13068
13069         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13070
13071
13072         /* if the result is a bit */
13073         if (AOP_TYPE(result) == AOP_CRY) {
13074         
13075                 /* if the right size is a literal then
13076                  * we know what the value is */
13077                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13078
13079                 if (AOP_TYPE(right) == AOP_LIT) {
13080                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13081                                 pic16_popGet(AOP(result),0));
13082
13083                         if (((int) operandLitValue(right))) 
13084                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13085                                         AOP(result)->aopu.aop_dir,
13086                                         AOP(result)->aopu.aop_dir);
13087                         else
13088                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13089                                         AOP(result)->aopu.aop_dir,
13090                                         AOP(result)->aopu.aop_dir);
13091                         goto release;
13092                 }
13093
13094                 /* the right is also a bit variable */
13095                 if (AOP_TYPE(right) == AOP_CRY) {
13096                         emitCLRC;
13097                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13098
13099                         pic16_emitcode("clrc","");
13100                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13101                                 AOP(right)->aopu.aop_dir,
13102                                 AOP(right)->aopu.aop_dir);
13103                         pic16_aopPut(AOP(result),"c",0);
13104                         goto release ;
13105                 }
13106
13107                 /* we need to or */
13108                 if (AOP_TYPE(right) == AOP_REG) {
13109                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13110                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13111                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13112                 }
13113                 pic16_toBoolean(right);
13114                 pic16_aopPut(AOP(result),"a",0);
13115                 goto release ;
13116         }
13117
13118         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13119           int offset = 1;
13120
13121                 size = AOP_SIZE(result);
13122
13123                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13124
13125                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13126                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13127                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13128
13129                 while (size--)
13130                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13131
13132                 goto release;
13133         }
13134
13135         if(IS_BITFIELD(getSpec(restype))
13136           && IS_BITFIELD(getSpec(rtype))) {
13137           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13138         }
13139         
13140         /* port from pic14 to cope with generic pointers */
13141         if (PIC_IS_TAGGED(restype))
13142         {
13143           operand *result = IC_RESULT(ic);
13144           //operand *left = IC_LEFT(ic);
13145           operand *right = IC_RIGHT(ic);
13146           int tag = 0xff;
13147
13148           /* copy common part */
13149           int max, size = AOP_SIZE(result);
13150           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13151           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13152
13153           max = size;
13154           while (size--)
13155           {
13156             pic16_mov2w (AOP(right), size);
13157             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13158           } // while
13159
13160           /* upcast into generic pointer type? */
13161           if (IS_GENPTR(restype)
13162               && !PIC_IS_TAGGED(rtype)
13163               && (AOP_SIZE(result) > max))
13164           {
13165             /* determine appropriate tag for right */
13166             if (PIC_IS_DATA_PTR(rtype))
13167               tag = GPTR_TAG_DATA;
13168             else if (IS_CODEPTR(rtype))
13169               tag = GPTR_TAG_CODE;
13170             else if (PIC_IS_DATA_PTR(ctype)) {
13171               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13172               tag = GPTR_TAG_DATA;
13173             } else if (IS_CODEPTR(ctype)) {
13174               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13175               tag = GPTR_TAG_CODE;
13176             } else if (IS_PTR(rtype)) {
13177               PERFORM_ONCE(weirdcast,
13178               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
13179               );
13180               tag = GPTR_TAG_DATA;
13181             } else {
13182               PERFORM_ONCE(weirdcast,
13183               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
13184               );
13185               tag = GPTR_TAG_DATA;
13186             }
13187
13188             assert (AOP_SIZE(result) == 3);
13189             /* zero-extend address... */
13190             for (size = max; size < AOP_SIZE(result)-1; size++)
13191               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13192             /* ...and add tag */
13193             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13194           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13195             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13196             for (size = max; size < AOP_SIZE(result)-1; size++)
13197               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13198             /* add __code tag */
13199             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13200           } else if (AOP_SIZE(result) > max) {
13201             /* extend non-pointers */
13202             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13203             pic16_addSign(result, max, 0);
13204           } // if
13205           goto release;
13206         }
13207
13208         /* if they are the same size : or less */
13209         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13210
13211                 /* if they are in the same place */
13212                 if (pic16_sameRegs(AOP(right),AOP(result)))
13213                         goto release;
13214
13215                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13216 #if 0
13217                 if (IS_PTR_CONST(rtype))
13218 #else
13219                 if (IS_CODEPTR(rtype))
13220 #endif
13221                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13222
13223 #if 0
13224                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13225 #else
13226                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13227 #endif
13228                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13229
13230 #if 0
13231                 if(AOP_TYPE(right) == AOP_IMMD) {
13232                   pCodeOp *pcop0, *pcop1, *pcop2;
13233                   symbol *sym = OP_SYMBOL( right );
13234
13235                         size = AOP_SIZE(result);
13236                         /* low */
13237                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13238                         /* high */
13239                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13240                         /* upper */
13241                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13242         
13243                         if (size == 3) {
13244                                 pic16_emitpcode(POC_MOVLW, pcop0);
13245                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13246                                 pic16_emitpcode(POC_MOVLW, pcop1);
13247                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13248                                 pic16_emitpcode(POC_MOVLW, pcop2);
13249                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13250                         } else
13251                         if (size == 2) {
13252                                 pic16_emitpcode(POC_MOVLW, pcop0);
13253                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13254                                 pic16_emitpcode(POC_MOVLW, pcop1);
13255                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13256                         } else {
13257                                 pic16_emitpcode(POC_MOVLW, pcop0);
13258                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13259                         }
13260                 } else
13261 #endif
13262                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13263                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13264                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13265
13266                         if(AOP_SIZE(result) < 2) {
13267                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13268                         } else {
13269                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13270                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13271                         }
13272                 } else {
13273                         /* if they in different places then copy */
13274                         size = AOP_SIZE(result);
13275                         offset = 0 ;
13276                         while (size--) {
13277                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13278                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13279                                 offset++;
13280                         }
13281                 }
13282                 goto release;
13283         }
13284
13285         /* if the result is of type pointer */
13286         if (IS_PTR(ctype)) {
13287           int p_type;
13288           sym_link *type = operandType(right);
13289           sym_link *etype = getSpec(type);
13290
13291                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13292
13293                 /* pointer to generic pointer */
13294                 if (IS_GENPTR(ctype)) {
13295                   char *l = zero;
13296             
13297                         if (IS_PTR(type)) 
13298                                 p_type = DCL_TYPE(type);
13299                         else {
13300                 /* we have to go by the storage class */
13301                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13302
13303 /*              if (SPEC_OCLS(etype)->codesp )  */
13304 /*                  p_type = CPOINTER ;  */
13305 /*              else */
13306 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13307 /*                      p_type = FPOINTER ; */
13308 /*                  else */
13309 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13310 /*                          p_type = PPOINTER; */
13311 /*                      else */
13312 /*                          if (SPEC_OCLS(etype) == idata ) */
13313 /*                              p_type = IPOINTER ; */
13314 /*                          else */
13315 /*                              p_type = POINTER ; */
13316             }
13317                 
13318             /* the first two bytes are known */
13319       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13320             size = GPTRSIZE - 1; 
13321             offset = 0 ;
13322             while (size--) {
13323               if(offset < AOP_SIZE(right)) {
13324                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13325                 pic16_mov2f(AOP(result), AOP(right), offset);
13326 /*
13327                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13328                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13329                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13330                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13331                 } else { 
13332                   
13333                   pic16_aopPut(AOP(result),
13334                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13335                          offset);
13336                 }
13337 */
13338               } else 
13339                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13340               offset++;
13341             }
13342             /* the last byte depending on type */
13343             switch (p_type) {
13344             case IPOINTER:
13345             case POINTER:
13346             case FPOINTER:
13347                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13348                 break;
13349
13350             case CPOINTER:
13351                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13352                 break;
13353
13354             case PPOINTER:
13355               pic16_emitcode(";BUG!? ","%d",__LINE__);
13356                 l = "#0x03";
13357                 break;
13358
13359             case GPOINTER:
13360                 if (GPTRSIZE > AOP_SIZE(right)) {
13361                   // assume __data pointer... THIS MIGHT BE WRONG!
13362                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13363                 } else {
13364                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13365                 }
13366               break;
13367               
13368             default:
13369                 /* this should never happen */
13370                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13371                        "got unknown pointer type");
13372                 exit(1);
13373             }
13374             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13375             goto release ;
13376         }
13377         
13378         
13379         assert( 0 );
13380         /* just copy the pointers */
13381         size = AOP_SIZE(result);
13382         offset = 0 ;
13383         while (size--) {
13384             pic16_aopPut(AOP(result),
13385                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13386                    offset);
13387             offset++;
13388         }
13389         goto release ;
13390     }
13391     
13392
13393
13394     /* so we now know that the size of destination is greater
13395     than the size of the source.
13396     Now, if the next iCode is an operator then we might be
13397     able to optimize the operation without performing a cast.
13398     */
13399     if(genMixedOperation(ic))
13400       goto release;
13401
13402     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13403     
13404     /* we move to result for the size of source */
13405     size = AOP_SIZE(right);
13406     offset = 0 ;
13407
13408     while (size--) {
13409       if(!_G.resDirect)
13410         pic16_mov2f(AOP(result), AOP(right), offset);
13411       offset++;
13412     }
13413
13414     /* now depending on the sign of the destination */
13415     size = AOP_SIZE(result) - AOP_SIZE(right);
13416     /* if unsigned or not an integral type */
13417     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13418       while (size--)
13419         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13420     } else {
13421       /* we need to extend the sign :( */
13422
13423       if(size == 1) {
13424         /* Save one instruction of casting char to int */
13425         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13426         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13427         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13428       } else {
13429         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13430
13431         if(offset)
13432           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13433         else
13434           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13435         
13436         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13437
13438         while (size--)
13439           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13440       }
13441     }
13442
13443 release:
13444     pic16_freeAsmop(right,NULL,ic,TRUE);
13445     pic16_freeAsmop(result,NULL,ic,TRUE);
13446
13447 }
13448
13449 /*-----------------------------------------------------------------*/
13450 /* genDjnz - generate decrement & jump if not zero instrucion      */
13451 /*-----------------------------------------------------------------*/
13452 static int genDjnz (iCode *ic, iCode *ifx)
13453 {
13454     symbol *lbl, *lbl1;
13455     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13456
13457     if (!ifx)
13458         return 0;
13459     
13460     /* if the if condition has a false label
13461        then we cannot save */
13462     if (IC_FALSE(ifx))
13463         return 0;
13464
13465     /* if the minus is not of the form 
13466        a = a - 1 */
13467     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13468         !IS_OP_LITERAL(IC_RIGHT(ic)))
13469         return 0;
13470
13471     if (operandLitValue(IC_RIGHT(ic)) != 1)
13472         return 0;
13473
13474     /* if the size of this greater than one then no
13475        saving */
13476     if (getSize(operandType(IC_RESULT(ic))) > 1)
13477         return 0;
13478
13479     /* otherwise we can save BIG */
13480     lbl = newiTempLabel(NULL);
13481     lbl1= newiTempLabel(NULL);
13482
13483     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13484     
13485     if (IS_AOP_PREG(IC_RESULT(ic))) {
13486         pic16_emitcode("dec","%s",
13487                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13488         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13489         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13490     } else {    
13491
13492
13493       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13494       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13495
13496       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13497       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13498
13499     }
13500     
13501     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13502     ifx->generated = 1;
13503     return 1;
13504 }
13505
13506 /*-----------------------------------------------------------------*/
13507 /* genReceive - generate code for a receive iCode                  */
13508 /*-----------------------------------------------------------------*/
13509 static void genReceive (iCode *ic)
13510 {    
13511
13512   FENTRY;
13513
13514 #if 0
13515   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13516         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13517 #endif
13518 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13519
13520   if (isOperandInFarSpace(IC_RESULT(ic))
13521       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13522           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13523
13524     int size = getSize(operandType(IC_RESULT(ic)));
13525     int offset =  pic16_fReturnSizePic - size;
13526
13527       assert( 0 );
13528       while (size--) {
13529         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13530                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13531                       offset++;
13532         }
13533
13534       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13535
13536       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13537       size = AOP_SIZE(IC_RESULT(ic));
13538       offset = 0;
13539       while (size--) {
13540         pic16_emitcode ("pop","acc");
13541         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13542       }
13543   } else {
13544     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13545     _G.accInUse++;
13546     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13547     _G.accInUse--;
13548
13549     /* set pseudo stack pointer to where it should be - dw*/
13550     GpsuedoStkPtr = ic->parmBytes;
13551
13552     /* setting GpsuedoStkPtr has side effects here: */
13553     /* FIXME: What's the correct size of the return(ed) value?
13554      *        For now, assuming '4' as before... */
13555     assignResultValue(IC_RESULT(ic), 4, 0);
13556   }
13557
13558   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13559 }
13560
13561 /*-----------------------------------------------------------------*/
13562 /* genDummyRead - generate code for dummy read of volatiles        */
13563 /*-----------------------------------------------------------------*/
13564 static void
13565 genDummyRead (iCode * ic)
13566 {
13567   operand *op;
13568   int i;
13569
13570   op = IC_RIGHT(ic);
13571   if (op && IS_SYMOP(op)) {
13572     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13573       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13574       return;
13575     }
13576     pic16_aopOp (op, ic, FALSE);
13577     for (i=0; i < AOP_SIZE(op); i++) {
13578       // may need to protect this from the peepholer -- this is not nice but works...
13579       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13580       pic16_mov2w (AOP(op),i);
13581       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13582     } // for i
13583     pic16_freeAsmop (op, NULL, ic, TRUE);
13584   } else if (op) {
13585     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13586   } // if
13587 }
13588
13589 /*-----------------------------------------------------------------*/
13590 /* genpic16Code - generate code for pic16 based controllers        */
13591 /*-----------------------------------------------------------------*/
13592 /*
13593  * At this point, ralloc.c has gone through the iCode and attempted
13594  * to optimize in a way suitable for a PIC. Now we've got to generate
13595  * PIC instructions that correspond to the iCode.
13596  *
13597  * Once the instructions are generated, we'll pass through both the
13598  * peep hole optimizer and the pCode optimizer.
13599  *-----------------------------------------------------------------*/
13600
13601 void genpic16Code (iCode *lic)
13602 {
13603   iCode *ic;
13604   int cln = 0;
13605
13606     lineHead = lineCurr = NULL;
13607
13608     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13609     pic16_addpBlock(pb);
13610
13611 #if 0
13612     /* if debug information required */
13613     if (options.debug && currFunc) {
13614       if (currFunc) {
13615         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13616       }
13617     }
13618 #endif
13619
13620     for (ic = lic ; ic ; ic = ic->next ) {
13621
13622       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13623       if ( cln != ic->lineno ) {
13624         if ( options.debug ) {
13625           debugFile->writeCLine (ic);
13626         }
13627         
13628         if(!options.noCcodeInAsm) {
13629           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13630               printCLine(ic->filename, ic->lineno)));
13631         }
13632
13633         cln = ic->lineno ;
13634       }
13635         
13636       if(options.iCodeInAsm) {
13637         char *iLine;
13638
13639           /* insert here code to print iCode as comment */
13640           iLine = printILine(ic);
13641           pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
13642           dbuf_free(iLine);
13643       }
13644
13645       /* if the result is marked as
13646        * spilt and rematerializable or code for
13647        * this has already been generated then
13648        * do nothing */
13649       if (resultRemat(ic) || ic->generated ) 
13650         continue ;
13651         
13652       /* depending on the operation */
13653       switch (ic->op) {
13654         case '!' :
13655           pic16_genNot(ic);
13656           break;
13657             
13658         case '~' :
13659           pic16_genCpl(ic);
13660           break;
13661             
13662         case UNARYMINUS:
13663           genUminus (ic);
13664           break;
13665             
13666         case IPUSH:
13667           genIpush (ic);
13668           break;
13669             
13670         case IPOP:
13671           /* IPOP happens only when trying to restore a 
13672            * spilt live range, if there is an ifx statement
13673            * following this pop then the if statement might
13674            * be using some of the registers being popped which
13675            * would destroy the contents of the register so
13676            * we need to check for this condition and handle it */
13677            if (ic->next
13678              && ic->next->op == IFX
13679              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13680                genIfx (ic->next,ic);
13681           else
13682             genIpop (ic);
13683           break; 
13684             
13685         case CALL:
13686           genCall (ic);
13687           break;
13688             
13689         case PCALL:
13690           genPcall (ic);
13691           break;
13692             
13693         case FUNCTION:
13694           genFunction (ic);
13695           break;
13696             
13697         case ENDFUNCTION:
13698           genEndFunction (ic);
13699           break;
13700             
13701         case RETURN:
13702           genRet (ic);
13703           break;
13704             
13705         case LABEL:
13706           genLabel (ic);
13707           break;
13708             
13709         case GOTO:
13710           genGoto (ic);
13711           break;
13712             
13713         case '+' :
13714           pic16_genPlus (ic) ;
13715           break;
13716             
13717         case '-' :
13718           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13719             pic16_genMinus (ic);
13720           break;
13721
13722         case '*' :
13723           genMult (ic);
13724           break;
13725             
13726         case '/' :
13727           genDiv (ic) ;
13728           break;
13729             
13730         case '%' :
13731           genMod (ic);
13732           break;
13733             
13734         case '>' :
13735           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13736           break;
13737             
13738         case '<' :
13739           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13740           break;
13741             
13742         case LE_OP:
13743         case GE_OP:
13744         case NE_OP:
13745           /* note these two are xlated by algebraic equivalence
13746            * during parsing SDCC.y */
13747           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13748             "got '>=' or '<=' shouldn't have come here");
13749           break;
13750
13751         case EQ_OP:
13752           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13753           break;            
13754             
13755         case AND_OP:
13756           genAndOp (ic);
13757           break;
13758             
13759         case OR_OP:
13760           genOrOp (ic);
13761           break;
13762             
13763         case '^' :
13764           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13765           break;
13766             
13767         case '|' :
13768           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13769           break;
13770             
13771         case BITWISEAND:
13772           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13773           break;
13774             
13775         case INLINEASM:
13776           genInline (ic);
13777           break;
13778             
13779         case RRC:
13780           genRRC (ic);
13781           break;
13782             
13783         case RLC:
13784           genRLC (ic);
13785           break;
13786             
13787         case GETHBIT:
13788           genGetHbit (ic);
13789           break;
13790             
13791         case LEFT_OP:
13792           genLeftShift (ic);
13793           break;
13794             
13795         case RIGHT_OP:
13796           genRightShift (ic);
13797           break;
13798             
13799         case GET_VALUE_AT_ADDRESS:
13800           genPointerGet(ic);
13801           break;
13802             
13803         case '=' :
13804           if (POINTER_SET(ic))
13805             genPointerSet(ic);
13806           else
13807             genAssign(ic);
13808           break;
13809             
13810         case IFX:
13811           genIfx (ic,NULL);
13812           break;
13813             
13814         case ADDRESS_OF:
13815           genAddrOf (ic);
13816           break;
13817             
13818         case JUMPTABLE:
13819           genJumpTab (ic);
13820           break;
13821             
13822         case CAST:
13823           genCast (ic);
13824           break;
13825             
13826         case RECEIVE:
13827           genReceive(ic);
13828           break;
13829             
13830         case SEND:
13831           addSet(&_G.sendSet,ic);
13832           break;
13833
13834         case DUMMY_READ_VOLATILE:
13835           genDummyRead (ic);
13836           break;
13837
13838         default :
13839           ic = ic;
13840       }
13841     }
13842
13843
13844     /* now we are ready to call the
13845        peep hole optimizer */
13846     if (!options.nopeep)
13847       peepHole (&lineHead);
13848
13849     /* now do the actual printing */
13850     printLine (lineHead, codeOutBuf);
13851
13852 #ifdef PCODE_DEBUG
13853     DFPRINTF((stderr,"printing pBlock\n\n"));
13854     pic16_printpBlock(stdout,pb);
13855 #endif
13856
13857     return;
13858 }
13859