* src/pic/pcode.c (LinkFlow): handle empty flows correctly,
[fw/sdcc] / src / pic16 / gen.c
1  /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
10   Bug Fixes  -  Raphael Neider rneider@web.de (2004,2005)
11   
12   This program is free software; you can redistribute it and/or modify it
13   under the terms of the GNU General Public License as published by the
14   Free Software Foundation; either version 2, or (at your option) any
15   later version.
16   
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21   
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software
24   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25   
26   In other words, you are welcome to use, share and improve this program.
27   You are forbidden to forbid anyone else to use, share and improve
28   what you give them.   Help stamp out software-hoarding!
29   
30   Notes:
31   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
32                 Made everything static
33 -------------------------------------------------------------------------*/
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "SDCCglobl.h"
40 #include "newalloc.h"
41
42 #include "common.h"
43 #include "SDCCpeeph.h"
44 #include "ralloc.h"
45 #include "pcode.h"
46 #include "gen.h"
47 #include "genutils.h"
48 #include "device.h"
49 #include "main.h"
50
51 /* Set the following to 1 to enable the slower/bigger
52  * but more robust generic shifting routine (which also
53  * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
55
56 /* Set the following to 1 to enable the new
57  * stripped down genCmp version.
58  * This version should be easier to understand,
59  * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
61
62 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
63 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
64 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
66
67 /* If you change these, you also have to update the library files
68  * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
69 #define GPTR_TAG_DATA   0x80
70 #define GPTR_TAG_EEPROM 0x40
71 #define GPTR_TAG_CODE   0x00    /* must be 0 becaue of UPPER(sym)==0 */
72
73 /* Wrapper to execute `code' at most once. */
74 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
75
76 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
77 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
78 void pic16_genMult8X8_8 (operand *, operand *,operand *);
79 void pic16_genMult16X16_16(operand *, operand *, operand *);
80 void pic16_genMult32X32_32(operand *, operand *, operand *);
81 pCode *pic16_AssembleLine(char *line, int peeps);
82 extern void pic16_printpBlock(FILE *of, pBlock *pb);
83 static asmop *newAsmop (short type);
84 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
85 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
86 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
87 static pCodeOp *pic16_popRegFromIdx(int rIdx);
88
89 //static int aopIdx (asmop *aop, int offset);
90
91 int pic16_labelOffset=0;
92 extern int pic16_debug_verbose;
93 #if !(USE_GENERIC_SIGNED_SHIFT)
94 static int optimized_for_speed = 0;
95 #endif
96 /*
97   hack hack
98
99 */
100
101 extern set *externs;
102
103 /* max_key keeps track of the largest label number used in 
104    a function. This is then used to adjust the label offset
105    for the next function.
106 */
107 static int max_key=0;
108 static int GpsuedoStkPtr=0;
109
110 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
111
112 unsigned int pic16aopLiteral (value *val, int offset);
113 const char *pic16_AopType(short type);
114 static iCode *ifxForOp ( operand *op, iCode *ic );
115
116 void pic16_pushpCodeOp(pCodeOp *pcop);
117 void pic16_poppCodeOp(pCodeOp *pcop);
118
119 static bool is_LitOp(operand *op);
120 static bool is_LitAOp(asmop *aop);
121
122
123 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
124
125 /* set the following macro to 1 to enable passing the
126  * first byte of functions parameters via WREG */
127 #define USE_WREG_IN_FUNC_PARAMS 0
128
129
130 /* this is the down and dirty file with all kinds of 
131    kludgy & hacky stuff. This is what it is all about
132    CODE GENERATION for a specific MCU . some of the
133    routines may be reusable, will have to see */
134
135 static char *zero = "#0x00";
136 static char *one  = "#0x01";
137 //static char *spname = "sp";
138
139
140 /*
141  * Function return value policy (MSB-->LSB):
142  *  8 bits      -> WREG
143  * 16 bits      -> PRODL:WREG
144  * 24 bits      -> PRODH:PRODL:WREG
145  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
146  * >32 bits     -> on stack, and FSR0 points to the beginning
147  *
148  */
149  
150
151 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
152 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
153 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
154 static char **fReturn = fReturnpic16;
155
156 static char *accUse[] = {"WREG"};
157
158 //static short rbank = -1;
159
160 static struct {
161     short r0Pushed;
162     short r1Pushed;
163     short fsr0Pushed;
164     short accInUse;
165     short inLine;
166     short debugLine;
167     short nRegsSaved;
168     short ipushRegs;
169     set *sendSet;
170     set *stackRegSet;
171     int usefastretfie;
172     bitVect *fregsUsed;                 /* registers used in function */
173     bitVect *sregsAlloc;
174     set *sregsAllocSet;                 /* registers used to store stack variables */
175     int stack_lat;                      /* stack offset latency */
176     int resDirect;
177     int useWreg;                        /* flag when WREG is used to pass function parameter */
178 } _G;
179
180 extern int pic16_ptrRegReq ;
181 extern int pic16_nRegs;
182 extern FILE *codeOutFile;
183 //static void saverbank (int, iCode *,bool);
184
185 static lineNode *lineHead = NULL;
186 static lineNode *lineCurr = NULL;
187
188 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
189 0xE0, 0xC0, 0x80, 0x00};
190 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
191 0x07, 0x03, 0x01, 0x00};
192
193 static  pBlock *pb;
194
195 /*-----------------------------------------------------------------*/
196 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
197 /*                 exponent of 2 is returned, otherwise -1 is      */
198 /*                 returned.                                       */
199 /* note that this is similar to the function `powof2' in SDCCsymt  */
200 /* if(n == 2^y)                                                    */
201 /*   return y;                                                     */
202 /* return -1;                                                      */
203 /*-----------------------------------------------------------------*/
204 int pic16_my_powof2 (unsigned long num)
205 {
206   if(num) {
207     if( (num & (num-1)) == 0) {
208       int nshifts = -1;
209       while(num) {
210         num>>=1;
211         nshifts++;
212       }
213       return nshifts;
214     }
215   }
216
217   return -1;
218 }
219
220 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
221 {
222   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
223                        line_no,
224                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
225                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
226                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
227                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
228                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
229                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
230                        ((result) ? AOP_SIZE(result) : 0));
231 }
232
233 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
234 {
235
236   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
237                        line_no,
238                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
239                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
240                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
241                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
242                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
243                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
244
245 }
246
247 void pic16_emitpcomment (char *fmt, ...)
248 {
249     va_list ap;
250     char lb[INITIAL_INLINEASM];  
251     unsigned char *lbp = lb;
252
253     va_start(ap,fmt);   
254
255     lb[0] = ';';
256     vsprintf(lb+1,fmt,ap);
257
258     while (isspace(*lbp)) lbp++;
259
260     if (lbp && *lbp) 
261         lineCurr = (lineCurr ?
262                     connectLine(lineCurr,newLineNode(lb)) :
263                     (lineHead = newLineNode(lb)));
264     lineCurr->isInline = _G.inLine;
265     lineCurr->isDebug  = _G.debugLine;
266
267     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
268     va_end(ap);
269
270 //      fprintf(stderr, "%s\n", lb);
271 }
272
273 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
274 {
275     va_list ap;
276     char lb[INITIAL_INLINEASM];  
277     unsigned char *lbp = lb;
278
279     if(!pic16_debug_verbose)
280       return;
281
282     va_start(ap,fmt);   
283
284     if (inst && *inst) {
285         if (fmt && *fmt)
286             sprintf(lb,"%s\t",inst);
287         else
288             sprintf(lb,"%s",inst);
289         vsprintf(lb+(strlen(lb)),fmt,ap);
290     }  else
291         vsprintf(lb,fmt,ap);
292
293     while (isspace(*lbp)) lbp++;
294
295     if (lbp && *lbp) 
296         lineCurr = (lineCurr ?
297                     connectLine(lineCurr,newLineNode(lb)) :
298                     (lineHead = newLineNode(lb)));
299     lineCurr->isInline = _G.inLine;
300     lineCurr->isDebug  = _G.debugLine;
301
302     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
303     va_end(ap);
304
305 //      fprintf(stderr, "%s\n", lb);
306 }
307
308
309
310 void pic16_emitpLabel(int key)
311 {
312   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
313 }
314
315 void pic16_emitpLabelFORCE(int key)
316 {
317   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
318 }
319
320 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
321  * NEVER call pic16_emitpcode_real directly, please... */
322 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
323 {
324
325   if(pcop)
326     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
327   else
328     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
329 }
330
331 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
332 {
333   if(pcop)
334     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
335   else
336     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
337 }
338   
339 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
340 {
341
342   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
343
344 }
345
346
347 #if 1
348 #define pic16_emitcode  DEBUGpic16_emitcode
349 #else
350 /*-----------------------------------------------------------------*/
351 /* pic16_emitcode - writes the code into a file : for now it is simple    */
352 /*-----------------------------------------------------------------*/
353 void pic16_emitcode (char *inst,char *fmt, ...)
354 {
355     va_list ap;
356     char lb[INITIAL_INLINEASM];  
357     unsigned char *lbp = lb;
358
359     va_start(ap,fmt);   
360
361     if (inst && *inst) {
362         if (fmt && *fmt)
363             sprintf(lb,"%s\t",inst);
364         else
365             sprintf(lb,"%s",inst);
366         vsprintf(lb+(strlen(lb)),fmt,ap);
367     }  else
368         vsprintf(lb,fmt,ap);
369
370     while (isspace(*lbp)) lbp++;
371
372     if (lbp && *lbp) 
373         lineCurr = (lineCurr ?
374                     connectLine(lineCurr,newLineNode(lb)) :
375                     (lineHead = newLineNode(lb)));
376     lineCurr->isInline = _G.inLine;
377     lineCurr->isDebug  = _G.debugLine;
378
379 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
380
381 //    if(pic16_debug_verbose)
382 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
383
384     va_end(ap);
385 }
386 #endif
387
388
389 /*-----------------------------------------------------------------*/
390 /* pic16_emitDebuggerSymbol - associate the current code location  */
391 /*   with a debugger symbol                                        */
392 /*-----------------------------------------------------------------*/
393 void
394 pic16_emitDebuggerSymbol (char * debugSym)
395 {
396   _G.debugLine = 1;
397   pic16_emitcode (";", "%s ==.", debugSym);
398   _G.debugLine = 0;
399 }
400
401
402 /*-----------------------------------------------------------------*/
403 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
404 /*-----------------------------------------------------------------*/
405 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
406 {
407 //    bool r0iu = FALSE , r1iu = FALSE;
408 //    bool r0ou = FALSE , r1ou = FALSE;
409     bool fsr0iu = FALSE, fsr0ou;
410     bool fsr2iu = FALSE, fsr2ou;
411     
412     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
413
414     
415     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
416     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
417     
418     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
419     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
420
421     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
422         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
423         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
424     }
425
426     if(!fsr0iu && !fsr0ou) {
427         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
428         (*aopp)->type = AOP_FSR0;
429
430         fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
431         
432       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
433     }
434
435 #if 0
436     /* no usage of FSR2 */
437     if(!fsr2iu && !fsr2ou) {
438         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
439         (*aopp)->type = AOP_FSR2;
440
441       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
442     }
443 #endif
444         
445     /* now we know they both have usage */
446     /* if fsr0 not used in this instruction */
447     if (!fsr0iu) {
448         if (!_G.fsr0Pushed) {
449                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
450                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
451                 _G.fsr0Pushed++;
452         }
453
454         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
455         (*aopp)->type = AOP_FSR0;
456
457 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
458
459       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
460     }
461         
462
463     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
464     assert( 0 );
465
466     return NULL;
467 #if 0
468     /* the logic: if r0 & r1 used in the instruction
469     then we are in trouble otherwise */
470
471     /* first check if r0 & r1 are used by this
472     instruction, in which case we are in trouble */
473     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
474         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
475     {
476         goto endOfWorld;      
477     }
478
479     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
480     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
481
482     /* if no usage of r0 then return it */
483     if (!r0iu && !r0ou) {
484         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
485         (*aopp)->type = AOP_R0; 
486         
487         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
488     }
489
490     /* if no usage of r1 then return it */
491     if (!r1iu && !r1ou) {
492         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
493         (*aopp)->type = AOP_R1;
494
495         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
496     }    
497
498     /* now we know they both have usage */
499     /* if r0 not used in this instruction */
500     if (!r0iu) {
501         /* push it if not already pushed */
502         if (!_G.r0Pushed) {
503           //pic16_emitcode ("push","%s",
504           //          pic16_regWithIdx(R0_IDX)->dname);
505             _G.r0Pushed++ ;
506         }
507         
508         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
509         (*aopp)->type = AOP_R0;
510
511         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
512     }
513
514     /* if r1 not used then */
515
516     if (!r1iu) {
517         /* push it if not already pushed */
518         if (!_G.r1Pushed) {
519           //pic16_emitcode ("push","%s",
520           //          pic16_regWithIdx(R1_IDX)->dname);
521             _G.r1Pushed++ ;
522         }
523         
524         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
525         (*aopp)->type = AOP_R1;
526         return pic16_regWithIdx(R1_IDX);
527     }
528
529 endOfWorld :
530     /* I said end of world but not quite end of world yet */
531     /* if this is a result then we can push it on the stack*/
532     if (result) {
533         (*aopp)->type = AOP_STK;    
534         return NULL;
535     }
536
537     /* other wise this is true end of the world */
538     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
539            "getFreePtr should never reach here");
540     exit(0);
541 #endif
542 }
543
544 /*-----------------------------------------------------------------*/
545 /* newAsmop - creates a new asmOp                                  */
546 /*-----------------------------------------------------------------*/
547 static asmop *newAsmop (short type)
548 {
549     asmop *aop;
550
551     aop = Safe_calloc(1,sizeof(asmop));
552     aop->type = type;
553     return aop;
554 }
555
556 static void genSetDPTR(int n)
557 {
558     if (!n)
559     {
560         pic16_emitcode(";", "Select standard DPTR");
561         pic16_emitcode("mov", "dps, #0x00");
562     }
563     else
564     {
565         pic16_emitcode(";", "Select alternate DPTR");
566         pic16_emitcode("mov", "dps, #0x01");
567     }
568 }
569
570 /*-----------------------------------------------------------------*/
571 /* resolveIfx - converts an iCode ifx into a form more useful for  */
572 /*              generating code                                    */
573 /*-----------------------------------------------------------------*/
574 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
575 {
576   FENTRY2;
577   
578 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
579
580   if(!resIfx) 
581     return;
582
583
584   resIfx->condition = 1;    /* assume that the ifx is true */
585   resIfx->generated = 0;    /* indicate that the ifx has not been used */
586
587   if(!ifx) {
588     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
589
590 #if 1
591     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
592                         __FUNCTION__,__LINE__,resIfx->lbl->key);
593 #endif
594
595   } else {
596     if(IC_TRUE(ifx)) {
597       resIfx->lbl = IC_TRUE(ifx);
598     } else {
599       resIfx->lbl = IC_FALSE(ifx);
600       resIfx->condition = 0;
601     }
602
603 #if 1
604     if(IC_TRUE(ifx)) 
605       DEBUGpic16_emitcode("; +++","ifx true is non-null");
606     else
607       DEBUGpic16_emitcode("; +++","ifx true is null");
608     if(IC_FALSE(ifx)) 
609       DEBUGpic16_emitcode("; +++","ifx false is non-null");
610     else
611       DEBUGpic16_emitcode("; +++","ifx false is null");
612 #endif
613   }
614
615   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
616
617 }
618 #if 0
619 /*-----------------------------------------------------------------*/
620 /* pointerCode - returns the code for a pointer type               */
621 /*-----------------------------------------------------------------*/
622 static int pointerCode (sym_link *etype)
623 {
624
625     return PTR_TYPE(SPEC_OCLS(etype));
626
627 }
628 #endif
629
630 /*-----------------------------------------------------------------*/
631 /* aopForSym - for a true symbol                                   */
632 /*-----------------------------------------------------------------*/
633 static asmop *aopForSym (iCode *ic, operand *op, bool result)
634 {
635     symbol *sym=OP_SYMBOL(op);
636     asmop *aop;
637     memmap *space= SPEC_OCLS(sym->etype);
638
639     FENTRY2;
640     
641     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
642     
643 //    sym = OP_SYMBOL(op);
644
645     /* if already has one */
646     if (sym->aop) {
647             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
648         return sym->aop;
649     }
650
651 #if 0
652     /* if symbol was initially placed onStack then we must re-place it
653      * to direct memory, since pic16 does not have a specific stack */
654     if(sym->onStack) {
655         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
656     }
657 #endif
658
659
660 #if 0
661     if(sym->iaccess) {
662       if(space->paged) {
663         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
664
665         sym->aop = aop = newAsmop (AOP_PAGED);
666         aop->aopu.aop_dir = sym->rname ;
667         aop->size = getSize(sym->type);
668         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
669         pic16_allocDirReg( IC_LEFT(ic) );
670         return aop;
671       }
672       assert( 0 );
673     }
674 #endif
675     
676 #if 1
677     /* assign depending on the storage class */
678     /* if it is on the stack or indirectly addressable */
679     /* space we need to assign either r0 or r1 to it   */    
680     if (sym->onStack)   // || sym->iaccess)
681     {
682       pCodeOp *pcop[4];
683       int i;
684       
685         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
686                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
687         
688         /* acquire a temporary register -- it is saved in function */
689
690         sym->aop = aop = newAsmop(AOP_STA);
691         aop->aopu.stk.stk = sym->stack;
692         aop->size = getSize(sym->type);
693
694
695         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
696         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
697           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
698 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
699           
700           for(i=0;i<aop->size;i++)
701             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
702             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
703         } else
704         if(1 && ic->op == SEND) {
705
706           /* if SEND do the send here */
707           _G.resDirect = 1;
708         } else {
709           for(i=0;i<aop->size;i++) {
710             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
711             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
712           }
713         }
714
715
716 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
717
718 #if 1
719         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
720
721         // we do not need to load the value if it is to be defined...
722         if (result) return aop;
723
724         if(_G.accInUse) {
725                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
726         }
727         
728         for(i=0;i<aop->size;i++) {
729
730           /* initialise for stack access via frame pointer */
731           // operands on stack are accessible via "FSR2 + index" with index
732           // starting at 2 for arguments and growing from 0 downwards for
733           // local variables (index == 0 is not assigned so we add one here)
734           {
735             int soffs = sym->stack;
736             if (soffs <= 0) {
737               assert (soffs < 0);
738               soffs++;
739             } // if
740
741             if(1 && ic->op == SEND) {
742               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
743               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
744                     pic16_popCopyReg( pic16_frame_plusw ),
745                     pic16_popCopyReg(pic16_stack_postdec )));
746             } else {
747               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
748               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
749                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
750             }
751           }
752         }
753         
754         if(_G.accInUse) {
755                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
756         }
757         
758         return (aop);
759 #endif
760
761 #if 0
762         /* now assign the address of the variable to 
763         the pointer register */
764         if (aop->type != AOP_STK) {
765
766             if (sym->onStack) {
767                     if ( _G.accInUse )
768                         pic16_emitcode("push","acc");
769
770                     pic16_emitcode("mov","a,_bp");
771                     pic16_emitcode("add","a,#0x%02x",
772                              ((sym->stack < 0) ?
773                               ((char)(sym->stack - _G.nRegsSaved )) :
774                               ((char)sym->stack)) & 0xff);
775                     pic16_emitcode("mov","%s,a",
776                              aop->aopu.aop_ptr->name);
777
778                     if ( _G.accInUse )
779                         pic16_emitcode("pop","acc");
780             } else
781                 pic16_emitcode("mov","%s,#%s",
782                          aop->aopu.aop_ptr->name,
783                          sym->rname);
784             aop->paged = space->paged;
785         } else
786             aop->aopu.aop_stk = sym->stack;
787         return aop;
788 #endif
789
790     }
791 #endif
792
793 #if 0
794     if (sym->onStack && options.stack10bit)
795     {
796         /* It's on the 10 bit stack, which is located in
797          * far data space.
798          */
799          
800       //DEBUGpic16_emitcode(";","%d",__LINE__);
801
802         if ( _G.accInUse )
803                 pic16_emitcode("push","acc");
804
805         pic16_emitcode("mov","a,_bp");
806         pic16_emitcode("add","a,#0x%02x",
807                  ((sym->stack < 0) ?
808                    ((char)(sym->stack - _G.nRegsSaved )) :
809                    ((char)sym->stack)) & 0xff);
810         
811         genSetDPTR(1);
812         pic16_emitcode ("mov","dpx1,#0x40");
813         pic16_emitcode ("mov","dph1,#0x00");
814         pic16_emitcode ("mov","dpl1, a");
815         genSetDPTR(0);
816         
817         if ( _G.accInUse )
818             pic16_emitcode("pop","acc");
819             
820         sym->aop = aop = newAsmop(AOP_DPTR2);
821         aop->size = getSize(sym->type); 
822         return aop;
823     }
824 #endif
825
826 #if 1
827     /* special case for a function */
828     if (IS_FUNC(sym->type)) {   
829         sym->aop = aop = newAsmop(AOP_PCODE);
830         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
831         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
832         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
833         PCOI(aop->aopu.pcop)->index = 0;
834         aop->size = FPTRSIZE; 
835         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
836         return aop;
837     }
838 #endif
839
840
841
842     //DEBUGpic16_emitcode(";","%d",__LINE__);
843     /* if in bit space */
844     if (IN_BITSPACE(space)) {
845         sym->aop = aop = newAsmop (AOP_CRY);
846         aop->aopu.aop_dir = sym->rname ;
847         aop->size = getSize(sym->type);
848         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
849         return aop;
850     }
851     /* if it is in direct space */
852     if (IN_DIRSPACE(space)) {
853         sym->aop = aop = newAsmop (AOP_DIR);
854         aop->aopu.aop_dir = sym->rname ;
855         aop->size = getSize(sym->type);
856         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
857         pic16_allocDirReg( IC_LEFT(ic) );
858         return aop;
859     }
860
861
862     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
863         sym->aop = aop = newAsmop (AOP_DIR);
864         aop->aopu.aop_dir = sym->rname ;
865         aop->size = getSize(sym->type);
866         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
867         pic16_allocDirReg( IC_LEFT(ic) );
868         return aop;
869     }
870
871
872     /* only remaining is far space */
873     sym->aop = aop = newAsmop(AOP_PCODE);
874
875 /* change the next if to 1 to revert to good old immediate code */
876         if(IN_CODESPACE(space)) {
877                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
878                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
879                 PCOI(aop->aopu.pcop)->index = 0;
880         } else {
881                 /* try to allocate via direct register */
882                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
883 //              aop->size = getSize( sym->type );
884         }
885
886         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
887                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
888
889 #if 0
890         if(!pic16_allocDirReg (IC_LEFT(ic)))
891                 return NULL;
892 #endif
893
894         if(IN_DIRSPACE( space ))
895                 aop->size = PTRSIZE;
896         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
897                 aop->size = FPTRSIZE;
898         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
899         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
900         else if(sym->onStack) {
901                 aop->size = PTRSIZE;
902         } else {
903           if(SPEC_SCLS(sym->etype) == S_PDATA) {
904             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
905             aop->size = FPTRSIZE;
906           } else
907                 assert( 0 );
908         }
909
910     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
911
912     /* if it is in code space */
913     if (IN_CODESPACE(space))
914         aop->code = 1;
915
916     return aop;     
917 }
918
919 /*-----------------------------------------------------------------*/
920 /* aopForRemat - rematerialzes an object                           */
921 /*-----------------------------------------------------------------*/
922 static asmop *aopForRemat (operand *op) // x symbol *sym)
923 {
924   symbol *sym = OP_SYMBOL(op);
925   operand *refop;
926   iCode *ic = NULL, *oldic;
927   asmop *aop = newAsmop(AOP_PCODE);
928   int val = 0;
929   int offset = 0;
930   int viaimmd=0;
931
932     FENTRY2;
933     
934         ic = sym->rematiCode;
935
936         if(IS_OP_POINTER(op)) {
937                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
938         }
939
940         for (;;) {
941                 oldic = ic;
942
943 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
944         
945                 if (ic->op == '+') {
946                         val += (int) operandLitValue(IC_RIGHT(ic));
947                 } else if (ic->op == '-') {
948                         val -= (int) operandLitValue(IC_RIGHT(ic));
949                 } else
950                         break;
951                 
952                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
953         }
954
955         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
956         refop = IC_LEFT(ic);
957
958         if(!op->isaddr)viaimmd++; else viaimmd=0;
959                 
960 /* set the following if to 1 to revert to good old immediate code */
961         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
962                 || viaimmd) {
963
964                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
965
966                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
967
968 #if 0
969                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
970 #else
971                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
972 #endif
973
974                 PCOI(aop->aopu.pcop)->index = val;
975                 
976                 aop->size = getSize( sym->type );
977         } else {
978                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
979
980                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
981                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
982
983                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
984         }
985
986
987         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
988                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
989 #if 0
990                 val, IS_PTR_CONST(operandType(op)));
991 #else
992                 val, IS_CODEPTR(operandType(op)));
993 #endif
994
995 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
996
997         pic16_allocDirReg (IC_LEFT(ic));
998
999         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1000                 aop->code = 1;
1001
1002   return aop;        
1003 }
1004
1005 #if 0
1006 static int aopIdx (asmop *aop, int offset)
1007 {
1008   if(!aop)
1009     return -1;
1010
1011   if(aop->type !=  AOP_REG)
1012     return -2;
1013         
1014   return aop->aopu.aop_reg[offset]->rIdx;
1015
1016 }
1017 #endif
1018
1019 /*-----------------------------------------------------------------*/
1020 /* regsInCommon - two operands have some registers in common       */
1021 /*-----------------------------------------------------------------*/
1022 static bool regsInCommon (operand *op1, operand *op2)
1023 {
1024     symbol *sym1, *sym2;
1025     int i;
1026
1027     /* if they have registers in common */
1028     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1029         return FALSE ;
1030
1031     sym1 = OP_SYMBOL(op1);
1032     sym2 = OP_SYMBOL(op2);
1033
1034     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1035         return FALSE ;
1036
1037     for (i = 0 ; i < sym1->nRegs ; i++) {
1038         int j;
1039         if (!sym1->regs[i])
1040             continue ;
1041
1042         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1043             if (!sym2->regs[j])
1044                 continue ;
1045
1046             if (sym2->regs[j] == sym1->regs[i])
1047                 return TRUE ;
1048         }
1049     }
1050
1051     return FALSE ;
1052 }
1053
1054 /*-----------------------------------------------------------------*/
1055 /* operandsEqu - equivalent                                        */
1056 /*-----------------------------------------------------------------*/
1057 static bool operandsEqu ( operand *op1, operand *op2)
1058 {
1059     symbol *sym1, *sym2;
1060
1061     /* if they not symbols */
1062     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1063         return FALSE;
1064
1065     sym1 = OP_SYMBOL(op1);
1066     sym2 = OP_SYMBOL(op2);
1067
1068     /* if both are itemps & one is spilt
1069        and the other is not then false */
1070     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1071         sym1->isspilt != sym2->isspilt )
1072         return FALSE ;
1073
1074     /* if they are the same */
1075     if (sym1 == sym2)
1076         return TRUE ;
1077
1078     if (sym1->rname[0] && sym2->rname[0]
1079         && strcmp (sym1->rname, sym2->rname) == 0)
1080         return TRUE;
1081
1082
1083     /* if left is a tmp & right is not */
1084     if (IS_ITEMP(op1)  && 
1085         !IS_ITEMP(op2) &&
1086         sym1->isspilt  &&
1087         (sym1->usl.spillLoc == sym2))
1088         return TRUE;
1089
1090     if (IS_ITEMP(op2)  && 
1091         !IS_ITEMP(op1) &&
1092         sym2->isspilt  &&
1093         sym1->level > 0 &&
1094         (sym2->usl.spillLoc == sym1))
1095         return TRUE ;
1096
1097     return FALSE ;
1098 }
1099
1100 /*-----------------------------------------------------------------*/
1101 /* pic16_sameRegs - two asmops have the same registers                   */
1102 /*-----------------------------------------------------------------*/
1103 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1104 {
1105     int i;
1106
1107     if (aop1 == aop2)
1108         return TRUE ;
1109
1110     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1111                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1112
1113     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1114
1115     if (aop1->type != AOP_REG ||
1116         aop2->type != AOP_REG )
1117         return FALSE ;
1118
1119     /* This is a bit too restrictive if one is a subset of the other...
1120     if (aop1->size != aop2->size )
1121         return FALSE ;
1122     */
1123
1124     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1125 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1126
1127 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1128         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1129             return FALSE ;
1130     }
1131
1132     return TRUE ;
1133 }
1134
1135 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1136 {
1137     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1138                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1139
1140     if(aop1 == aop2)return TRUE;
1141     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1142       
1143       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1144     
1145   return TRUE;
1146 }
1147
1148
1149 /*-----------------------------------------------------------------*/
1150 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1151 /*-----------------------------------------------------------------*/
1152 void pic16_aopOp (operand *op, iCode *ic, bool result)
1153 {
1154     asmop *aop;
1155     symbol *sym;
1156     int i;
1157
1158     if (!op)
1159         return ;
1160
1161     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1162
1163     /* if this a literal */
1164     if (IS_OP_LITERAL(op)) {
1165         op->aop = aop = newAsmop(AOP_LIT);
1166         aop->aopu.aop_lit = op->operand.valOperand;
1167         aop->size = getSize(operandType(op));
1168         return;
1169     }
1170
1171     {
1172       sym_link *type = operandType(op);
1173 #if 0
1174       if(IS_PTR_CONST(type))
1175 #else
1176       if(IS_CODEPTR(type))
1177 #endif
1178         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1179     }
1180
1181     /* if already has a asmop then continue */
1182     if (op->aop)
1183         return ;
1184
1185     /* if the underlying symbol has a aop */
1186     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1187       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1188         op->aop = OP_SYMBOL(op)->aop;
1189         return;
1190     }
1191
1192     /* if this is a true symbol */
1193     if (IS_TRUE_SYMOP(op)) {    
1194         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1195       op->aop = aopForSym(ic, op, result);
1196       return ;
1197     }
1198
1199     /* this is a temporary : this has
1200     only four choices :
1201     a) register
1202     b) spillocation
1203     c) rematerialize 
1204     d) conditional   
1205     e) can be a return use only */
1206
1207     sym = OP_SYMBOL(op);
1208
1209     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1210     /* if the type is a conditional */
1211     if (sym->regType == REG_CND) {
1212         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1213         aop->size = 0;
1214         return;
1215     }
1216
1217     /* if it is spilt then two situations
1218     a) is rematerialize 
1219     b) has a spill location */
1220     if (sym->isspilt || sym->nRegs == 0) {
1221
1222 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1223       DEBUGpic16_emitcode(";","%d",__LINE__);
1224         /* rematerialize it NOW */
1225         if (sym->remat) {
1226
1227             sym->aop = op->aop = aop = aopForRemat (op);
1228 //            aop->size = getSize(sym->type);
1229 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1230             return;
1231         }
1232
1233 #if 1
1234         if (sym->accuse) {
1235             int i;
1236             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1237             aop->size = getSize(sym->type);
1238             for ( i = 0 ; i < 1 ; i++ ) {
1239                 aop->aopu.aop_str[i] = accUse[i];
1240 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1241             }
1242             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1243             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1244             return;  
1245         }
1246 #endif
1247
1248 #if 1
1249         if (sym->ruonly) {
1250           /*
1251           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1252           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1253           //pic16_allocDirReg (IC_LEFT(ic));
1254           aop->size = getSize(sym->type);
1255           */
1256
1257           unsigned i;
1258
1259           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1260           aop->size = getSize(sym->type);
1261           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1262             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1263
1264           DEBUGpic16_emitcode(";","%d",__LINE__);
1265           return;
1266         }
1267 #endif
1268         /* else spill location  */
1269         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1270             /* force a new aop if sizes differ */
1271             sym->usl.spillLoc->aop = NULL;
1272         }
1273
1274 #if 0
1275         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1276                             __FUNCTION__,__LINE__,
1277                             sym->usl.spillLoc->rname,
1278                             sym->rname, sym->usl.spillLoc->offset);
1279 #endif
1280
1281         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1282         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1283         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1284           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1285                                                   getSize(sym->type), 
1286                                                   sym->usl.spillLoc->offset, op);
1287         } else {
1288           fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
1289           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1290           assert (getSize(sym->type) <= 1);
1291           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1292         }
1293         aop->size = getSize(sym->type);
1294
1295         return;
1296     }
1297
1298     {
1299       sym_link *type = operandType(op);
1300 #if 0
1301       if(IS_PTR_CONST(type)) 
1302 #else
1303       if(IS_CODEPTR(type)) 
1304 #endif
1305         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1306     }
1307
1308     /* must be in a register */
1309     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1310     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1311     aop->size = sym->nRegs;
1312     for ( i = 0 ; i < sym->nRegs ;i++)
1313         aop->aopu.aop_reg[i] = sym->regs[i];
1314 }
1315
1316 /*-----------------------------------------------------------------*/
1317 /* pic16_freeAsmop - free up the asmop given to an operand               */
1318 /*----------------------------------------------------------------*/
1319 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1320 {   
1321     asmop *aop ;
1322
1323     if (!op)
1324         aop = aaop;
1325     else 
1326         aop = op->aop;
1327
1328     if (!aop)
1329         return ;
1330
1331     if (aop->freed)
1332         goto dealloc; 
1333
1334     aop->freed = 1;
1335
1336     /* depending on the asmop type only three cases need work AOP_RO
1337        , AOP_R1 && AOP_STK */
1338 #if 1
1339     switch (aop->type) {
1340         case AOP_FSR0 :
1341             if (_G.fsr0Pushed ) {
1342                 if (pop) {
1343                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1344                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1345 //                    pic16_emitcode ("pop","ar0");
1346                     _G.fsr0Pushed--;
1347                 }
1348             }
1349             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1350             break;
1351
1352         case AOP_FSR2 :
1353             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1354             break;
1355
1356         case AOP_R0 :
1357             if (_G.r0Pushed ) {
1358                 if (pop) {
1359                     pic16_emitcode ("pop","ar0");     
1360                     _G.r0Pushed--;
1361                 }
1362             }
1363             bitVectUnSetBit(ic->rUsed,R0_IDX);
1364             break;
1365
1366         case AOP_R1 :
1367             if (_G.r1Pushed ) {
1368                 if (pop) {
1369                     pic16_emitcode ("pop","ar1");
1370                     _G.r1Pushed--;
1371                 }
1372             }
1373             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1374             break;
1375
1376         case AOP_STA:
1377           {
1378             int i;
1379
1380               /* we must store the result on stack */
1381               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1382                 // operands on stack are accessible via "FSR2 + index" with index
1383                 // starting at 2 for arguments and growing from 0 downwards for
1384                 // local variables (index == 0 is not assigned so we add one here)
1385                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1386                 if (soffs <= 0) {
1387                   assert (soffs < 0);
1388                   soffs++;
1389                 } // if
1390                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1391                 for(i=0;i<aop->size;i++) {
1392                   /* initialise for stack access via frame pointer */
1393                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1394                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1395                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1396                 }
1397         
1398                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1399               }
1400
1401               if(!_G.resDirect) {
1402                 for(i=0;i<aop->size;i++) {
1403                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1404
1405                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx))
1406                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1407                 }
1408                   
1409               }
1410               _G.resDirect = 0;
1411           }
1412           break;
1413 #if 0
1414         case AOP_STK :
1415         {
1416             int sz = aop->size;    
1417             int stk = aop->aopu.aop_stk + aop->size;
1418             bitVectUnSetBit(ic->rUsed,R0_IDX);
1419             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1420
1421             getFreePtr(ic,&aop,FALSE);
1422             
1423             if (options.stack10bit)
1424             {
1425                 /* I'm not sure what to do here yet... */
1426                 /* #STUB */
1427                 fprintf(stderr, 
1428                         "*** Warning: probably generating bad code for "
1429                         "10 bit stack mode.\n");
1430             }
1431             
1432             if (stk) {
1433                 pic16_emitcode ("mov","a,_bp");
1434                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1435                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1436             } else {
1437                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1438             }
1439
1440             while (sz--) {
1441                 pic16_emitcode("pop","acc");
1442                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1443                 if (!sz) break;
1444                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1445             }
1446             op->aop = aop;
1447             pic16_freeAsmop(op,NULL,ic,TRUE);
1448             if (_G.r0Pushed) {
1449                 pic16_emitcode("pop","ar0");
1450                 _G.r0Pushed--;
1451             }
1452
1453             if (_G.r1Pushed) {
1454                 pic16_emitcode("pop","ar1");
1455                 _G.r1Pushed--;
1456             }       
1457         }
1458 #endif
1459
1460     }
1461 #endif
1462
1463 dealloc:
1464     /* all other cases just dealloc */
1465     if (op ) {
1466         op->aop = NULL;
1467         if (IS_SYMOP(op)) {
1468             OP_SYMBOL(op)->aop = NULL;    
1469             /* if the symbol has a spill */
1470             if (SPIL_LOC(op))
1471                 SPIL_LOC(op)->aop = NULL;
1472         }
1473     }
1474 }
1475
1476 /*-----------------------------------------------------------------*/
1477 /* pic16_aopGet - for fetching value of the aop                          */
1478 /*-----------------------------------------------------------------*/
1479 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1480 {
1481     char *s = buffer ;
1482     char *rs;
1483
1484     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1485
1486     /* offset is greater than size then zero */
1487     if (offset > (aop->size - 1) &&
1488         aop->type != AOP_LIT)
1489         return zero;
1490
1491     /* depending on type */
1492     switch (aop->type) {
1493
1494     case AOP_FSR0:
1495     case AOP_FSR2:
1496       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1497       rs = Safe_calloc(1, strlen(s)+1);
1498       strcpy(rs, s);
1499       return (rs);
1500       
1501 #if 0
1502       /* if we need to increment it */
1503       while (offset > aop->coff)
1504         {
1505           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1506           aop->coff++;
1507         }
1508
1509       while (offset < aop->coff)
1510         {
1511           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1512           aop->coff--;
1513         }
1514       aop->coff = offset;
1515       if (aop->paged)
1516         {
1517           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1518           return (dname ? "acc" : "a");
1519         }
1520       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1521       rs = Safe_calloc (1, strlen (s) + 1);
1522       strcpy (rs, s);
1523       return rs;
1524 #endif
1525
1526         
1527     case AOP_IMMD:
1528         if (bit16) 
1529             sprintf (s,"%s",aop->aopu.aop_immd);
1530         else
1531             if (offset) 
1532                 sprintf(s,"(%s >> %d)",
1533                         aop->aopu.aop_immd,
1534                         offset*8);
1535             else
1536                 sprintf(s,"%s",
1537                         aop->aopu.aop_immd);
1538         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1539         rs = Safe_calloc(1,strlen(s)+1);
1540         strcpy(rs,s);   
1541         return rs;
1542         
1543     case AOP_DIR:
1544       if (offset) {
1545         sprintf(s,"(%s + %d)",
1546                 aop->aopu.aop_dir,
1547                 offset);
1548         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1549       } else
1550             sprintf(s,"%s",aop->aopu.aop_dir);
1551         rs = Safe_calloc(1,strlen(s)+1);
1552         strcpy(rs,s);   
1553         return rs;
1554         
1555     case AOP_REG:
1556       //if (dname) 
1557       //    return aop->aopu.aop_reg[offset]->dname;
1558       //else
1559             return aop->aopu.aop_reg[offset]->name;
1560         
1561     case AOP_CRY:
1562       //pic16_emitcode(";","%d",__LINE__);
1563       return aop->aopu.aop_dir;
1564         
1565     case AOP_ACC:
1566         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1567 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1568 //        assert( 0 );
1569 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1570         rs = Safe_strdup("WREG");
1571         return (rs);
1572
1573     case AOP_LIT:
1574         sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1575         rs = Safe_calloc(1,strlen(s)+1);
1576         strcpy(rs,s);   
1577         return rs;
1578         
1579     case AOP_STR:
1580         aop->coff = offset ;
1581
1582 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1583 //          dname)
1584 //          return "acc";
1585         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1586           aop->type = AOP_ACC;
1587           return Safe_strdup("WREG");
1588         }
1589         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1590         
1591         return aop->aopu.aop_str[offset];
1592         
1593     case AOP_PCODE:
1594       {
1595         pCodeOp *pcop = aop->aopu.pcop;
1596         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1597         if(pcop->name) {
1598           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1599           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1600           if (offset) {
1601             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1602           } else {
1603             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1604           }
1605         } else
1606           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1607
1608       }
1609       rs = Safe_calloc(1,strlen(s)+1);
1610       strcpy(rs,s);   
1611       return rs;
1612
1613 #if 0
1614     case AOP_PAGED:
1615       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1616       if (offset) {
1617         sprintf(s,"(%s + %d)",
1618                 aop->aopu.aop_dir,
1619                 offset);
1620       } else
1621             sprintf(s,"%s",aop->aopu.aop_dir);
1622       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1623       rs = Safe_calloc(1,strlen(s)+1);
1624       strcpy(rs,s);   
1625       return rs;
1626 #endif
1627
1628     case AOP_STA:
1629         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1630         return (rs);
1631         
1632     case AOP_STK:
1633 //        pCodeOp *pcop = aop->aop
1634         break;
1635
1636     }
1637
1638     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1639     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1640            "aopget got unsupported aop->type");
1641     exit(0);
1642 }
1643
1644
1645
1646 /* lock has the following meaning: When allocating temporary registers
1647  * for stack variables storage, the value of the temporary register is
1648  * saved on stack. Its value is restored at the end. This procedure is
1649  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1650  * a possibility that before a call to pic16_aopOp, a temporary register
1651  * is allocated for a while and it is freed after some time, this will
1652  * mess the stack and values will not be restored properly. So use lock=1
1653  * to allocate temporary registers used internally by the programmer, and
1654  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1655  * to inform the compiler developer about a possible bug. This is an internal
1656  * feature for developing the compiler -- VR */
1657  
1658 int _TempReg_lock = 0;
1659 /*-----------------------------------------------------------------*/
1660 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1661 /*-----------------------------------------------------------------*/
1662 pCodeOp *pic16_popGetTempReg(int lock)
1663 {
1664   pCodeOp *pcop;
1665   symbol *cfunc;
1666
1667 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1668     if(_TempReg_lock) {
1669 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1670     }
1671     
1672     _TempReg_lock += lock;
1673     
1674     cfunc = currFunc;
1675     currFunc = NULL;
1676
1677     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1678     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1679       PCOR(pcop)->r->wasUsed=1;
1680       PCOR(pcop)->r->isFree=0;
1681
1682       /* push value on stack */
1683       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1684     }
1685
1686     currFunc = cfunc;
1687
1688   return pcop;
1689 }
1690
1691 /*-----------------------------------------------------------------*/
1692 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1693 /*                           is not part of f, but don't save if   */
1694 /*                           inside v                              */
1695 /*-----------------------------------------------------------------*/
1696 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1697 {
1698   pCodeOp *pcop=NULL;
1699   symbol *cfunc;
1700   int i;
1701
1702 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1703
1704     if(_TempReg_lock) {
1705 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1706     }
1707
1708     _TempReg_lock += lock;
1709
1710     cfunc = currFunc;
1711     currFunc = NULL;
1712
1713     i = bitVectFirstBit(f);
1714     while(i < 128) {
1715
1716       /* bypass registers that are used by function */
1717       if(!bitVectBitValue(f, i)) {
1718       
1719         /* bypass registers that are already allocated for stack access */
1720         if(!bitVectBitValue(v, i))  {
1721         
1722 //          debugf("getting register rIdx = %d\n", i);
1723           /* ok, get the operand */
1724           pcop = pic16_newpCodeOpReg( i );
1725     
1726           /* should never by NULL */
1727           assert( pcop != NULL );
1728
1729           
1730           /* sanity check */
1731           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1732             int found=0;
1733             
1734               PCOR(pcop)->r->wasUsed=1;
1735               PCOR(pcop)->r->isFree=0;
1736
1737
1738               {
1739                 regs *sr;
1740               
1741                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1742
1743                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1744                       /* already used in previous steps, break */
1745                       found=1;          
1746                       break;
1747                     }
1748                   }
1749               }
1750
1751               /* caller takes care of the following */
1752 //              bitVectSetBit(v, i);
1753
1754               if(!found) {
1755                 /* push value on stack */
1756                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1757                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1758               }
1759           
1760             break;
1761           }
1762         }
1763       }
1764       i++;
1765     }
1766
1767     currFunc = cfunc;
1768
1769   return pcop;
1770 }
1771
1772
1773 /*-----------------------------------------------------------------*/
1774 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1775 /*-----------------------------------------------------------------*/
1776 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1777 {
1778   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1779
1780   _TempReg_lock -= lock;
1781
1782   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1783     PCOR(pcop)->r->isFree = 1;
1784
1785     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1786   }
1787 }
1788 /*-----------------------------------------------------------------*/
1789 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1790 /*-----------------------------------------------------------------*/
1791 pCodeOp *pic16_popGetLabel(unsigned int key)
1792 {
1793
1794   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1795
1796   if(key>max_key)
1797     max_key = key;
1798
1799   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1800 }
1801
1802 /*-----------------------------------------------------------------*/
1803 /* pic16_popCopyReg - copy a pcode operator                              */
1804 /*-----------------------------------------------------------------*/
1805 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1806 {
1807   pCodeOpReg *pcor;
1808
1809   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1810   memcpy (pcor, pc, sizeof (pCodeOpReg));
1811   pcor->r->wasUsed = 1;
1812   
1813   //pcor->pcop.type = pc->pcop.type;
1814   if(pc->pcop.name) {
1815     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1816       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1817   } else
1818     pcor->pcop.name = NULL;
1819
1820   //pcor->r = pc->r;
1821   //pcor->rIdx = pc->rIdx;
1822   //pcor->r->wasUsed=1;
1823   //pcor->instance = pc->instance;
1824
1825 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1826
1827   return PCOP(pcor);
1828 }
1829
1830 /*-----------------------------------------------------------------*/
1831 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1832 /*-----------------------------------------------------------------*/
1833 pCodeOp *pic16_popGetLit(int lit)
1834 {
1835   return pic16_newpCodeOpLit(lit);
1836 }
1837
1838 /*-----------------------------------------------------------------*/
1839 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1840 /*-----------------------------------------------------------------*/
1841 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1842 {
1843   return pic16_newpCodeOpLit2(lit, arg2);
1844 }
1845
1846
1847 /*-----------------------------------------------------------------*/
1848 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1849 /*-----------------------------------------------------------------*/
1850 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1851 {
1852   return pic16_newpCodeOpImmd(name, offset,index, 0);
1853 }
1854
1855
1856 /*-----------------------------------------------------------------*/
1857 /* pic16_popGet - asm operator to pcode operator conversion              */
1858 /*-----------------------------------------------------------------*/
1859 pCodeOp *pic16_popGetWithString(char *str)
1860 {
1861   pCodeOp *pcop;
1862
1863
1864   if(!str) {
1865     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1866     exit (1);
1867   }
1868
1869   pcop = pic16_newpCodeOp(str,PO_STR);
1870
1871   return pcop;
1872 }
1873
1874 /*-----------------------------------------------------------------*/
1875 /* pic16_popRegFromString -                                        */
1876 /*-----------------------------------------------------------------*/
1877 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1878 {
1879
1880   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1881   pcop->type = PO_DIR;
1882
1883   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1884   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1885
1886   if(!str)
1887     str = "BAD_STRING";
1888
1889   pcop->name = Safe_calloc(1,strlen(str)+1);
1890   strcpy(pcop->name,str);
1891
1892   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1893
1894   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1895
1896   /* make sure that register doesn't exist,
1897    * and operand isn't NULL
1898    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1899   if((PCOR(pcop)->r == NULL) 
1900     && (op)
1901     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1902 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1903 //              __FUNCTION__, __LINE__, str, size, offset);
1904
1905     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1906     fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1907
1908   }
1909   PCOR(pcop)->instance = offset;
1910
1911   return pcop;
1912 }
1913
1914 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1915 {
1916   pCodeOp *pcop;
1917
1918 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1919
1920         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1921         PCOR(pcop)->rIdx = rIdx;
1922         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1923
1924         PCOR(pcop)->r->isFree = 0;
1925         PCOR(pcop)->r->wasUsed = 1;
1926
1927         pcop->type = PCOR(pcop)->r->pc_type;
1928
1929   return pcop;
1930 }
1931
1932 /*---------------------------------------------------------------------------------*/
1933 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1934 /*                 VR 030601                                                       */
1935 /*---------------------------------------------------------------------------------*/
1936 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1937 {
1938   pCodeOpReg2 *pcop2;
1939   pCodeOp *temp;
1940   
1941         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1942
1943         /* comment the following check, so errors to throw up */
1944 //      if(!pcop2)return NULL;
1945
1946         temp = pic16_popGet(aop_dst, offset);
1947         pcop2->pcop2 = temp;
1948         
1949   return PCOP(pcop2);
1950 }
1951
1952
1953
1954 /*--------------------------------------------------------------------------------.-*/
1955 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1956 /*                  VR 030601 , adapted by Hans Dorn                                */
1957 /*--------------------------------------------------------------------------------.-*/
1958 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1959 {
1960   pCodeOpReg2 *pcop2;
1961  
1962         pcop2 = (pCodeOpReg2 *)src;
1963         pcop2->pcop2 = dst;
1964         
1965         return PCOP(pcop2);
1966 }
1967
1968
1969
1970 /*---------------------------------------------------------------------------------*/
1971 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1972 /*                     movff instruction                                           */
1973 /*---------------------------------------------------------------------------------*/
1974 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1975 {
1976   pCodeOpReg2 *pcop2;
1977
1978         if(!noalloc) {
1979                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1980                 pcop2->pcop2 = pic16_popCopyReg(dst);
1981         } else {
1982                 /* the pCodeOp may be already allocated */
1983                 pcop2 = (pCodeOpReg2 *)(src);
1984                 pcop2->pcop2 = (pCodeOp *)(dst);
1985         }
1986
1987   return PCOP(pcop2);
1988 }
1989
1990
1991 /*-----------------------------------------------------------------*/
1992 /* pic16_popGet - asm operator to pcode operator conversion              */
1993 /*-----------------------------------------------------------------*/
1994 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1995 {
1996   //char *s = buffer ;
1997   char *rs;
1998   pCodeOp *pcop;
1999
2000     FENTRY2;
2001     /* offset is greater than
2002     size then zero */
2003
2004 //    if (offset > (aop->size - 1) &&
2005 //        aop->type != AOP_LIT)
2006 //      return NULL;  //zero;
2007
2008     /* depending on type */
2009     switch (aop->type) {
2010         
2011     case AOP_R0:
2012     case AOP_R1:
2013     case AOP_DPTR:
2014     case AOP_DPTR2:
2015         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2016         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2017         assert( 0 );
2018         return NULL;
2019
2020
2021     case AOP_FSR0:
2022     case AOP_FSR2:
2023       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2024       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
2025       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2026       PCOR(pcop)->r->wasUsed = 1;
2027       PCOR(pcop)->r->isFree = 0;
2028       
2029       PCOR(pcop)->instance = offset;
2030       pcop->type = PCOR(pcop)->r->pc_type;
2031       return (pcop);
2032
2033     case AOP_IMMD:
2034       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2035       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2036
2037     case AOP_STA:
2038       /* pCodeOp is already allocated from aopForSym */
2039         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2040         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2041           
2042       return (pcop);
2043       
2044     case AOP_ACC:
2045       {
2046         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
2047
2048         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2049
2050         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2051         
2052         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2053         PCOR(pcop)->rIdx = rIdx;
2054         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2055         PCOR(pcop)->r->wasUsed=1;
2056         PCOR(pcop)->r->isFree=0;
2057
2058         PCOR(pcop)->instance = offset;
2059         pcop->type = PCOR(pcop)->r->pc_type;
2060 //      rs = aop->aopu.aop_reg[offset]->name;
2061 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2062         return pcop;
2063
2064
2065 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2066 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2067
2068 //      assert( 0 );
2069       }
2070         
2071     case AOP_DIR:
2072       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2073       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2074         
2075 #if 0
2076     case AOP_PAGED:
2077       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2078       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2079 #endif
2080
2081     case AOP_REG:
2082       {
2083         int rIdx;
2084         assert (aop && aop->aopu.aop_reg[offset] != NULL);
2085         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2086
2087         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2088         
2089         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2090 //      pcop->type = PO_GPR_REGISTER;
2091         PCOR(pcop)->rIdx = rIdx;
2092         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
2093         PCOR(pcop)->r->wasUsed=1;
2094         PCOR(pcop)->r->isFree=0;
2095
2096         PCOR(pcop)->instance = offset;
2097         pcop->type = PCOR(pcop)->r->pc_type;
2098         
2099         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2100         rs = aop->aopu.aop_reg[offset]->name;
2101         DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2102         return pcop;
2103       }
2104
2105     case AOP_CRY:
2106         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2107
2108       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2109       PCOR(pcop)->instance = offset;
2110       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2111       //if(PCOR(pcop)->r == NULL)
2112       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2113       return pcop;
2114         
2115     case AOP_LIT:
2116         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2117       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2118
2119     case AOP_STR:
2120       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2121       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2122
2123       /*
2124       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2125       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2126       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2127       pcop->type = PCOR(pcop)->r->pc_type;
2128       pcop->name = PCOR(pcop)->r->name;
2129
2130       return pcop;
2131       */
2132
2133     case AOP_PCODE:
2134       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2135                           __LINE__, 
2136                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2137       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2138       switch( aop->aopu.pcop->type ) {
2139         case PO_DIR: PCOR(pcop)->instance += offset; break;
2140         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2141         case PO_WREG:
2142             assert (offset==0);
2143             break;
2144         default:
2145           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2146           assert( 0 );  /* should never reach here */;
2147       }
2148       return pcop;
2149     }
2150
2151     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2152            "pic16_popGet got unsupported aop->type");
2153     exit(0);
2154 }
2155 /*-----------------------------------------------------------------*/
2156 /* pic16_aopPut - puts a string for a aop                                */
2157 /*-----------------------------------------------------------------*/
2158 void pic16_aopPut (asmop *aop, char *s, int offset)
2159 {
2160     char *d = buffer ;
2161     symbol *lbl ;
2162
2163     return;
2164
2165     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2166
2167     if (aop->size && offset > ( aop->size - 1)) {
2168         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2169                "pic16_aopPut got offset > aop->size");
2170         exit(0);
2171     }
2172
2173     /* will assign value to value */
2174     /* depending on where it is ofcourse */
2175     switch (aop->type) {
2176     case AOP_DIR:
2177       if (offset) {
2178         sprintf(d,"(%s + %d)",
2179                 aop->aopu.aop_dir,offset);
2180         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2181
2182       } else
2183             sprintf(d,"%s",aop->aopu.aop_dir);
2184         
2185         if (strcmp(d,s)) {
2186           DEBUGpic16_emitcode(";","%d",__LINE__);
2187           if(strcmp(s,"W"))
2188             pic16_emitcode("movf","%s,w",s);
2189           pic16_emitcode("movwf","%s",d);
2190
2191           if(strcmp(s,"W")) {
2192             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2193             if(offset >= aop->size) {
2194               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2195               break;
2196             } else
2197               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2198           }
2199
2200           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2201
2202
2203         }
2204         break;
2205         
2206     case AOP_REG:
2207       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2208         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2209           /*
2210             if (*s == '@'           ||
2211                 strcmp(s,"r0") == 0 ||
2212                 strcmp(s,"r1") == 0 ||
2213                 strcmp(s,"r2") == 0 ||
2214                 strcmp(s,"r3") == 0 ||
2215                 strcmp(s,"r4") == 0 ||
2216                 strcmp(s,"r5") == 0 ||
2217                 strcmp(s,"r6") == 0 || 
2218                 strcmp(s,"r7") == 0 )
2219                 pic16_emitcode("mov","%s,%s  ; %d",
2220                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2221             else
2222           */
2223
2224           if(strcmp(s,"W")==0 )
2225             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2226
2227           pic16_emitcode("movwf","%s",
2228                    aop->aopu.aop_reg[offset]->name);
2229
2230           if(strcmp(s,zero)==0) {
2231             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2232
2233           } else if(strcmp(s,"W")==0) {
2234             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2235             pcop->type = PO_GPR_REGISTER;
2236
2237             PCOR(pcop)->rIdx = -1;
2238             PCOR(pcop)->r = NULL;
2239
2240             DEBUGpic16_emitcode(";","%d",__LINE__);
2241             pcop->name = Safe_strdup(s);
2242             pic16_emitpcode(POC_MOVFW,pcop);
2243             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2244           } else if(strcmp(s,one)==0) {
2245             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2246             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2247           } else {
2248             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2249           }
2250         }
2251         break;
2252         
2253     case AOP_DPTR:
2254     case AOP_DPTR2:
2255     
2256     if (aop->type == AOP_DPTR2)
2257     {
2258         genSetDPTR(1);
2259     }
2260     
2261         if (aop->code) {
2262             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2263                    "pic16_aopPut writting to code space");
2264             exit(0);
2265         }
2266         
2267         while (offset > aop->coff) {
2268             aop->coff++;
2269             pic16_emitcode ("inc","dptr");
2270         }
2271         
2272         while (offset < aop->coff) {
2273             aop->coff-- ;
2274             pic16_emitcode("lcall","__decdptr");
2275         }
2276         
2277         aop->coff = offset;
2278         
2279         /* if not in accumulater */
2280         MOVA(s);        
2281         
2282         pic16_emitcode ("movx","@dptr,a");
2283         
2284     if (aop->type == AOP_DPTR2)
2285     {
2286         genSetDPTR(0);
2287     }
2288         break;
2289         
2290     case AOP_R0:
2291     case AOP_R1:
2292         while (offset > aop->coff) {
2293             aop->coff++;
2294             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2295         }
2296         while (offset < aop->coff) {
2297             aop->coff-- ;
2298             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2299         }
2300         aop->coff = offset;
2301         
2302         if (aop->paged) {
2303             MOVA(s);           
2304             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2305             
2306         } else
2307             if (*s == '@') {
2308                 MOVA(s);
2309                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2310             } else
2311                 if (strcmp(s,"r0") == 0 ||
2312                     strcmp(s,"r1") == 0 ||
2313                     strcmp(s,"r2") == 0 ||
2314                     strcmp(s,"r3") == 0 ||
2315                     strcmp(s,"r4") == 0 ||
2316                     strcmp(s,"r5") == 0 ||
2317                     strcmp(s,"r6") == 0 || 
2318                     strcmp(s,"r7") == 0 ) {
2319                     char buffer[10];
2320                     sprintf(buffer,"a%s",s);
2321                     pic16_emitcode("mov","@%s,%s",
2322                              aop->aopu.aop_ptr->name,buffer);
2323                 } else
2324                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2325         
2326         break;
2327         
2328     case AOP_STK:
2329         if (strcmp(s,"a") == 0)
2330             pic16_emitcode("push","acc");
2331         else
2332             pic16_emitcode("push","%s",s);
2333         
2334         break;
2335         
2336     case AOP_CRY:
2337         /* if bit variable */
2338         if (!aop->aopu.aop_dir) {
2339             pic16_emitcode("clr","a");
2340             pic16_emitcode("rlc","a");
2341         } else {
2342             if (s == zero) 
2343                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2344             else
2345                 if (s == one)
2346                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2347                 else
2348                     if (!strcmp(s,"c"))
2349                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2350                     else {
2351                         lbl = newiTempLabel(NULL);
2352                         
2353                         if (strcmp(s,"a")) {
2354                             MOVA(s);
2355                         }
2356                         pic16_emitcode("clr","c");
2357                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2358                         pic16_emitcode("cpl","c");
2359                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2360                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2361                     }
2362         }
2363         break;
2364         
2365     case AOP_STR:
2366         aop->coff = offset;
2367         if (strcmp(aop->aopu.aop_str[offset],s))
2368             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2369         break;
2370         
2371     case AOP_ACC:
2372         aop->coff = offset;
2373         if (!offset && (strcmp(s,"acc") == 0))
2374             break;
2375         
2376         if (strcmp(aop->aopu.aop_str[offset],s))
2377             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2378         break;
2379
2380     default :
2381         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2382 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2383 //             "pic16_aopPut got unsupported aop->type");
2384 //      exit(0);    
2385     }    
2386
2387 }
2388
2389 /*-----------------------------------------------------------------*/
2390 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2391 /*-----------------------------------------------------------------*/
2392 void pic16_mov2w (asmop *aop, int offset)
2393 {
2394   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2395
2396   if(is_LitAOp(aop))
2397     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2398   else
2399     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2400 }
2401
2402 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2403 {
2404   if(is_LitAOp(src)) {
2405     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2406     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2407   } else {
2408     if(pic16_sameRegsOfs(src, dst, offset))return;
2409     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2410                       pic16_popGet(dst, offset)));
2411   }
2412 }
2413
2414 static void pic16_movLit2f(pCodeOp *pc, int lit)
2415 {
2416   if (0 == (lit & 0x00ff))
2417   {
2418     pic16_emitpcode (POC_CLRF, pc);
2419   } else if (0xff == (lit & 0x00ff))
2420   {
2421     pic16_emitpcode (POC_SETF, pc);
2422   } else {
2423     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2424     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2425   }
2426 }
2427
2428 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2429 {
2430   if(is_LitAOp(src)) {
2431     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2432     pic16_emitpcode(POC_MOVWF, dst);
2433   } else {
2434     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2435   }
2436 }
2437
2438 void pic16_testStackOverflow(void)
2439 {
2440 #define GSTACK_TEST_NAME        "_gstack_test"
2441
2442   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2443   
2444   {
2445     symbol *sym;
2446
2447       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2448       sprintf(sym->rname, "%s%s", port->fun_prefix, GSTACK_TEST_NAME);
2449 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2450       checkAddSym(&externs, sym);
2451   }
2452
2453 }
2454
2455 /* push pcop into stack */
2456 void pic16_pushpCodeOp(pCodeOp *pcop)
2457 {
2458 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2459   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));    //&pic16_pc_postdec1)));
2460   if(pic16_options.gstack)
2461     pic16_testStackOverflow();
2462     
2463 }
2464
2465 /* pop pcop from stack */
2466 void pic16_poppCodeOp(pCodeOp *pcop)
2467 {
2468   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2469   if(pic16_options.gstack)
2470     pic16_testStackOverflow();
2471 }
2472
2473
2474 /*-----------------------------------------------------------------*/
2475 /* pushw - pushes wreg to stack                                    */
2476 /*-----------------------------------------------------------------*/
2477 void pushw(void)
2478 {
2479   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2480   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2481   if(pic16_options.gstack)
2482     pic16_testStackOverflow();
2483 }
2484
2485                 
2486 /*-----------------------------------------------------------------*/
2487 /* pushaop - pushes aop to stack                                   */
2488 /*-----------------------------------------------------------------*/
2489 void pushaop(asmop *aop, int offset)
2490 {
2491   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2492
2493   if(is_LitAOp(aop)) {
2494     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2495     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2496   } else {
2497     pic16_emitpcode(POC_MOVFF,
2498       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2499   }
2500
2501   if(pic16_options.gstack)
2502     pic16_testStackOverflow();
2503 }
2504
2505 /*-----------------------------------------------------------------*/
2506 /* popaop - pops aop from stack                                    */
2507 /*-----------------------------------------------------------------*/
2508 void popaop(asmop *aop, int offset)
2509 {
2510   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2511   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2512   if(pic16_options.gstack)
2513     pic16_testStackOverflow();
2514 }
2515
2516 void popaopidx(asmop *aop, int offset, int index)
2517 {
2518   int ofs=1;
2519
2520     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2521
2522     if(STACK_MODEL_LARGE)ofs++;
2523
2524     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2525     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2526     if(pic16_options.gstack)
2527       pic16_testStackOverflow();
2528 }
2529
2530 #if !(USE_GENERIC_SIGNED_SHIFT)
2531 /*-----------------------------------------------------------------*/
2532 /* reAdjustPreg - points a register back to where it should        */
2533 /*-----------------------------------------------------------------*/
2534 static void reAdjustPreg (asmop *aop)
2535 {
2536     int size ;
2537
2538     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2539     aop->coff = 0;
2540     if ((size = aop->size) <= 1)
2541         return ;
2542     size-- ;
2543     switch (aop->type) {
2544         case AOP_R0 :
2545         case AOP_R1 :
2546             while (size--)
2547                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2548             break;          
2549         case AOP_DPTR :
2550         case AOP_DPTR2:
2551             if (aop->type == AOP_DPTR2)
2552             {
2553                 genSetDPTR(1);
2554             } 
2555             while (size--)
2556             {
2557                 pic16_emitcode("lcall","__decdptr");
2558             }
2559                 
2560             if (aop->type == AOP_DPTR2)
2561             {
2562                 genSetDPTR(0);
2563             }                
2564             break;  
2565
2566     }   
2567
2568 }
2569 #endif
2570
2571 #if 0
2572 /*-----------------------------------------------------------------*/
2573 /* opIsGptr: returns non-zero if the passed operand is             */   
2574 /* a generic pointer type.                                         */
2575 /*-----------------------------------------------------------------*/ 
2576 static int opIsGptr(operand *op)
2577 {
2578     sym_link *type = operandType(op);
2579     
2580     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2581     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2582     {
2583         return 1;
2584     }
2585     return 0;        
2586 }
2587 #endif
2588
2589 /*-----------------------------------------------------------------*/
2590 /* pic16_getDataSize - get the operand data size                         */
2591 /*-----------------------------------------------------------------*/
2592 int pic16_getDataSize(operand *op)
2593 {
2594     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2595
2596
2597     return AOP_SIZE(op);
2598
2599     // tsd- in the pic port, the genptr size is 1, so this code here
2600     // fails. ( in the 8051 port, the size was 4).
2601 #if 0
2602     int size;
2603     size = AOP_SIZE(op);
2604     if (size == GPTRSIZE)
2605     {
2606         sym_link *type = operandType(op);
2607         if (IS_GENPTR(type))
2608         {
2609             /* generic pointer; arithmetic operations
2610              * should ignore the high byte (pointer type).
2611              */
2612             size--;
2613     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2614         }
2615     }
2616     return size;
2617 #endif
2618 }
2619
2620 /*-----------------------------------------------------------------*/
2621 /* pic16_outAcc - output Acc                                             */
2622 /*-----------------------------------------------------------------*/
2623 void pic16_outAcc(operand *result)
2624 {
2625   int size,offset;
2626   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2627   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2628
2629
2630   size = pic16_getDataSize(result);
2631   if(size){
2632     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2633     size--;
2634     offset = 1;
2635     /* unsigned or positive */
2636     while(size--)
2637       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2638   }
2639
2640 }
2641
2642 /*-----------------------------------------------------------------*/
2643 /* pic16_outBitC - output a bit C                                  */
2644 /*                 Move to result the value of Carry flag -- VR    */
2645 /*-----------------------------------------------------------------*/
2646 void pic16_outBitC(operand *result)
2647 {
2648   int i;
2649
2650     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2651
2652     /* if the result is bit */
2653     if (AOP_TYPE(result) == AOP_CRY) {
2654         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2655         pic16_aopPut(AOP(result),"c",0);
2656     } else {
2657
2658         i = AOP_SIZE(result);
2659         while(i--) {
2660                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2661         }
2662         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2663     }
2664 }
2665
2666 /*-----------------------------------------------------------------*/
2667 /* pic16_outBitOp - output a bit from Op                           */
2668 /*                 Move to result the value of set/clr op -- VR    */
2669 /*-----------------------------------------------------------------*/
2670 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2671 {
2672   int i;
2673
2674     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2675
2676     /* if the result is bit */
2677     if (AOP_TYPE(result) == AOP_CRY) {
2678         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2679         pic16_aopPut(AOP(result),"c",0);
2680     } else {
2681
2682         i = AOP_SIZE(result);
2683         while(i--) {
2684                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2685         }
2686         pic16_emitpcode(POC_RRCF, pcop);          
2687         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2688     }
2689 }
2690
2691 /*-----------------------------------------------------------------*/
2692 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2693 /*-----------------------------------------------------------------*/
2694 void pic16_toBoolean(operand *oper)
2695 {
2696     int size = AOP_SIZE(oper) - 1;
2697     int offset = 1;
2698
2699     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2700
2701     if ( AOP_TYPE(oper) != AOP_ACC) {
2702       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2703     }
2704     while (size--) {
2705       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2706     }
2707 }
2708
2709 /*-----------------------------------------------------------------*/
2710 /* genUminusFloat - unary minus for floating points                */
2711 /*-----------------------------------------------------------------*/
2712 static void genUminusFloat(operand *op,operand *result)
2713 {
2714   int size ,offset =0 ;
2715   
2716     FENTRY;
2717     /* for this we just need to flip the 
2718     first it then copy the rest in place */
2719     size = AOP_SIZE(op);
2720     assert( size == AOP_SIZE(result) );
2721
2722     while(size--) {
2723       pic16_mov2f(AOP(result), AOP(op), offset);
2724       offset++;
2725     }
2726     
2727     /* toggle the MSB's highest bit */
2728     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2729 }
2730
2731 /*-----------------------------------------------------------------*/
2732 /* genUminus - unary minus code generation                         */
2733 /*-----------------------------------------------------------------*/
2734 static void genUminus (iCode *ic)
2735 {
2736   int size, i;
2737   sym_link *optype, *rtype;
2738   symbol *label;
2739   int needLabel=0;
2740
2741     FENTRY;     
2742     
2743     /* assign asmops */
2744     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2745     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2746
2747     /* if both in bit space then special case */
2748     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2749       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2750         
2751         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2752         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2753         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2754         goto release; 
2755     } 
2756
2757     optype = operandType(IC_LEFT(ic));
2758     rtype = operandType(IC_RESULT(ic));
2759
2760
2761     /* if float then do float stuff */
2762     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2763       if(IS_FIXED(optype))
2764         debugf("implement fixed16x16 type\n", 0);
2765         
2766         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2767         goto release;
2768     }
2769
2770     /* otherwise subtract from zero by taking the 2's complement */
2771     size = AOP_SIZE(IC_LEFT(ic));
2772     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2773     label = newiTempLabel ( NULL );
2774     
2775     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2776       for (i=size-1; i > 0; i--) {
2777         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2778       } // for
2779       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2780       for (i=1; i < size; i++) {
2781         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2782         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2783       } // for
2784     } else {
2785       for (i=size-1; i >= 0; i--) {
2786         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2787         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2788       } // for
2789       if (size > 1) {
2790         for (i=0; i < size-2; i++) {
2791           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2792           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2793         } // for
2794         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2795       } // if
2796       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2797     }
2798     if (needLabel)
2799       pic16_emitpLabel (label->key);
2800
2801 release:
2802     /* release the aops */
2803     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2804     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2805 }
2806
2807 #if 0
2808 /*-----------------------------------------------------------------*/
2809 /* saveRegisters - will look for a call and save the registers     */
2810 /*-----------------------------------------------------------------*/
2811 static void saveRegisters(iCode *lic) 
2812 {
2813     int i;
2814     iCode *ic;
2815     bitVect *rsave;
2816     sym_link *dtype;
2817
2818     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2819     /* look for call */
2820     for (ic = lic ; ic ; ic = ic->next) 
2821         if (ic->op == CALL || ic->op == PCALL)
2822             break;
2823
2824     if (!ic) {
2825         fprintf(stderr,"found parameter push with no function call\n");
2826         return ;
2827     }
2828
2829     /* if the registers have been saved already then
2830     do nothing */
2831     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2832         return ;
2833
2834     /* find the registers in use at this time 
2835     and push them away to safety */
2836     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2837                           ic->rUsed);
2838
2839     ic->regsSaved = 1;
2840     if (options.useXstack) {
2841         if (bitVectBitValue(rsave,R0_IDX))
2842             pic16_emitcode("mov","b,r0");
2843         pic16_emitcode("mov","r0,%s",spname);
2844         for (i = 0 ; i < pic16_nRegs ; i++) {
2845             if (bitVectBitValue(rsave,i)) {
2846                 if (i == R0_IDX)
2847                     pic16_emitcode("mov","a,b");
2848                 else
2849                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2850                 pic16_emitcode("movx","@r0,a");
2851                 pic16_emitcode("inc","r0");
2852             }
2853         }
2854         pic16_emitcode("mov","%s,r0",spname);
2855         if (bitVectBitValue(rsave,R0_IDX))
2856             pic16_emitcode("mov","r0,b");           
2857     }// else
2858     //for (i = 0 ; i < pic16_nRegs ; i++) {
2859     //    if (bitVectBitValue(rsave,i))
2860     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2861     //}
2862
2863     dtype = operandType(IC_LEFT(ic));
2864     if (currFunc && dtype && 
2865         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2866         IFFUNC_ISISR(currFunc->type) &&
2867         !ic->bankSaved) 
2868
2869         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2870
2871 }
2872 /*-----------------------------------------------------------------*/
2873 /* unsaveRegisters - pop the pushed registers                      */
2874 /*-----------------------------------------------------------------*/
2875 static void unsaveRegisters (iCode *ic)
2876 {
2877     int i;
2878     bitVect *rsave;
2879
2880     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2881     /* find the registers in use at this time 
2882     and push them away to safety */
2883     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2884                           ic->rUsed);
2885     
2886     if (options.useXstack) {
2887         pic16_emitcode("mov","r0,%s",spname);   
2888         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2889             if (bitVectBitValue(rsave,i)) {
2890                 pic16_emitcode("dec","r0");
2891                 pic16_emitcode("movx","a,@r0");
2892                 if (i == R0_IDX)
2893                     pic16_emitcode("mov","b,a");
2894                 else
2895                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2896             }       
2897
2898         }
2899         pic16_emitcode("mov","%s,r0",spname);
2900         if (bitVectBitValue(rsave,R0_IDX))
2901             pic16_emitcode("mov","r0,b");
2902     } //else
2903     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2904     //    if (bitVectBitValue(rsave,i))
2905     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2906     //}
2907
2908 }  
2909 #endif
2910
2911 #if 0  // patch 14
2912 /*-----------------------------------------------------------------*/
2913 /* pushSide -                                                      */
2914 /*-----------------------------------------------------------------*/
2915 static void pushSide(operand * oper, int size)
2916 {
2917         int offset = 0;
2918     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2919         while (size--) {
2920                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2921                 if (AOP_TYPE(oper) != AOP_REG &&
2922                     AOP_TYPE(oper) != AOP_DIR &&
2923                     strcmp(l,"a") ) {
2924                         pic16_emitcode("mov","a,%s",l);
2925                         pic16_emitcode("push","acc");
2926                 } else
2927                         pic16_emitcode("push","%s",l);
2928         }
2929 }
2930 #endif // patch 14
2931
2932 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2933 {
2934   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2935     pic16_emitpcode(POC_MOVFW, src);
2936     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2937   } else {
2938     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2939         src, pic16_popGet(AOP(op), offset)));
2940   }
2941 }
2942
2943
2944 /*-----------------------------------------------------------------*/
2945 /* assignResultValue - assign results to oper, rescall==1 is       */
2946 /*                     called from genCall() or genPcall()         */
2947 /*-----------------------------------------------------------------*/
2948 static void assignResultValue(operand * oper, int rescall)
2949 {
2950   int size = AOP_SIZE(oper);
2951   int offset=0;
2952   
2953     FENTRY2;
2954 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2955     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2956
2957     if(rescall) {
2958       /* assign result from a call/pcall function() */
2959                 
2960       /* function results are stored in a special order,
2961        * see top of file with Function return policy, or manual */
2962
2963       if(size <= 4) {
2964         /* 8-bits, result in WREG */
2965         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2966                         
2967         if(size>1) {
2968           /* 16-bits, result in PRODL:WREG */
2969           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2970         }
2971                         
2972         if(size>2) {
2973           /* 24-bits, result in PRODH:PRODL:WREG */
2974           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2975         }
2976                         
2977         if(size>3) {
2978           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2979           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2980         }
2981       
2982       } else {
2983         /* >32-bits, result on stack, and FSR0 points to beginning.
2984          * Fix stack when done */
2985         /* FIXME FIXME */
2986 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2987         while (size--) {
2988 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2989 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2990                 
2991           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2992           GpsuedoStkPtr++;
2993         }
2994                         
2995         /* fix stack */
2996         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2997         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2998         if(STACK_MODEL_LARGE) {
2999           emitSKPNC;
3000           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3001         }
3002       }                 
3003     } else {
3004       int areg = 0;             /* matching argument register */
3005       
3006 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3007       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3008
3009
3010       /* its called from genReceive (probably) -- VR */
3011       /* I hope this code will not be called from somewhere else in the future! 
3012        * We manually set the pseudo stack pointer in genReceive. - dw
3013        */
3014       if(!GpsuedoStkPtr && _G.useWreg) {
3015 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3016
3017         /* The last byte in the assignment is in W */
3018         if(areg <= GpsuedoStkPtr) {
3019           size--;
3020           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3021           offset++;
3022 //          debugf("receive from WREG\n", 0);
3023         }
3024         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3025       }
3026 //      GpsuedoStkPtr++;
3027       _G.stack_lat = AOP_SIZE(oper)-1;
3028
3029       while (size) {
3030         size--;
3031         GpsuedoStkPtr++;
3032         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3033 //        debugf("receive from STACK\n", 0);
3034         offset++;
3035       }
3036     }
3037 }
3038
3039
3040 /*-----------------------------------------------------------------*/
3041 /* genIpush - generate code for pushing this gets a little complex */
3042 /*-----------------------------------------------------------------*/
3043 static void genIpush (iCode *ic)
3044 {
3045 //  int size, offset=0;
3046
3047   FENTRY;
3048   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3049
3050   if(ic->parmPush) {
3051     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3052
3053     /* send to stack as normal */
3054     addSet(&_G.sendSet,ic);
3055 //    addSetHead(&_G.sendSet,ic);
3056     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3057   }
3058
3059         
3060 #if 0
3061     int size, offset = 0 ;
3062     char *l;
3063
3064
3065     /* if this is not a parm push : ie. it is spill push 
3066     and spill push is always done on the local stack */
3067     if (!ic->parmPush) {
3068
3069         /* and the item is spilt then do nothing */
3070         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3071             return ;
3072
3073         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3074         size = AOP_SIZE(IC_LEFT(ic));
3075         /* push it on the stack */
3076         while(size--) {
3077             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3078             if (*l == '#') {
3079                 MOVA(l);
3080                 l = "acc";
3081             }
3082             pic16_emitcode("push","%s",l);
3083         }
3084         return ;        
3085     }
3086
3087     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3088 #endif
3089 }
3090
3091 /*-----------------------------------------------------------------*/
3092 /* genIpop - recover the registers: can happen only for spilling   */
3093 /*-----------------------------------------------------------------*/
3094 static void genIpop (iCode *ic)
3095 {
3096   FENTRY;
3097   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3098 #if 0
3099     int size,offset ;
3100
3101
3102     /* if the temp was not pushed then */
3103     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3104         return ;
3105
3106     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3107     size = AOP_SIZE(IC_LEFT(ic));
3108     offset = (size-1);
3109     while (size--) 
3110         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3111                                    FALSE,TRUE));
3112
3113     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3114 #endif
3115 }
3116
3117 #if 0
3118 /*-----------------------------------------------------------------*/
3119 /* unsaverbank - restores the resgister bank from stack            */
3120 /*-----------------------------------------------------------------*/
3121 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3122 {
3123   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3124 #if 0
3125     int i;
3126     asmop *aop ;
3127     regs *r = NULL;
3128
3129     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3130     if (popPsw) {
3131         if (options.useXstack) {
3132             aop = newAsmop(0);
3133             r = getFreePtr(ic,&aop,FALSE);
3134             
3135             
3136             pic16_emitcode("mov","%s,_spx",r->name);
3137             pic16_emitcode("movx","a,@%s",r->name);
3138             pic16_emitcode("mov","psw,a");
3139             pic16_emitcode("dec","%s",r->name);
3140             
3141         }else
3142             pic16_emitcode ("pop","psw");
3143     }
3144
3145     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3146         if (options.useXstack) {       
3147             pic16_emitcode("movx","a,@%s",r->name);
3148             //pic16_emitcode("mov","(%s+%d),a",
3149             //       regspic16[i].base,8*bank+regspic16[i].offset);
3150             pic16_emitcode("dec","%s",r->name);
3151
3152         } else 
3153           pic16_emitcode("pop",""); //"(%s+%d)",
3154         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3155     }
3156
3157     if (options.useXstack) {
3158
3159         pic16_emitcode("mov","_spx,%s",r->name);
3160         pic16_freeAsmop(NULL,aop,ic,TRUE);
3161
3162     }
3163 #endif 
3164 }
3165
3166 /*-----------------------------------------------------------------*/
3167 /* saverbank - saves an entire register bank on the stack          */
3168 /*-----------------------------------------------------------------*/
3169 static void saverbank (int bank, iCode *ic, bool pushPsw)
3170 {
3171   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3172 #if 0
3173     int i;
3174     asmop *aop ;
3175     regs *r = NULL;
3176
3177     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3178     if (options.useXstack) {
3179
3180         aop = newAsmop(0);
3181         r = getFreePtr(ic,&aop,FALSE);  
3182         pic16_emitcode("mov","%s,_spx",r->name);
3183
3184     }
3185
3186     for (i = 0 ; i < pic16_nRegs ;i++) {
3187         if (options.useXstack) {
3188             pic16_emitcode("inc","%s",r->name);
3189             //pic16_emitcode("mov","a,(%s+%d)",
3190             //         regspic16[i].base,8*bank+regspic16[i].offset);
3191             pic16_emitcode("movx","@%s,a",r->name);           
3192         } else 
3193           pic16_emitcode("push","");// "(%s+%d)",
3194                      //regspic16[i].base,8*bank+regspic16[i].offset);
3195     }
3196     
3197     if (pushPsw) {
3198         if (options.useXstack) {
3199             pic16_emitcode("mov","a,psw");
3200             pic16_emitcode("movx","@%s,a",r->name);     
3201             pic16_emitcode("inc","%s",r->name);
3202             pic16_emitcode("mov","_spx,%s",r->name);       
3203             pic16_freeAsmop (NULL,aop,ic,TRUE);
3204             
3205         } else
3206             pic16_emitcode("push","psw");
3207         
3208         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3209     }
3210     ic->bankSaved = 1;
3211 #endif
3212 }
3213 #endif  /* 0 */
3214
3215
3216 static int wparamCmp(void *p1, void *p2)
3217 {
3218   return (!strcmp((char *)p1, (char *)p2));
3219 }
3220
3221 int inWparamList(char *s)
3222 {
3223   return isinSetWith(wparamList, s, wparamCmp);
3224
3225
3226
3227 /*-----------------------------------------------------------------*/
3228 /* genCall - generates a call statement                            */
3229 /*-----------------------------------------------------------------*/
3230 static void genCall (iCode *ic)
3231 {
3232   sym_link *ftype;   
3233   int stackParms=0;
3234   int use_wreg=0;
3235   int inwparam=0;
3236   char *fname;
3237   
3238     FENTRY;
3239
3240     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3241     /* if caller saves & we have not saved then */
3242 //    if (!ic->regsSaved)
3243 //      saveRegisters(ic);
3244
3245         /* initialise stackParms for IPUSH pushes */
3246 //      stackParms = psuedoStkPtr;
3247 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3248     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3249     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3250
3251 #if 0
3252     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3253 #endif
3254
3255     /* if send set is not empty the assign */
3256     if (_G.sendSet) {
3257       iCode *sic;
3258       int psuedoStkPtr=-1; 
3259       int firstTimeThruLoop = 1;
3260
3261
3262         /* reverse sendSet if function is not reentrant */
3263         if(!IFFUNC_ISREENT(ftype))
3264           _G.sendSet = reverseSet(_G.sendSet);
3265
3266         /* First figure how many parameters are getting passed */
3267         stackParms = 0;
3268         use_wreg = 0;
3269         
3270         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3271           int size;
3272 //          int offset = 0;
3273
3274             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3275             size = AOP_SIZE(IC_LEFT(sic));
3276
3277             stackParms += size;
3278
3279             /* pass the last byte through WREG */
3280             if(inwparam) {
3281
3282               while (size--) {
3283                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3284                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3285                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3286
3287                 if(!firstTimeThruLoop) {
3288                   /* If this is not the first time we've been through the loop
3289                    * then we need to save the parameter in a temporary
3290                    * register. The last byte of the last parameter is
3291                    * passed in W. */
3292
3293                   pushw();
3294 //                  --psuedoStkPtr;             // sanity check
3295                   use_wreg = 1;
3296                 }
3297                 
3298                 firstTimeThruLoop=0;
3299
3300                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3301
3302 //                offset++;
3303               }
3304             } else {
3305               /* all arguments are passed via stack */
3306               use_wreg = 0;
3307
3308               while (size--) {
3309                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3310                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3311                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3312
3313 //                pushaop(AOP(IC_LEFT(sic)), size);
3314                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3315
3316                 if(!_G.resDirect)
3317                   pushw();
3318               }
3319             }
3320
3321             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3322           }
3323
3324           if(inwparam) {
3325             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3326               pushw();  /* save last parameter to stack if functions has varargs */
3327               use_wreg = 0;
3328             } else
3329               use_wreg = 1;
3330           } else use_wreg = 0;
3331
3332           _G.stackRegSet = _G.sendSet;
3333           _G.sendSet = NULL;
3334     }
3335
3336     /* make the call */
3337     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3338
3339     GpsuedoStkPtr=0;
3340     
3341     /* if we need to assign a result value */
3342     if ((IS_ITEMP(IC_RESULT(ic))
3343           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3344               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3345         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3346
3347       _G.accInUse++;
3348       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3349       _G.accInUse--;
3350
3351       assignResultValue(IC_RESULT(ic), 1);
3352
3353       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3354                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3355                 
3356       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3357     }
3358
3359     if(!stackParms && ic->parmBytes) {
3360       stackParms = ic->parmBytes;
3361     }
3362       
3363     stackParms -= use_wreg;
3364     
3365     if(stackParms>0) {
3366       if(stackParms == 1) {
3367         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3368       } else {
3369         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3370         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3371       }
3372       if(STACK_MODEL_LARGE) {
3373         emitSKPNC;
3374         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3375       }
3376     }
3377
3378 #if 0
3379     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3380 #endif
3381
3382     /* adjust the stack for parameters if required */
3383 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3384
3385 #if 0
3386       /* if register bank was saved then pop them */
3387       if (ic->bankSaved)
3388         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3389
3390       /* if we hade saved some registers then unsave them */
3391       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3392         unsaveRegisters (ic);
3393 #endif
3394 }
3395
3396
3397
3398 /*-----------------------------------------------------------------*/
3399 /* genPcall - generates a call by pointer statement                */
3400 /*            new version, created from genCall - HJD              */
3401 /*-----------------------------------------------------------------*/
3402 static void genPcall (iCode *ic)
3403 {
3404   sym_link *ftype, *fntype;
3405   int stackParms=0;
3406   symbol *retlbl = newiTempLabel(NULL);
3407   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3408   
3409     FENTRY;
3410
3411     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3412     fntype = operandType( IC_LEFT(ic) )->next;
3413
3414     /* if send set is not empty the assign */
3415     if (_G.sendSet) {
3416       iCode *sic;
3417       int psuedoStkPtr=-1; 
3418
3419       /* reverse sendSet if function is not reentrant */
3420       if(!IFFUNC_ISREENT(fntype))
3421         _G.sendSet = reverseSet(_G.sendSet);
3422
3423       stackParms = 0;
3424       
3425       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3426         int size;
3427
3428           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3429           size = AOP_SIZE(IC_LEFT(sic));
3430           stackParms += size;
3431
3432           /* all parameters are passed via stack, since WREG is clobbered
3433            * by the calling sequence */
3434           while (size--) {
3435             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3436             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3437             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3438
3439             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3440             pushw();
3441           }
3442
3443           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3444       }
3445
3446       _G.stackRegSet = _G.sendSet;
3447       _G.sendSet = NULL;
3448     }
3449
3450     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3451
3452     // push return address
3453     // push $ on return stack, then replace with retlbl
3454
3455     /* Thanks to Thorsten Klose for pointing out that the following
3456      * snippet should be interrupt safe */
3457     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3458     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3459
3460     pic16_emitpcodeNULLop(POC_PUSH);
3461
3462     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3463     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3464     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3465     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3466     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3467     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3468
3469
3470     /* restore interrupt control register */
3471     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3472     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3473
3474     /* make the call by writing the pointer into pc */
3475     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3476     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3477
3478     // note: MOVFF to PCL not allowed
3479     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3480     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3481
3482
3483     /* return address is here: (X) */
3484     pic16_emitpLabelFORCE(retlbl->key);
3485
3486     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3487
3488     GpsuedoStkPtr=0;
3489     /* if we need assign a result value */
3490     if ((IS_ITEMP(IC_RESULT(ic))
3491           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3492               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3493         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3494
3495       _G.accInUse++;
3496       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3497       _G.accInUse--;
3498
3499       assignResultValue(IC_RESULT(ic), 1);
3500
3501       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3502               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3503                 
3504       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3505     }
3506
3507 //    stackParms -= use_wreg;
3508     
3509     if(stackParms>0) {
3510       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3511       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3512       if(STACK_MODEL_LARGE) {
3513         emitSKPNC;
3514         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3515       }
3516     }
3517 }
3518
3519 /*-----------------------------------------------------------------*/
3520 /* resultRemat - result  is rematerializable                       */
3521 /*-----------------------------------------------------------------*/
3522 static int resultRemat (iCode *ic)
3523 {
3524   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3525   if (SKIP_IC(ic) || ic->op == IFX)
3526     return 0;
3527
3528   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3529     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3530     if (sym->remat && !POINTER_SET(ic)) 
3531       return 1;
3532   }
3533
3534   return 0;
3535 }
3536
3537 #if defined(__BORLANDC__) || defined(_MSC_VER)
3538 #define STRCASECMP stricmp
3539 #else
3540 #define STRCASECMP strcasecmp
3541 #endif
3542
3543 #if 0
3544 /*-----------------------------------------------------------------*/
3545 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3546 /*-----------------------------------------------------------------*/
3547 static bool inExcludeList(char *s)
3548 {
3549   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3550     int i =0;
3551     
3552     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3553     if (options.excludeRegs[i] &&
3554     STRCASECMP(options.excludeRegs[i],"none") == 0)
3555         return FALSE ;
3556
3557     for ( i = 0 ; options.excludeRegs[i]; i++) {
3558         if (options.excludeRegs[i] &&
3559         STRCASECMP(s,options.excludeRegs[i]) == 0)
3560             return TRUE;
3561     }
3562     return FALSE ;
3563 }
3564 #endif
3565
3566 /*-----------------------------------------------------------------*/
3567 /* genFunction - generated code for function entry                 */
3568 /*-----------------------------------------------------------------*/
3569 static void genFunction (iCode *ic)
3570 {
3571   symbol *sym;
3572   sym_link *ftype;
3573   
3574     FENTRY;
3575     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3576
3577     pic16_labelOffset += (max_key+4);
3578     max_key=0;
3579     GpsuedoStkPtr=0;
3580     _G.nRegsSaved = 0;
3581         
3582     ftype = operandType(IC_LEFT(ic));
3583     sym = OP_SYMBOL(IC_LEFT(ic));
3584
3585     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3586       /* create an absolute section at the interrupt vector:
3587        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3588       symbol *asym;
3589       char asymname[128];
3590       pBlock *apb;
3591
3592 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3593
3594         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3595           sprintf(asymname, "ivec_%s", sym->name);
3596         else
3597           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3598   
3599         /* when an interrupt is declared as naked, do not emit the special
3600          * wrapper segment at vector address. The user should take care for
3601          * this instead. -- VR */
3602
3603         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3604           asym = newSymbol(asymname, 0);
3605           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3606           pic16_addpBlock( apb );
3607
3608           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3609           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3610           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3611           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3612           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3613                 
3614           /* mark the end of this tiny function */
3615           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3616         } else {
3617           sprintf(asymname, "%s", sym->rname);
3618         }
3619
3620         {
3621           absSym *abSym;
3622
3623             abSym = Safe_calloc(1, sizeof(absSym));
3624             strcpy(abSym->name, asymname);
3625
3626             switch( FUNC_INTNO(sym->type) ) {
3627               case 0: abSym->address = 0x000000; break;
3628               case 1: abSym->address = 0x000008; break;
3629               case 2: abSym->address = 0x000018; break;
3630               
3631               default:
3632 //                fprintf(stderr, "no interrupt number is given\n");
3633                 abSym->address = -1; break;
3634             }
3635
3636             /* relocate interrupt vectors if needed */
3637             if(abSym->address != -1)
3638               abSym->address += pic16_options.ivt_loc;
3639
3640             addSet(&absSymSet, abSym);
3641         }
3642     }
3643
3644     /* create the function header */
3645     pic16_emitcode(";","-----------------------------------------");
3646     pic16_emitcode(";"," function %s",sym->name);
3647     pic16_emitcode(";","-----------------------------------------");
3648
3649     pic16_emitcode("","%s:",sym->rname);
3650     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3651
3652     {
3653       absSym *ab;
3654
3655         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3656           if(!strcmp(ab->name, sym->rname)) {
3657             pic16_pBlockConvert2Absolute(pb);
3658             break;
3659           }
3660         }
3661     }
3662
3663     if(IFFUNC_ISNAKED(ftype)) {
3664       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3665       return;
3666     }
3667         
3668     /* if critical function then turn interrupts off */
3669     if (IFFUNC_ISCRITICAL(ftype)) {
3670       //pic16_emitcode("clr","ea");
3671     }
3672
3673     currFunc = sym;             /* update the currFunc symbol */
3674     _G.fregsUsed = sym->regsUsed;
3675     _G.sregsAlloc = newBitVect(128);
3676     
3677
3678     /* if this is an interrupt service routine then
3679      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3680     if (IFFUNC_ISISR(sym->type)) {
3681         _G.usefastretfie = 1;   /* use shadow registers by default */
3682         
3683         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3684         if(!FUNC_ISSHADOWREGS(sym->type)) {
3685           /* do not save WREG,STATUS,BSR for high priority interrupts
3686            * because they are stored in the hardware shadow registers already */
3687           _G.usefastretfie = 0;
3688           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3689           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3690           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3691         }
3692
3693         /* these should really be optimized somehow, because not all
3694          * interrupt handlers modify them */
3695         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3696         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3697         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3698         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3699         
3700 //        pic16_pBlockConvert2ISR(pb);
3701     }
3702
3703     /* emit code to setup stack frame if user enabled,
3704      * and function is not main() */
3705     
3706 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3707     if(strcmp(sym->name, "main")) {
3708       if(0 
3709         || !options.ommitFramePtr 
3710 //        || sym->regsUsed
3711         || IFFUNC_ARGS(sym->type)
3712         || FUNC_HASSTACKPARM(sym->etype)
3713         ) {
3714         /* setup the stack frame */
3715         if(STACK_MODEL_LARGE)
3716           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3717         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3718
3719         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3720         if(STACK_MODEL_LARGE)
3721           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3722       }
3723     }
3724
3725     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3726           && sym->stack) {
3727
3728       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3729
3730       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3731       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3732       emitSKPC;
3733       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3734     }
3735           
3736     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3737       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3738         _G.useWreg = 0;
3739       else
3740         _G.useWreg = 1;
3741     } else
3742       _G.useWreg = 0;
3743
3744     /* if callee-save to be used for this function
3745      * then save the registers being used in this function */
3746 //    if (IFFUNC_CALLEESAVES(sym->type))
3747     {
3748       int i;
3749
3750         /* if any registers used */
3751         if (sym->regsUsed) {
3752           /* save the registers used */
3753           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3754           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3755           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3756             if (bitVectBitValue(sym->regsUsed,i)) {
3757               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3758               _G.nRegsSaved++;
3759
3760               if(!pic16_regWithIdx(i)->wasUsed) {
3761                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3762                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3763                 pic16_regWithIdx(i)->wasUsed = 1;
3764               }
3765             }
3766           }
3767           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3768         }
3769     }
3770         
3771     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3772 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3773 }
3774
3775 /*-----------------------------------------------------------------*/
3776 /* genEndFunction - generates epilogue for functions               */
3777 /*-----------------------------------------------------------------*/
3778 static void genEndFunction (iCode *ic)
3779 {
3780   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3781
3782     FENTRY;
3783
3784     if(IFFUNC_ISNAKED(sym->type)) {
3785       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3786       return;
3787     }
3788
3789     _G.stack_lat = 0;
3790
3791     /* add code for ISCRITICAL */
3792     if(IFFUNC_ISCRITICAL(sym->type)) {
3793       /* if critical function, turn on interrupts */
3794       
3795       /* TODO: add code here -- VR */
3796     }
3797     
3798 //    sym->regsUsed = _G.fregsUsed;
3799     
3800     /* now we need to restore the registers */
3801     /* if any registers used */
3802
3803     /* first restore registers that might be used for stack access */
3804     if(_G.sregsAllocSet) {
3805     regs *sr;
3806     
3807       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3808       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3809         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3810       }
3811     }
3812
3813     if (sym->regsUsed) {
3814       int i;
3815
3816         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3817         /* restore registers used */
3818         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3819         for ( i = sym->regsUsed->size; i >= 0; i--) {
3820           if (bitVectBitValue(sym->regsUsed,i)) {
3821             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3822             _G.nRegsSaved--;
3823           }
3824         }
3825         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3826     }
3827
3828       
3829
3830     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3831           && sym->stack) {
3832       if (sym->stack == 1) {
3833         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3834         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3835       } else {
3836         // we have to add more than one...
3837         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3838         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3839         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3840         emitSKPNC;
3841         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3842         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3843         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3844       }
3845     }
3846
3847     if(strcmp(sym->name, "main")) {
3848       if(0
3849         || !options.ommitFramePtr
3850 //        || sym->regsUsed
3851         || IFFUNC_ARGS(sym->type)
3852         || FUNC_HASSTACKPARM(sym->etype)
3853         ) {
3854         /* restore stack frame */
3855         if(STACK_MODEL_LARGE)
3856           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3857         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3858       }
3859     }
3860
3861     _G.useWreg = 0;
3862
3863     if (IFFUNC_ISISR(sym->type)) {
3864       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3865       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3866       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3867       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3868
3869       if(!FUNC_ISSHADOWREGS(sym->type)) {
3870         /* do not restore interrupt vector for WREG,STATUS,BSR
3871          * for high priority interrupt, see genFunction */
3872         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3873         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3874         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3875       }
3876 //      _G.interruptvector = 0;         /* sanity check */
3877
3878
3879       /* if debug then send end of function */
3880 /*      if (options.debug && currFunc)  */
3881       if (currFunc) {
3882         debugFile->writeEndFunction (currFunc, ic, 1);
3883       }
3884         
3885       if(_G.usefastretfie)
3886         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3887       else
3888         pic16_emitpcodeNULLop(POC_RETFIE);
3889
3890       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3891       
3892       _G.usefastretfie = 0;
3893       return;
3894     }
3895
3896     if (IFFUNC_ISCRITICAL(sym->type)) {
3897       pic16_emitcode("setb","ea");
3898     }
3899
3900     /* if debug then send end of function */
3901     if (currFunc) {
3902       debugFile->writeEndFunction (currFunc, ic, 1);
3903     }
3904
3905     /* insert code to restore stack frame, if user enabled it
3906      * and function is not main() */
3907          
3908
3909     pic16_emitpcodeNULLop(POC_RETURN);
3910
3911     /* Mark the end of a function */
3912     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3913 }
3914
3915
3916 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3917 {
3918   unsigned long lit=1;
3919   operand *op;
3920
3921     op = IC_LEFT(ic);
3922   
3923     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3924     if(AOP_TYPE(op) == AOP_LIT) {
3925       if(!IS_FLOAT(operandType( op ))) {
3926         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3927       } else {
3928         union {
3929           unsigned long lit_int;
3930           float lit_float;
3931         } info;
3932         
3933         /* take care if literal is a float */
3934         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3935         lit = info.lit_int;
3936       }
3937     }
3938
3939     if(is_LitOp(op)) {
3940       pic16_movLit2f(dest, lit);
3941     } else {
3942       if(dest->type == PO_WREG && (offset == 0)) {
3943         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3944       return;
3945     }
3946     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3947   }
3948 }
3949
3950 /*-----------------------------------------------------------------*/
3951 /* genRet - generate code for return statement                     */
3952 /*-----------------------------------------------------------------*/
3953 static void genRet (iCode *ic)
3954 {
3955   int size;
3956   operand *left;
3957
3958     FENTRY;
3959         /* if we have no return value then
3960          * just generate the "ret" */
3961         
3962         if (!IC_LEFT(ic)) 
3963                 goto jumpret;       
3964     
3965         /* we have something to return then
3966          * move the return value into place */
3967         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3968         size = AOP_SIZE(IC_LEFT(ic));
3969
3970         if(size <= 4) {
3971           if(size>3)
3972             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3973           
3974           if(size>2)
3975             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3976
3977           if(size>1)
3978             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3979           
3980           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3981
3982         } else {
3983                 /* >32-bits, setup stack and FSR0 */
3984                 while (size--) {
3985 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3986 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3987
3988                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3989
3990 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3991                         GpsuedoStkPtr++;
3992                 }
3993                         
3994                 /* setup FSR0 */
3995                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3996                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3997
3998                 if(STACK_MODEL_LARGE) {
3999                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4000                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4001                 } else {
4002                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4003                 }
4004         }
4005                                 
4006 #if 0
4007         /* old code, left here for reference -- VR */    
4008         while (size--) {
4009           char *l ;
4010
4011                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4012                         /* #NOCHANGE */
4013                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4014                         pic16_emitpcomment("push %s",l);
4015                         pushed++;
4016                 } else {
4017                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4018                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4019                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4020                         
4021                         if (strcmp(fReturn[offset],l)) {
4022                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4023                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4024                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4025                                 } else {
4026                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4027                                 }
4028                                 
4029                                 if(size) {
4030                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4031                                 }
4032                                 offset++;
4033                         }
4034                 }
4035         }    
4036
4037         if (pushed) {
4038                 while(pushed) {
4039                         pushed--;
4040                         if (strcmp(fReturn[pushed],"a"))
4041                                 pic16_emitcode("pop",fReturn[pushed]);
4042                         else
4043                                 pic16_emitcode("pop","acc");
4044                 }
4045         }
4046 #endif
4047
4048
4049         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4050     
4051 jumpret:
4052         /* generate a jump to the return label
4053          * if the next is not the return statement */
4054         if (!(ic->next && ic->next->op == LABEL
4055                 && IC_LABEL(ic->next) == returnLabel)) {
4056         
4057                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4058                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4059         }
4060 }
4061
4062 /*-----------------------------------------------------------------*/
4063 /* genLabel - generates a label                                    */
4064 /*-----------------------------------------------------------------*/
4065 static void genLabel (iCode *ic)
4066 {
4067   FENTRY;
4068
4069   /* special case never generate */
4070   if (IC_LABEL(ic) == entryLabel)
4071     return ;
4072
4073   pic16_emitpLabel(IC_LABEL(ic)->key);
4074 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4075 }
4076
4077 /*-----------------------------------------------------------------*/
4078 /* genGoto - generates a goto                                      */
4079 /*-----------------------------------------------------------------*/
4080 //tsd
4081 static void genGoto (iCode *ic)
4082 {
4083   FENTRY;
4084   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4085 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4086 }
4087
4088
4089 /*-----------------------------------------------------------------*/
4090 /* genMultbits :- multiplication of bits                           */
4091 /*-----------------------------------------------------------------*/
4092 static void genMultbits (operand *left, 
4093                          operand *right, 
4094                          operand *result)
4095 {
4096   FENTRY;
4097
4098   if(!pic16_sameRegs(AOP(result),AOP(right)))
4099     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4100
4101   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4102   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4103   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4104
4105 }
4106
4107
4108 /*-----------------------------------------------------------------*/
4109 /* genMultOneByte : 8 bit multiplication & division                */
4110 /*-----------------------------------------------------------------*/
4111 static void genMultOneByte (operand *left,
4112                             operand *right,
4113                             operand *result)
4114 {
4115
4116   FENTRY;
4117   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4118   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4119
4120   /* (if two literals, the value is computed before) */
4121   /* if one literal, literal on the right */
4122   if (AOP_TYPE(left) == AOP_LIT){
4123     operand *t = right;
4124     right = left;
4125     left = t;
4126   }
4127
4128         /* size is already checked in genMult == 1 */
4129 //      size = AOP_SIZE(result);
4130
4131         if (AOP_TYPE(right) == AOP_LIT){
4132                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4133                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4134                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4135                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4136         } else {
4137                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4138                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4139                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4140                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4141         }
4142         
4143         pic16_genMult8X8_8 (left, right,result);
4144 }
4145
4146 /*-----------------------------------------------------------------*/
4147 /* genMultOneWord : 16 bit multiplication                          */
4148 /*-----------------------------------------------------------------*/
4149 static void genMultOneWord (operand *left,
4150                             operand *right,
4151                             operand *result)
4152 {
4153   FENTRY;
4154   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4155   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4156
4157   /* (if two literals, the value is computed before)
4158    * if one literal, literal on the right */
4159   if (AOP_TYPE(left) == AOP_LIT){
4160     operand *t = right;
4161     right = left;
4162     left = t;
4163   }
4164
4165   /* size is checked already == 2 */
4166 //  size = AOP_SIZE(result);
4167
4168   if (AOP_TYPE(right) == AOP_LIT) {
4169     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4170       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4171       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4172       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4173   } else {
4174     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4175       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4176       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4177       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4178   }
4179         
4180   pic16_genMult16X16_16(left, right,result);
4181 }
4182
4183 /*-----------------------------------------------------------------*/
4184 /* genMultOneLong : 32 bit multiplication                          */
4185 /*-----------------------------------------------------------------*/
4186 static void genMultOneLong (operand *left,
4187                             operand *right,
4188                             operand *result)
4189 {
4190   FENTRY;
4191   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4192   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4193
4194   /* (if two literals, the value is computed before)
4195    * if one literal, literal on the right */
4196   if (AOP_TYPE(left) == AOP_LIT){
4197     operand *t = right;
4198     right = left;
4199     left = t;
4200   }
4201
4202   /* size is checked already == 4 */
4203 //  size = AOP_SIZE(result);
4204
4205   if (AOP_TYPE(right) == AOP_LIT) {
4206     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4207         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4208         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4209         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4210   } else {
4211     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4212         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4213         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4214         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4215   }
4216         
4217   pic16_genMult32X32_32(left, right,result);
4218 }
4219
4220
4221
4222 /*-----------------------------------------------------------------*/
4223 /* genMult - generates code for multiplication                     */
4224 /*-----------------------------------------------------------------*/
4225 static void genMult (iCode *ic)
4226 {
4227   operand *left = IC_LEFT(ic);
4228   operand *right = IC_RIGHT(ic);
4229   operand *result= IC_RESULT(ic);   
4230
4231     FENTRY;
4232         /* assign the amsops */
4233         pic16_aopOp (left,ic,FALSE);
4234         pic16_aopOp (right,ic,FALSE);
4235         pic16_aopOp (result,ic,TRUE);
4236
4237         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4238
4239         /* special cases first *
4240         * both are bits */
4241         if (AOP_TYPE(left) == AOP_CRY
4242                 && AOP_TYPE(right)== AOP_CRY) {
4243                 genMultbits(left,right,result);
4244           goto release ;
4245         }
4246
4247         /* if both are of size == 1 */
4248         if(AOP_SIZE(left) == 1
4249                 && AOP_SIZE(right) == 1) {
4250                 genMultOneByte(left,right,result);
4251           goto release ;
4252         }
4253
4254         /* if both are of size == 2 */
4255         if(AOP_SIZE(left) == 2
4256                 && AOP_SIZE(right) == 2) {
4257                 genMultOneWord(left, right, result);
4258           goto release;
4259         }
4260         
4261         /* if both are of size == 4 */
4262         if(AOP_SIZE(left) == 4
4263                 && AOP_SIZE(right) == 4) {
4264                 genMultOneLong(left, right, result);
4265           goto release;
4266         }
4267         
4268         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4269
4270
4271         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4272         /* should have been converted to function call */
4273         assert(0) ;
4274
4275 release :
4276         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4277         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4278         pic16_freeAsmop(result,NULL,ic,TRUE); 
4279 }
4280
4281 /*-----------------------------------------------------------------*/
4282 /* genDivbits :- division of bits                                  */
4283 /*-----------------------------------------------------------------*/
4284 static void genDivbits (operand *left, 
4285                         operand *right, 
4286                         operand *result)
4287 {
4288   char *l;
4289
4290     FENTRY;
4291     /* the result must be bit */    
4292     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4293     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4294
4295     MOVA(l);    
4296
4297     pic16_emitcode("div","ab");
4298     pic16_emitcode("rrc","a");
4299     pic16_aopPut(AOP(result),"c",0);
4300 }
4301
4302 /*-----------------------------------------------------------------*/
4303 /* genDivOneByte : 8 bit division                                  */
4304 /*-----------------------------------------------------------------*/
4305 static void genDivOneByte (operand *left,
4306                            operand *right,
4307                            operand *result)
4308 {
4309   sym_link *opetype = operandType(result);
4310   char *l ;
4311   symbol *lbl ;
4312   int size,offset;
4313
4314         /* result = divident / divisor
4315          * - divident may be a register or a literal,
4316          * - divisor may be a register or a literal,
4317          * so there are 3 cases (literal / literal is optimized
4318          * by the front-end) to handle.
4319          * In addition we must handle signed and unsigned, which
4320          * result in 6 final different cases -- VR */
4321
4322     FENTRY;
4323     
4324     size = AOP_SIZE(result) - 1;
4325     offset = 1;
4326     /* signed or unsigned */
4327     if (SPEC_USIGN(opetype)) {
4328       pCodeOp *pct1,    /* count */
4329                 *pct2,  /* reste */
4330                 *pct3;  /* temp */
4331       symbol *label1, *label2, *label3;;
4332
4333
4334         /* unsigned is easy */
4335
4336         pct1 = pic16_popGetTempReg(1);
4337         pct2 = pic16_popGetTempReg(1);
4338         pct3 = pic16_popGetTempReg(1);
4339         
4340         label1 = newiTempLabel(NULL);
4341         label2 = newiTempLabel(NULL);
4342         label3 = newiTempLabel(NULL);
4343
4344         /* the following algorithm is extracted from divuint.c */
4345
4346         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4347         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4348         
4349         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4350
4351         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4352         
4353         pic16_emitpLabel(label1->key);
4354         
4355         emitCLRC;
4356         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4357
4358
4359         emitCLRC;
4360         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4361         
4362
4363         emitSKPNC;
4364         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4365         
4366         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4367         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4368         
4369         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4370         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4371         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4372         
4373         pic16_emitpLabel( label3->key );
4374         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4375         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4376         
4377         
4378
4379         pic16_emitpLabel(label2->key);
4380         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4381         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4382         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4383         
4384         /* result is in wreg */
4385         if(AOP_TYPE(result) != AOP_ACC)
4386                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4387
4388         pic16_popReleaseTempReg( pct3, 1);
4389         pic16_popReleaseTempReg( pct2, 1);
4390         pic16_popReleaseTempReg( pct1, 1);
4391
4392         return ;
4393     }
4394
4395     /* signed is a little bit more difficult */
4396
4397     /* save the signs of the operands */
4398     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4399     MOVA(l);    
4400     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4401     pic16_emitcode("push","acc"); /* save it on the stack */
4402
4403     /* now sign adjust for both left & right */
4404     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4405     MOVA(l);       
4406     lbl = newiTempLabel(NULL);
4407     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4408     pic16_emitcode("cpl","a");   
4409     pic16_emitcode("inc","a");
4410     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4411     pic16_emitcode("mov","b,a");
4412
4413     /* sign adjust left side */
4414     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4415     MOVA(l);
4416
4417     lbl = newiTempLabel(NULL);
4418     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4419     pic16_emitcode("cpl","a");
4420     pic16_emitcode("inc","a");
4421     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4422
4423     /* now the division */
4424     pic16_emitcode("div","ab");
4425     /* we are interested in the lower order
4426     only */
4427     pic16_emitcode("mov","b,a");
4428     lbl = newiTempLabel(NULL);
4429     pic16_emitcode("pop","acc");   
4430     /* if there was an over flow we don't 
4431     adjust the sign of the result */
4432     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4433     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4434     CLRC;
4435     pic16_emitcode("clr","a");
4436     pic16_emitcode("subb","a,b");
4437     pic16_emitcode("mov","b,a");
4438     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4439
4440     /* now we are done */
4441     pic16_aopPut(AOP(result),"b",0);
4442     if(size > 0){
4443         pic16_emitcode("mov","c,b.7");
4444         pic16_emitcode("subb","a,acc");   
4445     }
4446     while (size--)
4447         pic16_aopPut(AOP(result),"a",offset++);
4448
4449 }
4450
4451 /*-----------------------------------------------------------------*/
4452 /* genDiv - generates code for division                            */
4453 /*-----------------------------------------------------------------*/
4454 static void genDiv (iCode *ic)
4455 {
4456     operand *left = IC_LEFT(ic);
4457     operand *right = IC_RIGHT(ic);
4458     operand *result= IC_RESULT(ic);   
4459
4460
4461         /* Division is a very lengthy algorithm, so it is better
4462          * to call support routines than inlining algorithm.
4463          * Division functions written here just in case someone
4464          * wants to inline and not use the support libraries -- VR */
4465
4466     FENTRY;
4467     
4468     /* assign the amsops */
4469     pic16_aopOp (left,ic,FALSE);
4470     pic16_aopOp (right,ic,FALSE);
4471     pic16_aopOp (result,ic,TRUE);
4472
4473     /* special cases first */
4474     /* both are bits */
4475     if (AOP_TYPE(left) == AOP_CRY &&
4476         AOP_TYPE(right)== AOP_CRY) {
4477         genDivbits(left,right,result);
4478         goto release ;
4479     }
4480
4481     /* if both are of size == 1 */
4482     if (AOP_SIZE(left) == 1 &&
4483         AOP_SIZE(right) == 1 ) {
4484         genDivOneByte(left,right,result);
4485         goto release ;
4486     }
4487
4488     /* should have been converted to function call */
4489     assert(0);
4490 release :
4491     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4492     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4493     pic16_freeAsmop(result,NULL,ic,TRUE); 
4494 }
4495
4496 /*-----------------------------------------------------------------*/
4497 /* genModbits :- modulus of bits                                   */
4498 /*-----------------------------------------------------------------*/
4499 static void genModbits (operand *left, 
4500                         operand *right, 
4501                         operand *result)
4502 {
4503   char *l;
4504
4505     FENTRY;  
4506     
4507     werror(W_POSSBUG2, __FILE__, __LINE__);
4508     /* the result must be bit */    
4509     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4510     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4511
4512     MOVA(l);       
4513
4514     pic16_emitcode("div","ab");
4515     pic16_emitcode("mov","a,b");
4516     pic16_emitcode("rrc","a");
4517     pic16_aopPut(AOP(result),"c",0);
4518 }
4519
4520 /*-----------------------------------------------------------------*/
4521 /* genModOneByte : 8 bit modulus                                   */
4522 /*-----------------------------------------------------------------*/
4523 static void genModOneByte (operand *left,
4524                            operand *right,
4525                            operand *result)
4526 {
4527   sym_link *opetype = operandType(result);
4528   char *l ;
4529   symbol *lbl ;
4530
4531     FENTRY;
4532     werror(W_POSSBUG2, __FILE__, __LINE__);
4533
4534     /* signed or unsigned */
4535     if (SPEC_USIGN(opetype)) {
4536         /* unsigned is easy */
4537         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4538         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4539         MOVA(l);    
4540         pic16_emitcode("div","ab");
4541         pic16_aopPut(AOP(result),"b",0);
4542         return ;
4543     }
4544
4545     /* signed is a little bit more difficult */
4546
4547     /* save the signs of the operands */
4548     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4549     MOVA(l);
4550
4551     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4552     pic16_emitcode("push","acc"); /* save it on the stack */
4553
4554     /* now sign adjust for both left & right */
4555     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4556     MOVA(l);
4557
4558     lbl = newiTempLabel(NULL);
4559     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4560     pic16_emitcode("cpl","a");   
4561     pic16_emitcode("inc","a");
4562     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4563     pic16_emitcode("mov","b,a"); 
4564
4565     /* sign adjust left side */
4566     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4567     MOVA(l);
4568
4569     lbl = newiTempLabel(NULL);
4570     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4571     pic16_emitcode("cpl","a");   
4572     pic16_emitcode("inc","a");
4573     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4574
4575     /* now the multiplication */
4576     pic16_emitcode("div","ab");
4577     /* we are interested in the lower order
4578     only */
4579     lbl = newiTempLabel(NULL);
4580     pic16_emitcode("pop","acc");   
4581     /* if there was an over flow we don't 
4582     adjust the sign of the result */
4583     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4584     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4585     CLRC ;
4586     pic16_emitcode("clr","a");
4587     pic16_emitcode("subb","a,b");
4588     pic16_emitcode("mov","b,a");
4589     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4590
4591     /* now we are done */
4592     pic16_aopPut(AOP(result),"b",0);
4593
4594 }
4595
4596 /*-----------------------------------------------------------------*/
4597 /* genMod - generates code for division                            */
4598 /*-----------------------------------------------------------------*/
4599 static void genMod (iCode *ic)
4600 {
4601   operand *left = IC_LEFT(ic);
4602   operand *right = IC_RIGHT(ic);
4603   operand *result= IC_RESULT(ic);  
4604
4605     FENTRY;
4606     
4607     /* assign the amsops */
4608     pic16_aopOp (left,ic,FALSE);
4609     pic16_aopOp (right,ic,FALSE);
4610     pic16_aopOp (result,ic,TRUE);
4611
4612     /* special cases first */
4613     /* both are bits */
4614     if (AOP_TYPE(left) == AOP_CRY &&
4615         AOP_TYPE(right)== AOP_CRY) {
4616         genModbits(left,right,result);
4617         goto release ;
4618     }
4619
4620     /* if both are of size == 1 */
4621     if (AOP_SIZE(left) == 1 &&
4622         AOP_SIZE(right) == 1 ) {
4623         genModOneByte(left,right,result);
4624         goto release ;
4625     }
4626
4627     /* should have been converted to function call */
4628     assert(0);
4629
4630 release :
4631     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4632     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4633     pic16_freeAsmop(result,NULL,ic,TRUE); 
4634 }
4635
4636 /*-----------------------------------------------------------------*/
4637 /* genIfxJump :- will create a jump depending on the ifx           */
4638 /*-----------------------------------------------------------------*/
4639 /*
4640   note: May need to add parameter to indicate when a variable is in bit space.
4641 */
4642 static void genIfxJump (iCode *ic, char *jval)
4643 {
4644   FENTRY;
4645   
4646     /* if true label then we jump if condition
4647     supplied is true */
4648     if ( IC_TRUE(ic) ) {
4649
4650         if(strcmp(jval,"a") == 0)
4651           emitSKPZ;
4652         else if (strcmp(jval,"c") == 0)
4653           emitSKPNC;
4654         else {
4655           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4656           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4657         }
4658
4659         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4660         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4661
4662     }
4663     else {
4664         /* false label is present */
4665         if(strcmp(jval,"a") == 0)
4666           emitSKPNZ;
4667         else if (strcmp(jval,"c") == 0)
4668           emitSKPC;
4669         else {
4670           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4671           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4672         }
4673
4674         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4675         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4676
4677     }
4678
4679
4680     /* mark the icode as generated */
4681     ic->generated = 1;
4682 }
4683
4684 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4685 {
4686   FENTRY;
4687   
4688     /* if true label then we jump if condition
4689     supplied is true */
4690     if ( IC_TRUE(ic) ) {
4691       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4692       pic16_emitpcode(POC_BTFSC, jop);
4693
4694       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4695       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4696
4697     } else {
4698       /* false label is present */
4699       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4700       pic16_emitpcode(POC_BTFSS, jop);
4701           
4702       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4703       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4704     }
4705
4706
4707     /* mark the icode as generated */
4708     ic->generated = 1;
4709 }
4710
4711 #if 0
4712 // not needed ATM
4713
4714 /*-----------------------------------------------------------------*/
4715 /* genSkip                                                         */
4716 /*-----------------------------------------------------------------*/
4717 static void genSkip(iCode *ifx,int status_bit)
4718 {
4719   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4720   if(!ifx)
4721     return;
4722
4723   if ( IC_TRUE(ifx) ) {
4724     switch(status_bit) {
4725     case 'z':
4726       emitSKPNZ;
4727       break;
4728
4729     case 'c':
4730       emitSKPNC;
4731       break;
4732
4733     case 'd':
4734       emitSKPDC;
4735       break;
4736
4737     }
4738
4739     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4740     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4741
4742   } else {
4743
4744     switch(status_bit) {
4745
4746     case 'z':
4747       emitSKPZ;
4748       break;
4749
4750     case 'c':
4751       emitSKPC;
4752       break;
4753
4754     case 'd':
4755       emitSKPDC;
4756       break;
4757     }
4758     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4759     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4760
4761   }
4762
4763 }
4764 #endif
4765
4766 /*-----------------------------------------------------------------*/
4767 /* genSkipc                                                        */
4768 /*-----------------------------------------------------------------*/
4769 static void genSkipc(resolvedIfx *rifx)
4770 {
4771   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4772   
4773   if(!rifx)
4774     return;
4775
4776   if(rifx->condition)
4777     emitSKPNC;
4778   else
4779     emitSKPC;
4780
4781   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4782   rifx->generated = 1;
4783 }
4784
4785 #if !(USE_SIMPLE_GENCMP)
4786 /*-----------------------------------------------------------------*/
4787 /* genSkipz2                                                       */
4788 /*-----------------------------------------------------------------*/
4789 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4790 {
4791   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4792   
4793   if(!rifx)
4794     return;
4795
4796   if( (rifx->condition ^ invert_condition) & 1)
4797     emitSKPZ;
4798   else
4799     emitSKPNZ;
4800
4801   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4802   rifx->generated = 1;
4803 }
4804 #endif
4805
4806 #if 0
4807 /*-----------------------------------------------------------------*/
4808 /* genSkipz                                                        */
4809 /*-----------------------------------------------------------------*/
4810 static void genSkipz(iCode *ifx, int condition)
4811 {
4812   if(!ifx)
4813     return;
4814
4815   if(condition)
4816     emitSKPNZ;
4817   else
4818     emitSKPZ;
4819
4820   if ( IC_TRUE(ifx) )
4821     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4822   else
4823     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4824
4825   if ( IC_TRUE(ifx) )
4826     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4827   else
4828     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4829
4830 }
4831 #endif
4832
4833 #if !(USE_SIMPLE_GENCMP)
4834 /*-----------------------------------------------------------------*/
4835 /* genSkipCond                                                     */
4836 /*-----------------------------------------------------------------*/
4837 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4838 {
4839   if(!rifx)
4840     return;
4841
4842   if(rifx->condition)
4843     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4844   else
4845     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4846
4847
4848   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4849   rifx->generated = 1;
4850 }
4851 #endif
4852
4853 #if 0
4854 /*-----------------------------------------------------------------*/
4855 /* genChkZeroes :- greater or less than comparison                 */
4856 /*     For each byte in a literal that is zero, inclusive or the   */
4857 /*     the corresponding byte in the operand with W                */
4858 /*     returns true if any of the bytes are zero                   */
4859 /*-----------------------------------------------------------------*/
4860 static int genChkZeroes(operand *op, int lit,  int size)
4861 {
4862
4863   int i;
4864   int flag =1;
4865
4866   while(size--) {
4867     i = (lit >> (size*8)) & 0xff;
4868
4869     if(i==0) {
4870       if(flag) 
4871         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4872       else
4873         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4874       flag = 0;
4875     }
4876   }
4877
4878   return (flag==0);
4879 }
4880 #endif
4881
4882
4883 /*-----------------------------------------------------------------*/
4884 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4885 /*                  aop (if it's NOT a literal) or from lit (if    */
4886 /*                  aop is a literal)                              */
4887 /*-----------------------------------------------------------------*/
4888 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4889   if (aop->type == AOP_LIT) {
4890     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4891   } else {
4892     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4893   }
4894 }
4895
4896 /*-----------------------------------------------------------------*/
4897 /* genCmp :- greater or less than comparison                       */
4898 /*-----------------------------------------------------------------*/
4899
4900 #if USE_SIMPLE_GENCMP           /* { */
4901
4902 /* genCmp performs a left < right comparison, stores
4903  * the outcome in result (if != NULL) and generates
4904  * control flow code for the ifx (if != NULL).
4905  *
4906  * This version leaves in sequences like
4907  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4908  * which should be optmized by the peephole
4909  * optimizer - RN 2005-01-01 */
4910 static void genCmp (operand *left,operand *right,
4911                     operand *result, iCode *ifx, int sign)
4912 {
4913   resolvedIfx rIfx;
4914   int size;
4915   int offs;
4916   symbol *templbl;
4917   operand *dummy;
4918   unsigned long lit;
4919   unsigned long mask;
4920   int performedLt;
4921
4922   FENTRY;
4923   
4924   assert (left && right);
4925   assert (AOP_SIZE(left) == AOP_SIZE(right));
4926
4927   size = AOP_SIZE(right) - 1;
4928   mask = (0x100UL << (size*8)) - 1;
4929   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4930   performedLt = 1;
4931   templbl = NULL;
4932   lit = 0;
4933   
4934   resolveIfx (&rIfx, ifx);
4935
4936   /* handle for special cases */
4937   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4938       return;
4939
4940   /**********************************************************************
4941    * handle bits - bit compares are promoted to int compares seemingly! *
4942    **********************************************************************/
4943 #if 0
4944   // THIS IS COMPLETELY UNTESTED!
4945   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4946     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4947     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4948     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4949
4950     emitSETC;
4951     // 1 < {0,1} is false --> clear C by skipping the next instruction
4952     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4953     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4954     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4955     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4956     emitCLRC; // only skipped for left=0 && right=1
4957
4958     goto correct_result_in_carry;
4959   } // if
4960 #endif
4961
4962   /*************************************************
4963    * make sure that left is register (or the like) *
4964    *************************************************/
4965   if (!isAOP_REGlike(left)) {
4966     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4967     assert (isAOP_LIT(left));
4968     assert (isAOP_REGlike(right));
4969     // swap left and right
4970     // left < right <==> right > left <==> (right >= left + 1)
4971     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4972
4973     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4974       // MAXVALUE < right? always false
4975       if (performedLt) emitCLRC; else emitSETC;
4976       goto correct_result_in_carry;
4977     } // if
4978
4979     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4980     // that's why we handled it above.
4981     lit++;
4982
4983     dummy = left;
4984     left = right;
4985     right = dummy;
4986
4987     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4988   } else if (isAOP_LIT(right)) {
4989     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4990   } // if
4991
4992   assert (isAOP_REGlike(left)); // left must be register or the like
4993   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4994
4995   /*************************************************
4996    * special cases go here                         *
4997    *************************************************/
4998
4999   if (isAOP_LIT(right)) {
5000     if (!sign) {
5001       // unsigned comparison to a literal
5002       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5003       if (lit == 0) {
5004         // unsigned left < 0? always false
5005         if (performedLt) emitCLRC; else emitSETC;
5006         goto correct_result_in_carry;
5007       }
5008     } else {
5009       // signed comparison to a literal
5010       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5011       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5012         // signed left < 0x80000000? always false
5013         if (performedLt) emitCLRC; else emitSETC;
5014         goto correct_result_in_carry;
5015       } else if (lit == 0) {
5016         // compare left < 0; set CARRY if SIGNBIT(left) is set
5017         if (performedLt) emitSETC; else emitCLRC;
5018         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5019         if (performedLt) emitCLRC; else emitSETC;
5020         goto correct_result_in_carry;
5021       }
5022     } // if (!sign)
5023   } // right is literal
5024
5025   /*************************************************
5026    * perform a general case comparison             *
5027    * make sure we get CARRY==1 <==> left >= right  *
5028    *************************************************/
5029   // compare most significant bytes
5030   //DEBUGpc ("comparing bytes at offset %d", size);
5031   if (!sign) {
5032     // unsigned comparison
5033     mov2w_regOrLit (AOP(right), lit, size);
5034     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5035   } else {
5036     // signed comparison
5037     // (add 2^n to both operands then perform an unsigned comparison)
5038     if (isAOP_LIT(right)) {
5039       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5040       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5041
5042       if (litbyte == 0x80) {
5043         // left >= 0x80 -- always true, but more bytes to come
5044         pic16_mov2w (AOP(left), size);
5045         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5046         emitSETC;
5047       } else {
5048         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5049         pic16_mov2w (AOP(left), size);
5050         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5051         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5052       } // if
5053     } else {
5054       /* using PRODL as a temporary register here */
5055       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5056       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5057       pic16_mov2w (AOP(left), size);
5058       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5059       pic16_emitpcode (POC_MOVWF, pctemp);
5060       pic16_mov2w (AOP(right), size);
5061       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5062       pic16_emitpcode (POC_SUBFW, pctemp);
5063       //pic16_popReleaseTempReg(pctemp, 1);
5064     }
5065   } // if (!sign)
5066
5067   // compare remaining bytes (treat as unsigned case from above)
5068   templbl = newiTempLabel ( NULL );
5069   offs = size;
5070   while (offs--) {
5071     //DEBUGpc ("comparing bytes at offset %d", offs);
5072     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5073     mov2w_regOrLit (AOP(right), lit, offs);
5074     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5075   } // while (offs)
5076   pic16_emitpLabel (templbl->key);
5077   goto result_in_carry;
5078
5079 result_in_carry:
5080   
5081   /****************************************************
5082    * now CARRY contains the result of the comparison: *
5083    * SUBWF sets CARRY iff                             *
5084    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5085    * (F=left, W=right)                                *
5086    ****************************************************/
5087
5088   if (performedLt) {
5089     if (result && AOP_TYPE(result) != AOP_CRY) {
5090       // value will be stored
5091       emitTOGC;
5092     } else {
5093       // value wil only be used in the following genSkipc()
5094       rIfx.condition ^= 1;
5095     }
5096   } // if
5097
5098 correct_result_in_carry:
5099
5100   // assign result to variable (if neccessary)
5101   if (result && AOP_TYPE(result) != AOP_CRY) {
5102     //DEBUGpc ("assign result");
5103     size = AOP_SIZE(result);
5104     while (size--) {
5105       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5106     } // while
5107     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5108   } // if (result)
5109
5110   // perform conditional jump
5111   if (ifx) {
5112     //DEBUGpc ("generate control flow");
5113     genSkipc (&rIfx);
5114     ifx->generated = 1;
5115   } // if
5116 }
5117
5118 #elif 1         /* } */
5119                 /* { */
5120       /* original code */
5121 static void genCmp (operand *left,operand *right,
5122                     operand *result, iCode *ifx, int sign)
5123 {
5124   int size; //, offset = 0 ;
5125   unsigned long lit = 0L,i = 0;
5126   resolvedIfx rFalseIfx;
5127   //  resolvedIfx rTrueIfx;
5128   symbol *truelbl;
5129   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5130 /*
5131   if(ifx) {
5132     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5133     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5134   }
5135 */
5136
5137   FENTRY;
5138   
5139   resolveIfx(&rFalseIfx,ifx);
5140   truelbl  = newiTempLabel(NULL);
5141   size = max(AOP_SIZE(left),AOP_SIZE(right));
5142
5143   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5144
5145 #define _swapp
5146
5147   /* if literal is on the right then swap with left */
5148   if ((AOP_TYPE(right) == AOP_LIT)) {
5149     operand *tmp = right ;
5150     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5151     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5152 #ifdef _swapp
5153
5154     lit = (lit - 1) & mask;
5155     right = left;
5156     left = tmp;
5157     rFalseIfx.condition ^= 1;
5158 #endif
5159
5160   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5161     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5162   }
5163
5164
5165   //if(IC_TRUE(ifx) == NULL)
5166   /* if left & right are bit variables */
5167   if (AOP_TYPE(left) == AOP_CRY &&
5168       AOP_TYPE(right) == AOP_CRY ) {
5169     assert (0 && "bit variables used in genCmp");
5170     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5171     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5172   } else {
5173     /* subtract right from left if at the
5174        end the carry flag is set then we know that
5175        left is greater than right */
5176
5177     symbol *lbl  = newiTempLabel(NULL);
5178
5179 #if 0
5180         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5181                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5182 #endif
5183
5184 #ifndef _swapp
5185     if(AOP_TYPE(right) == AOP_LIT) {
5186
5187       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5188
5189       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5190
5191       /* special cases */
5192
5193       if(lit == 0) {
5194
5195         if(sign != 0) 
5196           genSkipCond(&rFalseIfx,left,size-1,7);
5197         else 
5198           /* no need to compare to 0...*/
5199           /* NOTE: this is a de-generate compare that most certainly 
5200            *       creates some dead code. */
5201           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5202
5203         if(ifx) ifx->generated = 1;
5204         return;
5205
5206       }
5207       size--;
5208
5209       if(size == 0) {
5210         //i = (lit >> (size*8)) & 0xff;
5211         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5212         
5213         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5214
5215         i = ((0-lit) & 0xff);
5216         if(sign) {
5217           if( i == 0x81) { 
5218             /* lit is 0x7f, all signed chars are less than
5219              * this except for 0x7f itself */
5220             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5221             genSkipz2(&rFalseIfx,0);
5222           } else {
5223             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5224             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5225             genSkipc(&rFalseIfx);
5226           }
5227
5228         } else {
5229           if(lit == 1) {
5230             genSkipz2(&rFalseIfx,1);
5231           } else {
5232             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5233             genSkipc(&rFalseIfx);
5234           }
5235         }
5236
5237         if(ifx) ifx->generated = 1;
5238         return;
5239       }
5240
5241       /* chars are out of the way. now do ints and longs */
5242
5243
5244       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5245         
5246       /* special cases */
5247
5248       if(sign) {
5249
5250         if(lit == 0) {
5251           genSkipCond(&rFalseIfx,left,size,7);
5252           if(ifx) ifx->generated = 1;
5253           return;
5254         }
5255
5256         if(lit <0x100) {
5257           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5258
5259           //rFalseIfx.condition ^= 1;
5260           //genSkipCond(&rFalseIfx,left,size,7);
5261           //rFalseIfx.condition ^= 1;
5262
5263           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5264           if(rFalseIfx.condition)
5265             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5266           else
5267             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5268
5269           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5270           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5271           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5272
5273           while(size > 1)
5274             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5275
5276           if(rFalseIfx.condition) {
5277             emitSKPZ;
5278             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5279
5280           } else {
5281             emitSKPNZ;
5282           }
5283
5284           genSkipc(&rFalseIfx);
5285           pic16_emitpLabel(truelbl->key);
5286           if(ifx) ifx->generated = 1;
5287           return;
5288
5289         }
5290
5291         if(size == 1) {
5292
5293           if( (lit & 0xff) == 0) {
5294             /* lower byte is zero */
5295             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5296             i = ((lit >> 8) & 0xff) ^0x80;
5297             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5298             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5299             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5300             genSkipc(&rFalseIfx);
5301
5302
5303             if(ifx) ifx->generated = 1;
5304             return;
5305
5306           }
5307         } else {
5308           /* Special cases for signed longs */
5309           if( (lit & 0xffffff) == 0) {
5310             /* lower byte is zero */
5311             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5312             i = ((lit >> 8*3) & 0xff) ^0x80;
5313             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5314             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5315             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5316             genSkipc(&rFalseIfx);
5317
5318
5319             if(ifx) ifx->generated = 1;
5320             return;
5321
5322           }
5323
5324         }
5325
5326
5327         if(lit & (0x80 << (size*8))) {
5328           /* lit is negative */
5329           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5330
5331           //genSkipCond(&rFalseIfx,left,size,7);
5332
5333           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5334
5335           if(rFalseIfx.condition)
5336             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5337           else
5338             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5339
5340
5341         } else {
5342           /* lit is positive */
5343           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5344           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5345           if(rFalseIfx.condition)
5346             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5347           else
5348             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5349
5350         }
5351
5352         /*
5353           This works, but is only good for ints.
5354           It also requires a "known zero" register.
5355           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5356           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5357           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5358           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5359           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5360           genSkipc(&rFalseIfx);
5361
5362           pic16_emitpLabel(truelbl->key);
5363           if(ifx) ifx->generated = 1;
5364           return;
5365         **/
5366           
5367         /* There are no more special cases, so perform a general compare */
5368   
5369         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5370         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5371
5372         while(size--) {
5373
5374           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5375           emitSKPNZ;
5376           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5377         }
5378         //rFalseIfx.condition ^= 1;
5379         genSkipc(&rFalseIfx);
5380
5381         pic16_emitpLabel(truelbl->key);
5382
5383         if(ifx) ifx->generated = 1;
5384         return;
5385
5386
5387       }
5388
5389
5390       /* sign is out of the way. So now do an unsigned compare */
5391       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5392
5393
5394       /* General case - compare to an unsigned literal on the right.*/
5395
5396       i = (lit >> (size*8)) & 0xff;
5397       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5398       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5399       while(size--) {
5400         i = (lit >> (size*8)) & 0xff;
5401
5402         if(i) {
5403           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5404           emitSKPNZ;
5405           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5406         } else {
5407           /* this byte of the lit is zero, 
5408            *if it's not the last then OR in the variable */
5409           if(size)
5410             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5411         }
5412       }
5413
5414
5415       pic16_emitpLabel(lbl->key);
5416 //      pic16_emitpLabel(truelbl->key);
5417       //if(emitFinalCheck)
5418       genSkipc(&rFalseIfx);
5419       if(sign)
5420         pic16_emitpLabel(truelbl->key);
5421
5422       if(ifx) ifx->generated = 1;
5423       return;
5424
5425
5426     }
5427 #endif  // _swapp
5428
5429     if(AOP_TYPE(left) == AOP_LIT) {
5430       //symbol *lbl = newiTempLabel(NULL);
5431
5432       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5433
5434
5435       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5436
5437       /* Special cases */
5438       if((lit == 0) && (sign == 0)){
5439
5440         size--;
5441         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5442         while(size) 
5443           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5444
5445         genSkipz2(&rFalseIfx,0);
5446         if(ifx) ifx->generated = 1;
5447         return;
5448       }
5449
5450       if(size==1) {
5451         /* Special cases */
5452         lit &= 0xff;
5453         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5454           /* degenerate compare can never be true */
5455           if(rFalseIfx.condition == 0)
5456             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5457
5458           if(ifx) ifx->generated = 1;
5459           return;
5460         }
5461
5462         if(sign) {
5463           /* signed comparisons to a literal byte */
5464
5465           int lp1 = (lit+1) & 0xff;
5466
5467           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5468           switch (lp1) {
5469           case 0:
5470             rFalseIfx.condition ^= 1;
5471             genSkipCond(&rFalseIfx,right,0,7);
5472             break;
5473           case 0x7f:
5474             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5475             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5476             genSkipz2(&rFalseIfx,1);
5477             break;
5478           default:
5479             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5480             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5481             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5482             rFalseIfx.condition ^= 1;
5483             genSkipc(&rFalseIfx);
5484             break;
5485           }
5486         } else {
5487           /* unsigned comparisons to a literal byte */
5488
5489           switch(lit & 0xff ) {
5490           case 0:
5491             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5492             genSkipz2(&rFalseIfx,0);
5493             break;
5494           case 0x7f:
5495             rFalseIfx.condition ^= 1;
5496             genSkipCond(&rFalseIfx,right,0,7);
5497             break;
5498
5499           default:
5500             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5501             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5502             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5503             rFalseIfx.condition ^= 1;
5504             if (AOP_TYPE(result) == AOP_CRY)
5505               genSkipc(&rFalseIfx);
5506             else {
5507               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5508               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5509             }         
5510             break;
5511           }
5512         }
5513
5514         if(ifx) ifx->generated = 1;
5515         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5516                 goto check_carry;
5517         return;
5518
5519       } else {
5520
5521         /* Size is greater than 1 */
5522
5523         if(sign) {
5524           int lp1 = lit+1;
5525
5526           size--;
5527
5528           if(lp1 == 0) {
5529             /* this means lit = 0xffffffff, or -1 */
5530
5531
5532             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5533             rFalseIfx.condition ^= 1;
5534             genSkipCond(&rFalseIfx,right,size,7);
5535             if(ifx) ifx->generated = 1;
5536
5537             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5538               goto check_carry;
5539
5540             return;
5541           }
5542
5543           if(lit == 0) {
5544             int s = size;
5545
5546             if(rFalseIfx.condition) {
5547               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5548               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5549             }
5550
5551             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5552             while(size--)
5553               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5554
5555
5556             emitSKPZ;
5557             if(rFalseIfx.condition) {
5558               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5559               pic16_emitpLabel(truelbl->key);
5560             }else {
5561               rFalseIfx.condition ^= 1;
5562               genSkipCond(&rFalseIfx,right,s,7);
5563             }
5564
5565             if(ifx) ifx->generated = 1;
5566
5567             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5568               goto check_carry;
5569
5570             return;
5571           }
5572
5573           if((size == 1) &&  (0 == (lp1&0xff))) {
5574             /* lower byte of signed word is zero */
5575             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5576             i = ((lp1 >> 8) & 0xff) ^0x80;
5577             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5578             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5579             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5580
5581             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5582               emitTOGC;
5583               if(ifx) ifx->generated = 1;
5584               goto check_carry;
5585             } else {
5586               rFalseIfx.condition ^= 1;
5587               genSkipc(&rFalseIfx);
5588               if(ifx) ifx->generated = 1;
5589             }
5590
5591             return;
5592           }
5593
5594           if(lit & (0x80 << (size*8))) {
5595             /* Lit is less than zero */
5596             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5597             //rFalseIfx.condition ^= 1;
5598             //genSkipCond(&rFalseIfx,left,size,7);
5599             //rFalseIfx.condition ^= 1;
5600             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5601             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5602
5603             if(rFalseIfx.condition)
5604               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5605             else
5606               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5607
5608
5609           } else {
5610             /* Lit is greater than or equal to zero */
5611             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5612             //rFalseIfx.condition ^= 1;
5613             //genSkipCond(&rFalseIfx,right,size,7);
5614             //rFalseIfx.condition ^= 1;
5615
5616             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5617             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5618
5619             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5620             if(rFalseIfx.condition)
5621               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5622             else
5623               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5624
5625           }
5626
5627           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5628           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5629
5630           while(size--) {
5631
5632             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5633             emitSKPNZ;
5634             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5635           }
5636           rFalseIfx.condition ^= 1;
5637           //rFalseIfx.condition = 1;
5638           genSkipc(&rFalseIfx);
5639
5640           pic16_emitpLabel(truelbl->key);
5641
5642           if(ifx) ifx->generated = 1;
5643
5644
5645           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5646             goto check_carry;
5647
5648           return;
5649           // end of if (sign)
5650         } else {
5651
5652           /* compare word or long to an unsigned literal on the right.*/
5653
5654
5655           size--;
5656           if(lit < 0xff) {
5657             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5658             switch (lit) {
5659             case 0:
5660               break; /* handled above */
5661 /*
5662             case 0xff:
5663               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5664               while(size--)
5665                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5666               genSkipz2(&rFalseIfx,0);
5667               break;
5668 */
5669             default:
5670               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5671               while(--size)
5672                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5673
5674               emitSKPZ;
5675               if(rFalseIfx.condition)
5676                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5677               else
5678                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5679
5680
5681               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5682               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5683
5684               rFalseIfx.condition ^= 1;
5685               genSkipc(&rFalseIfx);
5686             }
5687
5688             pic16_emitpLabel(truelbl->key);
5689
5690             if(ifx) ifx->generated = 1;
5691
5692             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5693               goto check_carry;
5694
5695             return;
5696           }
5697
5698
5699           lit++;
5700           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5701           i = (lit >> (size*8)) & 0xff;
5702
5703           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5704           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5705
5706           while(size--) {
5707             i = (lit >> (size*8)) & 0xff;
5708
5709             if(i) {
5710               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5711               emitSKPNZ;
5712               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5713             } else {
5714               /* this byte of the lit is zero, 
5715                * if it's not the last then OR in the variable */
5716               if(size)
5717                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5718             }
5719           }
5720
5721
5722           pic16_emitpLabel(lbl->key);
5723
5724           rFalseIfx.condition ^= 1;
5725
5726           genSkipc(&rFalseIfx);
5727         }
5728
5729         if(sign)
5730           pic16_emitpLabel(truelbl->key);
5731         if(ifx) ifx->generated = 1;
5732
5733             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5734               goto check_carry;
5735
5736         return;
5737       }
5738     }
5739     /* Compare two variables */
5740
5741     DEBUGpic16_emitcode(";sign","%d",sign);
5742
5743     size--;
5744     if(sign) {
5745       /* Sigh. thus sucks... */
5746       if(size) {
5747         pCodeOp *pctemp;
5748         
5749         pctemp = pic16_popGetTempReg(1);
5750         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5751         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5752         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5753         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5754         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5755         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5756         pic16_popReleaseTempReg(pctemp, 1);
5757       } else {
5758         /* Signed char comparison */
5759         /* Special thanks to Nikolai Golovchenko for this snippet */
5760         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5761         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5762         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5763         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5764         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5765         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5766
5767         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5768         genSkipc(&rFalseIfx);
5769           
5770         if(ifx) ifx->generated = 1;
5771
5772             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5773               goto check_carry;
5774
5775         return;
5776       }
5777
5778     } else {
5779
5780       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5781       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5782     }
5783
5784
5785     /* The rest of the bytes of a multi-byte compare */
5786     while (size) {
5787
5788       emitSKPZ;
5789       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5790       size--;
5791
5792       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5793       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5794
5795
5796     }
5797
5798     pic16_emitpLabel(lbl->key);
5799
5800     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5801     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5802         (AOP_TYPE(result) == AOP_REG)) {
5803       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5804       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5805     } else {
5806       genSkipc(&rFalseIfx);
5807     }         
5808     //genSkipc(&rFalseIfx);
5809     if(ifx) ifx->generated = 1;
5810
5811
5812             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5813               goto check_carry;
5814
5815     return;
5816
5817   }
5818
5819 check_carry:
5820   if ((AOP_TYPE(result) != AOP_CRY) 
5821         && AOP_SIZE(result)) {
5822     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5823
5824     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5825
5826     pic16_outBitC(result);
5827   } else {
5828     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5829     /* if the result is used in the next
5830        ifx conditional branch then generate
5831        code a little differently */
5832     if (ifx )
5833       genIfxJump (ifx,"c");
5834     else
5835       pic16_outBitC(result);
5836     /* leave the result in acc */
5837   }
5838
5839 }
5840
5841 #elif 0 /* VR version of genCmp() */    /* } else { */
5842
5843 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5844 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5845         operand *result, int offset, int invert_op)
5846 {
5847   /* add code here */
5848   
5849   /* check condition, > or < ?? */
5850   if(rIfx->condition != 0)invert_op ^= 1;
5851   
5852   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5853
5854   if(!ifx)invert_op ^= 1;
5855
5856   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5857       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5858   
5859   /* do selection */
5860   if(!invert_op)return POC_CPFSGT;
5861   else return POC_CPFSLT;
5862 }
5863
5864 static int compareAopfirstpass=1;
5865
5866 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5867             operand *oper, int offset, operand *result,
5868             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5869             symbol *tlbl)
5870 {
5871   int op;
5872   symbol *truelbl;
5873
5874   /* invert if there is a result to be loaded, in order to fit,
5875    * SETC/CLRC sequence */
5876   if(AOP_SIZE(result))invert_op ^= 1;
5877
5878 //  if(sign && !offset)invert_op ^= 1;
5879   
5880 //  if(sign)invert_op ^= 1;
5881   
5882   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5883
5884   if(AOP_SIZE(result) && compareAopfirstpass) {
5885     if(!ifx) {
5886       if(pcop2)
5887         pic16_emitpcode(POC_SETF, pcop2);
5888       else
5889         emitSETC;
5890     } else {
5891       if(pcop2)
5892         pic16_emitpcode(POC_CLRF, pcop2);
5893       else
5894         emitCLRC;
5895     }
5896   }
5897
5898   compareAopfirstpass = 0;
5899
5900       /* there is a bug when comparing operands with size > 1,
5901        * because higher bytes can be equal and test should be performed
5902        * to the next lower byte, current algorithm, considers operands
5903        * inequal in these cases! -- VR 20041107 */
5904
5905     
5906   if(pcop)
5907     pic16_emitpcode(op, pcop);
5908   else
5909     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5910
5911
5912   if((!sign || !offset) && AOP_SIZE(result)) {
5913     if(!ifx) {
5914       if(pcop2)
5915         pic16_emitpcode(POC_CLRF, pcop2);
5916         else
5917         emitCLRC;
5918     } else {
5919       if(pcop2)
5920         pic16_emitpcode(POC_SETF, pcop2);
5921       else
5922         emitSETC;
5923     }
5924     
5925     /* don't emit final branch (offset == 0) */
5926     if(offset) {
5927
5928       if(pcop2)
5929         pic16_emitpcode(POC_RRCF, pcop2);
5930
5931       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5932     }
5933   } else {
5934     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5935       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5936             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5937
5938       truelbl = newiTempLabel( NULL );
5939       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5940       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5941         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5942       else
5943         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5944       pic16_emitpLabel(truelbl->key);
5945     } else {
5946       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5947     }
5948   }
5949 }
5950
5951 static void genCmp (operand *left, operand *right,
5952                     operand *result, iCode *ifx, int sign)
5953 {
5954   int size, cmpop=1;
5955   long lit = 0L;
5956   resolvedIfx rFalseIfx;
5957   symbol *falselbl, *tlbl;
5958
5959     FENTRY;
5960     
5961     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5962
5963     resolveIfx(&rFalseIfx, ifx);
5964     size = max(AOP_SIZE(left), AOP_SIZE(right));
5965     
5966     /* if left & right are bit variables */
5967     if(AOP_TYPE(left) == AOP_CRY
5968       && AOP_TYPE(right) == AOP_CRY ) {
5969
5970         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5971         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5972         
5973         werror(W_POSSBUG2, __FILE__, __LINE__);
5974         exit(-1);
5975     }
5976     
5977     /* if literal is on the right then swap with left */
5978     if((AOP_TYPE(right) == AOP_LIT)) {
5979       operand *tmp = right ;
5980 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5981
5982         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5983
5984 //      lit = (lit - 1) & mask;
5985         right = left;
5986         left = tmp;
5987         rFalseIfx.condition ^= 1;               /* reverse compare */
5988     } else
5989     if ((AOP_TYPE(left) == AOP_LIT)) {
5990       /* float compares are handled by support functions */
5991       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5992     }
5993
5994     /* actual comparing algorithm */
5995 //    size = AOP_SIZE( right );
5996
5997     falselbl = newiTempLabel( NULL );
5998     if(AOP_TYPE(left) == AOP_LIT) {
5999       /* compare to literal */
6000       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6001       
6002       if(sign) {
6003         pCodeOp *pct, *pct2;
6004         symbol *tlbl1;
6005
6006         /* signed compare */
6007         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6008
6009         /* using PRODL:PRODH as a temporary register here */
6010         pct = pic16_popCopyReg(&pic16_pc_prodl);
6011         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6012         tlbl = newiTempLabel( NULL );
6013         
6014         /* first compare signs:
6015          *  a. if both are positive, compare just like unsigned
6016          *  b. if both are negative, invert cmpop, compare just like unsigned
6017          *  c. if different signs, determine the result directly */
6018
6019         size--;
6020
6021 #if 1
6022         /* { */
6023         tlbl1 = newiTempLabel( NULL );
6024 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6025
6026         if(lit > 0) {
6027
6028           /* literal is zero or positive:
6029            *  a. if carry is zero, too, continue compare,
6030            *  b. if carry is set, then continue depending on cmpop ^ condition:
6031            *    1. '<' return false (literal < variable),
6032            *    2. '>' return true (literal > variable) */
6033 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6034           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6035           
6036           
6037           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6038           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6039         } else 
6040         if(lit < 0) {
6041           
6042           /* literal is negative:
6043            *  a. if carry is set, too, continue compare,
6044            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6045            *    1. '<' return true (literal < variable),
6046            *    2. '>' return false (literal > variable) */
6047 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6048           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6049           
6050           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6051           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6052         }
6053 #if 1
6054         else {
6055           /* lit == 0 */
6056           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6057           
6058           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6059           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6060         }
6061 #endif
6062         
6063         
6064         pic16_emitpLabel( tlbl1->key );
6065 #endif  /* } */
6066
6067         compareAopfirstpass=1;
6068 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6069 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6070 //        pic16_emitpcode(POC_MOVWF, pct);
6071
6072 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6073         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6074 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6075         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6076
6077         /* generic case */        
6078           while( size-- ) {
6079 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6080 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6081 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6082 //            pic16_emitpcode(POC_MOVWF, pct);
6083
6084 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6085             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6086             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6087 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6088 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6089           }
6090         
6091         if(ifx)ifx->generated = 1;
6092
6093         if(AOP_SIZE(result)) {
6094           pic16_emitpLabel(tlbl->key);
6095           pic16_emitpLabel(falselbl->key);
6096           pic16_outBitOp( result, pct2 );
6097         } else {
6098           pic16_emitpLabel(tlbl->key);
6099         }
6100       } else {
6101
6102         /* unsigned compare */      
6103         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6104     
6105         compareAopfirstpass=1;
6106         while(size--) {
6107           
6108           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6109           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6110
6111         }
6112         if(ifx)ifx->generated = 1;
6113
6114         if(AOP_SIZE(result)) {
6115           pic16_emitpLabel(falselbl->key);
6116           pic16_outBitC( result );
6117         }
6118
6119       }
6120     } else {
6121       /* compare registers */
6122       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6123
6124
6125       if(sign) {
6126         pCodeOp *pct, *pct2;
6127         
6128         /* signed compare */
6129         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6130
6131         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6132         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6133         tlbl = newiTempLabel( NULL );
6134         
6135         compareAopfirstpass=1;
6136
6137         size--;
6138         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6139 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6140         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6141         pic16_emitpcode(POC_MOVWF, pct);
6142
6143         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6144 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6145         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6146
6147         /* WREG already holds left + 0x80 */
6148         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6149         
6150         while( size-- ) {
6151           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6152 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6153           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6154           pic16_emitpcode(POC_MOVWF, pct);
6155                 
6156           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6157 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6158           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6159
6160           /* WREG already holds left + 0x80 */
6161           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6162 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6163         }
6164         
6165         if(ifx)ifx->generated = 1;
6166
6167         if(AOP_SIZE(result)) {
6168           pic16_emitpLabel(tlbl->key);
6169           pic16_emitpLabel(falselbl->key);
6170           pic16_outBitOp( result, pct2 );
6171         } else {
6172           pic16_emitpLabel(tlbl->key);
6173         }
6174
6175       } else {
6176         /* unsigned compare */      
6177         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6178
6179         compareAopfirstpass=1;
6180         while(size--) {
6181           
6182           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6183           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6184
6185         }
6186
6187         if(ifx)ifx->generated = 1;
6188         if(AOP_SIZE(result)) {
6189
6190           pic16_emitpLabel(falselbl->key);
6191           pic16_outBitC( result );
6192         }
6193
6194       }
6195     }
6196 }
6197
6198 #endif  /* } */
6199
6200
6201
6202 /*-----------------------------------------------------------------*/
6203 /* genCmpGt :- greater than comparison                             */
6204 /*-----------------------------------------------------------------*/
6205 static void genCmpGt (iCode *ic, iCode *ifx)
6206 {
6207   operand *left, *right, *result;
6208   sym_link *letype , *retype;
6209   int sign ;
6210
6211     FENTRY;
6212     
6213     left = IC_LEFT(ic);
6214     right= IC_RIGHT(ic);
6215     result = IC_RESULT(ic);
6216
6217     letype = getSpec(operandType(left));
6218     retype =getSpec(operandType(right));
6219     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6220     /* assign the amsops */
6221     pic16_aopOp (left,ic,FALSE);
6222     pic16_aopOp (right,ic,FALSE);
6223     pic16_aopOp (result,ic,TRUE);
6224
6225     genCmp(right, left, result, ifx, sign);
6226
6227     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6228     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6229     pic16_freeAsmop(result,NULL,ic,TRUE); 
6230 }
6231
6232 /*-----------------------------------------------------------------*/
6233 /* genCmpLt - less than comparisons                                */
6234 /*-----------------------------------------------------------------*/
6235 static void genCmpLt (iCode *ic, iCode *ifx)
6236 {
6237   operand *left, *right, *result;
6238   sym_link *letype , *retype;
6239   int sign ;
6240
6241     FENTRY;
6242
6243     left = IC_LEFT(ic);
6244     right= IC_RIGHT(ic);
6245     result = IC_RESULT(ic);
6246
6247     letype = getSpec(operandType(left));
6248     retype =getSpec(operandType(right));
6249     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6250
6251     /* assign the amsops */
6252     pic16_aopOp (left,ic,FALSE);
6253     pic16_aopOp (right,ic,FALSE);
6254     pic16_aopOp (result,ic,TRUE);
6255
6256     genCmp(left, right, result, ifx, sign);
6257
6258     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6259     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6260     pic16_freeAsmop(result,NULL,ic,TRUE); 
6261 }
6262
6263 #if 0
6264 // not needed ATM
6265 // FIXME reenable literal optimisation when the pic16 port is stable
6266
6267 /*-----------------------------------------------------------------*/
6268 /* genc16bit2lit - compare a 16 bit value to a literal             */
6269 /*-----------------------------------------------------------------*/
6270 static void genc16bit2lit(operand *op, int lit, int offset)
6271 {
6272   int i;
6273
6274   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6275   if( (lit&0xff) == 0) 
6276     i=1;
6277   else
6278     i=0;
6279
6280   switch( BYTEofLONG(lit,i)) { 
6281   case 0:
6282     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6283     break;
6284   case 1:
6285     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6286     break;
6287   case 0xff:
6288     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6289     break;
6290   default:
6291     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6292     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6293   }
6294
6295   i ^= 1;
6296
6297   switch( BYTEofLONG(lit,i)) { 
6298   case 0:
6299     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6300     break;
6301   case 1:
6302     emitSKPNZ;
6303     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6304     break;
6305   case 0xff:
6306     emitSKPNZ;
6307     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6308     break;
6309   default:
6310     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6311     emitSKPNZ;
6312     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6313
6314   }
6315
6316 }
6317 #endif
6318
6319 #if 0
6320 // not needed ATM
6321 /*-----------------------------------------------------------------*/
6322 /* gencjneshort - compare and jump if not equal                    */
6323 /*-----------------------------------------------------------------*/
6324 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6325 {
6326   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6327   int offset = 0;
6328   int res_offset = 0;  /* the result may be a different size then left or right */
6329   int res_size = AOP_SIZE(result);
6330   resolvedIfx rIfx;
6331   symbol *lbl, *lbl_done;
6332
6333   unsigned long lit = 0L;
6334   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6335
6336   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6337   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6338   if(result)
6339     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6340   resolveIfx(&rIfx,ifx);
6341   lbl =  newiTempLabel(NULL);
6342   lbl_done =  newiTempLabel(NULL);
6343
6344
6345   /* if the left side is a literal or 
6346      if the right is in a pointer register and left 
6347      is not */
6348   if ((AOP_TYPE(left) == AOP_LIT) || 
6349       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6350     operand *t = right;
6351     right = left;
6352     left = t;
6353   }
6354   if(AOP_TYPE(right) == AOP_LIT)
6355     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6356
6357   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6358     preserve_result = 1;
6359
6360   if(result && !preserve_result)
6361     {
6362       int i;
6363       for(i = 0; i < AOP_SIZE(result); i++)
6364         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6365     }
6366
6367
6368   /* if the right side is a literal then anything goes */
6369   if (AOP_TYPE(right) == AOP_LIT &&
6370       AOP_TYPE(left) != AOP_DIR ) {
6371     switch(size) {
6372     case 2:
6373       genc16bit2lit(left, lit, 0);
6374       emitSKPZ;
6375       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6376       break;
6377     default:
6378       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6379       while (size--) {
6380         if(lit & 0xff) {
6381           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6382           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6383         } else {
6384           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6385         }
6386
6387         emitSKPZ;
6388         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6389         offset++;
6390         if(res_offset < res_size-1)
6391           res_offset++;
6392         lit >>= 8;
6393       }
6394       break;
6395     }
6396   }
6397
6398   /* if the right side is in a register or in direct space or
6399      if the left is a pointer register & right is not */    
6400   else if (AOP_TYPE(right) == AOP_REG ||
6401            AOP_TYPE(right) == AOP_DIR || 
6402            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6403            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6404     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6405     int lbl_key = lbl->key;
6406
6407     if(result) {
6408       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6409       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6410     }else {
6411       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6412       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6413               __FUNCTION__,__LINE__);
6414       return;
6415     }
6416    
6417 /*     switch(size) { */
6418 /*     case 2: */
6419 /*       genc16bit2lit(left, lit, 0); */
6420 /*       emitSKPNZ; */
6421 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6422 /*       break; */
6423 /*     default: */
6424     while (size--) {
6425       int emit_skip=1;
6426       if((AOP_TYPE(left) == AOP_DIR) && 
6427          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6428
6429         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6430         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6431
6432       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6433             
6434         switch (lit & 0xff) {
6435         case 0:
6436           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6437           break;
6438         case 1:
6439           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6440           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6441           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6442           emit_skip=0;
6443           break;
6444         case 0xff:
6445           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6446           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6447           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6448           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6449           emit_skip=0;
6450           break;
6451         default:
6452           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6453           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6454         }
6455         lit >>= 8;
6456
6457       } else {
6458         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6459       }
6460       if(emit_skip) {
6461         if(AOP_TYPE(result) == AOP_CRY) {
6462           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6463           if(rIfx.condition)
6464             emitSKPNZ;
6465           else
6466             emitSKPZ;
6467           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6468         } else {
6469           /* fix me. probably need to check result size too */
6470           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6471           if(rIfx.condition)
6472             emitSKPZ;
6473           else
6474             emitSKPNZ;
6475           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6476           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6477         }
6478         if(ifx)
6479           ifx->generated=1;
6480       }
6481       emit_skip++;
6482       offset++;
6483       if(res_offset < res_size-1)
6484         res_offset++;
6485     }
6486 /*       break; */
6487 /*     } */
6488   } else if(AOP_TYPE(right) == AOP_REG &&
6489             AOP_TYPE(left) != AOP_DIR){
6490
6491     while(size--) {
6492       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6493       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6494       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6495       if(rIfx.condition)
6496         emitSKPNZ;
6497       else
6498         emitSKPZ;
6499       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6500       offset++;
6501       if(res_offset < res_size-1)
6502         res_offset++;
6503     }
6504       
6505   }else{
6506     /* right is a pointer reg need both a & b */
6507     while(size--) {
6508       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6509       if(strcmp(l,"b"))
6510         pic16_emitcode("mov","b,%s",l);
6511       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6512       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6513       offset++;
6514     }
6515   }
6516
6517   if(result && preserve_result)
6518     {
6519       int i;
6520       for(i = 0; i < AOP_SIZE(result); i++)
6521         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6522     }
6523
6524   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6525
6526   if(result && preserve_result)
6527     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6528
6529   if(!rIfx.condition)
6530     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6531
6532   pic16_emitpLabel(lbl->key);
6533
6534   if(result && preserve_result)
6535     {
6536       int i;
6537       for(i = 0; i < AOP_SIZE(result); i++)
6538         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6539
6540       pic16_emitpLabel(lbl_done->key);
6541    }
6542
6543   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6544
6545   if(ifx)
6546     ifx->generated = 1;
6547 }
6548 #endif
6549
6550 #if 0
6551 /*-----------------------------------------------------------------*/
6552 /* gencjne - compare and jump if not equal                         */
6553 /*-----------------------------------------------------------------*/
6554 static void gencjne(operand *left, operand *right, iCode *ifx)
6555 {
6556     symbol *tlbl  = newiTempLabel(NULL);
6557
6558     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6559     gencjneshort(left, right, lbl);
6560
6561     pic16_emitcode("mov","a,%s",one);
6562     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6563     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6564     pic16_emitcode("clr","a");
6565     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6566
6567     pic16_emitpLabel(lbl->key);
6568     pic16_emitpLabel(tlbl->key);
6569
6570 }
6571 #endif
6572
6573
6574 /*-----------------------------------------------------------------*/
6575 /* is_LitOp - check if operand has to be treated as literal        */
6576 /*-----------------------------------------------------------------*/
6577 static bool is_LitOp(operand *op)
6578 {
6579   return ((AOP_TYPE(op) == AOP_LIT)
6580       || ( (AOP_TYPE(op) == AOP_PCODE)
6581           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6582               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6583 }
6584
6585 /*-----------------------------------------------------------------*/
6586 /* is_LitAOp - check if operand has to be treated as literal        */
6587 /*-----------------------------------------------------------------*/
6588 static bool is_LitAOp(asmop *aop)
6589 {
6590   return ((aop->type == AOP_LIT)
6591       || ( (aop->type == AOP_PCODE)
6592           && ( (aop->aopu.pcop->type == PO_LITERAL)
6593               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6594 }
6595
6596
6597
6598 /*-----------------------------------------------------------------*/
6599 /* genCmpEq - generates code for equal to                          */
6600 /*-----------------------------------------------------------------*/
6601 static void genCmpEq (iCode *ic, iCode *ifx)
6602 {
6603   operand *left, *right, *result;
6604   symbol *falselbl = newiTempLabel(NULL);
6605   symbol *donelbl = newiTempLabel(NULL);
6606
6607   int preserve_result = 0;
6608   int generate_result = 0;
6609   int i=0;
6610   unsigned long lit = -1;
6611
6612   FENTRY;
6613   
6614   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6615   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6616   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6617  
6618   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6619
6620   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6621     {
6622       werror(W_POSSBUG2, __FILE__, __LINE__);
6623       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6624       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6625       goto release;
6626     }
6627
6628   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6629     {
6630       operand *tmp = right ;
6631       right = left;
6632       left = tmp;
6633     }
6634
6635   if (AOP_TYPE(right) == AOP_LIT) {
6636     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6637   }
6638
6639   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6640     preserve_result = 1;
6641
6642   if(result && AOP_SIZE(result))
6643     generate_result = 1;
6644
6645   if(generate_result && !preserve_result)
6646     {
6647       for(i = 0; i < AOP_SIZE(result); i++)
6648         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6649     }
6650
6651   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6652   for(i=0; i < AOP_SIZE(left); i++)
6653     {
6654       if(AOP_TYPE(left) != AOP_ACC)
6655         {
6656           if(is_LitOp(left))
6657             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6658           else
6659             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6660         }
6661       if(is_LitOp(right)) {
6662         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6663           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6664         }
6665       } else
6666         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6667
6668       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6669     }
6670
6671   // result == true
6672
6673   if(generate_result && preserve_result)
6674     {
6675       for(i = 0; i < AOP_SIZE(result); i++)
6676         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6677     }
6678
6679   if(generate_result)
6680     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6681
6682   if(generate_result && preserve_result)
6683     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6684
6685   if(ifx && IC_TRUE(ifx))
6686     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6687
6688   if(ifx && IC_FALSE(ifx))
6689     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6690
6691   pic16_emitpLabel(falselbl->key);
6692
6693   // result == false
6694
6695   if(ifx && IC_FALSE(ifx))
6696     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6697
6698   if(generate_result && preserve_result)
6699     {
6700       for(i = 0; i < AOP_SIZE(result); i++)
6701         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6702     }
6703
6704   pic16_emitpLabel(donelbl->key);
6705
6706   if(ifx)
6707     ifx->generated = 1;
6708
6709 release:
6710   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6711   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6712   pic16_freeAsmop(result,NULL,ic,TRUE);
6713
6714 }
6715
6716
6717 #if 0
6718 // old version kept for reference
6719
6720 /*-----------------------------------------------------------------*/
6721 /* genCmpEq - generates code for equal to                          */
6722 /*-----------------------------------------------------------------*/
6723 static void genCmpEq (iCode *ic, iCode *ifx)
6724 {
6725     operand *left, *right, *result;
6726     unsigned long lit = 0L;
6727     int size,offset=0;
6728     symbol *falselbl  = newiTempLabel(NULL);
6729
6730
6731     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6732
6733     if(ifx)
6734       DEBUGpic16_emitcode ("; ifx is non-null","");
6735     else
6736       DEBUGpic16_emitcode ("; ifx is null","");
6737
6738     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6739     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6740     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6741
6742     size = max(AOP_SIZE(left),AOP_SIZE(right));
6743
6744     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6745
6746     /* if literal, literal on the right or 
6747     if the right is in a pointer register and left 
6748     is not */
6749     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6750         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6751       operand *tmp = right ;
6752       right = left;
6753       left = tmp;
6754     }
6755
6756
6757     if(ifx && !AOP_SIZE(result)){
6758         symbol *tlbl;
6759         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6760         /* if they are both bit variables */
6761         if (AOP_TYPE(left) == AOP_CRY &&
6762             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6763                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6764             if(AOP_TYPE(right) == AOP_LIT){
6765                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6766                 if(lit == 0L){
6767                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6768                     pic16_emitcode("cpl","c");
6769                 } else if(lit == 1L) {
6770                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6771                 } else {
6772                     pic16_emitcode("clr","c");
6773                 }
6774                 /* AOP_TYPE(right) == AOP_CRY */
6775             } else {
6776                 symbol *lbl = newiTempLabel(NULL);
6777                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6778                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6779                 pic16_emitcode("cpl","c");
6780                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6781             }
6782             /* if true label then we jump if condition
6783             supplied is true */
6784             tlbl = newiTempLabel(NULL);
6785             if ( IC_TRUE(ifx) ) {
6786                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6787                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6788             } else {
6789                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6790                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6791             }
6792             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6793
6794                 {
6795                 /* left and right are both bit variables, result is carry */
6796                         resolvedIfx rIfx;
6797               
6798                         resolveIfx(&rIfx,ifx);
6799
6800                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6801                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6802                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6803                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6804                         genSkipz2(&rIfx,0);
6805                 }
6806         } else {
6807
6808                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6809
6810                         /* They're not both bit variables. Is the right a literal? */
6811                         if(AOP_TYPE(right) == AOP_LIT) {
6812                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6813             
6814                         switch(size) {
6815
6816                                 case 1:
6817                                         switch(lit & 0xff) {
6818                                                 case 1:
6819                                                                 if ( IC_TRUE(ifx) ) {
6820                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6821                                                                         emitSKPNZ;
6822                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6823                                                                 } else {
6824                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6825                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6826                                                                 }
6827                                                                 break;
6828                                                 case 0xff:
6829                                                                 if ( IC_TRUE(ifx) ) {
6830                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6831                                                                         emitSKPNZ;
6832                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6833                                                                 } else {
6834                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6835                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6836                                                                 }
6837                                                                 break;
6838                                                 default:
6839                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6840                                                                 if(lit)
6841                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6842                                                                 genSkip(ifx,'z');
6843                                         } // switch lit
6844
6845
6846                                         /* end of size == 1 */
6847                                         break;
6848               
6849                                 case 2:
6850                                         genc16bit2lit(left,lit,offset);
6851                                         genSkip(ifx,'z');
6852                                         break;
6853                                         /* end of size == 2 */
6854
6855                                 default:
6856                                         /* size is 4 */
6857                                         if(lit==0) {
6858                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6859                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6860                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6861                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6862                                                 genSkip(ifx,'z');
6863                                         } else {
6864                                                 /* search for patterns that can be optimized */
6865
6866                                                 genc16bit2lit(left,lit,0);
6867                                                 lit >>= 16;
6868                                                 if(lit) {
6869                                                                 if(IC_TRUE(ifx))
6870                                                                 emitSKPZ; // if hi word unequal
6871                                                                 else
6872                                                                 emitSKPNZ; // if hi word equal
6873                                                                 // fail early
6874                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6875                                                         genc16bit2lit(left,lit,2);
6876                                                         genSkip(ifx,'z');
6877                                                 } else {
6878                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6879                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6880                                                         genSkip(ifx,'z');
6881                                                 }
6882                                         }
6883                                                 pic16_emitpLabel(falselbl->key);
6884                                                 break;
6885
6886                         } // switch size
6887           
6888                         ifx->generated = 1;
6889                         goto release ;
6890             
6891
6892           } else if(AOP_TYPE(right) == AOP_CRY ) {
6893             /* we know the left is not a bit, but that the right is */
6894             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6895             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6896                       pic16_popGet(AOP(right),offset));
6897             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6898
6899             /* if the two are equal, then W will be 0 and the Z bit is set
6900              * we could test Z now, or go ahead and check the high order bytes if
6901              * the variable we're comparing is larger than a byte. */
6902
6903             while(--size)
6904               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6905
6906             if ( IC_TRUE(ifx) ) {
6907               emitSKPNZ;
6908               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6909               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6910             } else {
6911               emitSKPZ;
6912               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6913               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6914             }
6915
6916           } else {
6917             /* They're both variables that are larger than bits */
6918             int s = size;
6919
6920             tlbl = newiTempLabel(NULL);
6921
6922             while(size--) {
6923               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6924               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6925
6926               if ( IC_TRUE(ifx) ) {
6927                 if(size) {
6928                   emitSKPZ;
6929                 
6930                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6931
6932                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6933                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6934                 } else {
6935                   emitSKPNZ;
6936
6937                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6938
6939
6940                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6941                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6942                 }
6943               } else {
6944                 emitSKPZ;
6945
6946                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6947
6948                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6949                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6950               }
6951               offset++;
6952             }
6953             if(s>1 && IC_TRUE(ifx)) {
6954               pic16_emitpLabel(tlbl->key);
6955               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6956             }
6957           }
6958         }
6959         /* mark the icode as generated */
6960         ifx->generated = 1;
6961         goto release ;
6962     }
6963
6964     /* if they are both bit variables */
6965     if (AOP_TYPE(left) == AOP_CRY &&
6966         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6967         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6968         if(AOP_TYPE(right) == AOP_LIT){
6969             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6970             if(lit == 0L){
6971                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6972                 pic16_emitcode("cpl","c");
6973             } else if(lit == 1L) {
6974                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6975             } else {
6976                 pic16_emitcode("clr","c");
6977             }
6978             /* AOP_TYPE(right) == AOP_CRY */
6979         } else {
6980             symbol *lbl = newiTempLabel(NULL);
6981             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6982             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6983             pic16_emitcode("cpl","c");
6984             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6985         }
6986         /* c = 1 if egal */
6987         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6988             pic16_outBitC(result);
6989             goto release ;
6990         }
6991         if (ifx) {
6992             genIfxJump (ifx,"c");
6993             goto release ;
6994         }
6995         /* if the result is used in an arithmetic operation
6996         then put the result in place */
6997         pic16_outBitC(result);
6998     } else {
6999       
7000       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7001       gencjne(left,right,result,ifx);
7002 /*
7003       if(ifx) 
7004         gencjne(left,right,newiTempLabel(NULL));
7005       else {
7006         if(IC_TRUE(ifx)->key)
7007           gencjne(left,right,IC_TRUE(ifx)->key);
7008         else
7009           gencjne(left,right,IC_FALSE(ifx)->key);
7010         ifx->generated = 1;
7011         goto release ;
7012       }
7013       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7014         pic16_aopPut(AOP(result),"a",0);
7015         goto release ;
7016       }
7017
7018       if (ifx) {
7019         genIfxJump (ifx,"a");
7020         goto release ;
7021       }
7022 */
7023       /* if the result is used in an arithmetic operation
7024          then put the result in place */
7025 /*
7026       if (AOP_TYPE(result) != AOP_CRY) 
7027         pic16_outAcc(result);
7028 */
7029       /* leave the result in acc */
7030     }
7031
7032 release:
7033     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7034     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7035     pic16_freeAsmop(result,NULL,ic,TRUE);
7036 }
7037 #endif
7038
7039 /*-----------------------------------------------------------------*/
7040 /* ifxForOp - returns the icode containing the ifx for operand     */
7041 /*-----------------------------------------------------------------*/
7042 static iCode *ifxForOp ( operand *op, iCode *ic )
7043 {
7044   FENTRY2;
7045
7046     /* if true symbol then needs to be assigned */
7047     if (IS_TRUE_SYMOP(op))
7048         return NULL ;
7049
7050     /* if this has register type condition and
7051     the next instruction is ifx with the same operand
7052     and live to of the operand is upto the ifx only then */
7053     if (ic->next
7054         && ic->next->op == IFX
7055         && IC_COND(ic->next)->key == op->key
7056         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7057         ) {
7058                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7059           return ic->next;
7060     }
7061
7062     /*
7063     if (ic->next &&
7064         ic->next->op == IFX &&
7065         IC_COND(ic->next)->key == op->key) {
7066       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7067       return ic->next;
7068     }
7069     */
7070
7071     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7072     if (ic->next &&
7073         ic->next->op == IFX)
7074       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7075
7076     if (ic->next &&
7077         ic->next->op == IFX &&
7078         IC_COND(ic->next)->key == op->key) {
7079       DEBUGpic16_emitcode ("; "," key is okay");
7080       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7081                            OP_SYMBOL(op)->liveTo,
7082                            ic->next->seq);
7083     }
7084
7085 #if 0
7086     /* the code below is completely untested
7087      * it just allows ulong2fs.c compile -- VR */
7088          
7089     ic = ic->next;
7090     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7091                                         __FILE__, __FUNCTION__, __LINE__);
7092         
7093     /* if this has register type condition and
7094     the next instruction is ifx with the same operand
7095     and live to of the operand is upto the ifx only then */
7096     if (ic->next &&
7097         ic->next->op == IFX &&
7098         IC_COND(ic->next)->key == op->key &&
7099         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7100         return ic->next;
7101
7102     if (ic->next &&
7103         ic->next->op == IFX &&
7104         IC_COND(ic->next)->key == op->key) {
7105       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7106       return ic->next;
7107     }
7108
7109     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7110                                         __FILE__, __FUNCTION__, __LINE__);
7111
7112 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7113 #endif
7114
7115     return NULL;
7116 }
7117 /*-----------------------------------------------------------------*/
7118 /* genAndOp - for && operation                                     */
7119 /*-----------------------------------------------------------------*/
7120 static void genAndOp (iCode *ic)
7121 {
7122   operand *left,*right, *result;
7123 /*     symbol *tlbl; */
7124
7125     FENTRY;
7126
7127     /* note here that && operations that are in an
7128     if statement are taken away by backPatchLabels
7129     only those used in arthmetic operations remain */
7130     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7131     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7132     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7133
7134     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7135
7136     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7137     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7138     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7139
7140     /* if both are bit variables */
7141 /*     if (AOP_TYPE(left) == AOP_CRY && */
7142 /*         AOP_TYPE(right) == AOP_CRY ) { */
7143 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7144 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7145 /*         pic16_outBitC(result); */
7146 /*     } else { */
7147 /*         tlbl = newiTempLabel(NULL); */
7148 /*         pic16_toBoolean(left);     */
7149 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7150 /*         pic16_toBoolean(right); */
7151 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7152 /*         pic16_outBitAcc(result); */
7153 /*     } */
7154
7155     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7156     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7157     pic16_freeAsmop(result,NULL,ic,TRUE);
7158 }
7159
7160
7161 /*-----------------------------------------------------------------*/
7162 /* genOrOp - for || operation                                      */
7163 /*-----------------------------------------------------------------*/
7164 /*
7165   tsd pic port -
7166   modified this code, but it doesn't appear to ever get called
7167 */
7168
7169 static void genOrOp (iCode *ic)
7170 {
7171   operand *left,*right, *result;
7172   symbol *tlbl;
7173
7174     FENTRY;  
7175
7176   /* note here that || operations that are in an
7177     if statement are taken away by backPatchLabels
7178     only those used in arthmetic operations remain */
7179     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7180     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7181     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7182
7183     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7184
7185     /* if both are bit variables */
7186     if (AOP_TYPE(left) == AOP_CRY &&
7187         AOP_TYPE(right) == AOP_CRY ) {
7188       pic16_emitcode("clrc","");
7189       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7190                AOP(left)->aopu.aop_dir,
7191                AOP(left)->aopu.aop_dir);
7192       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7193                AOP(right)->aopu.aop_dir,
7194                AOP(right)->aopu.aop_dir);
7195       pic16_emitcode("setc","");
7196
7197     } else {
7198         tlbl = newiTempLabel(NULL);
7199         pic16_toBoolean(left);
7200         emitSKPZ;
7201         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7202         pic16_toBoolean(right);
7203         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7204
7205         pic16_outBitAcc(result);
7206     }
7207
7208     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7209     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7210     pic16_freeAsmop(result,NULL,ic,TRUE);            
7211 }
7212
7213 /*-----------------------------------------------------------------*/
7214 /* isLiteralBit - test if lit == 2^n                               */
7215 /*-----------------------------------------------------------------*/
7216 static int isLiteralBit(unsigned long lit)
7217 {
7218     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7219     0x100L,0x200L,0x400L,0x800L,
7220     0x1000L,0x2000L,0x4000L,0x8000L,
7221     0x10000L,0x20000L,0x40000L,0x80000L,
7222     0x100000L,0x200000L,0x400000L,0x800000L,
7223     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7224     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7225     int idx;
7226     
7227     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7228     for(idx = 0; idx < 32; idx++)
7229         if(lit == pw[idx])
7230             return idx+1;
7231     return 0;
7232 }
7233
7234 /*-----------------------------------------------------------------*/
7235 /* continueIfTrue -                                                */
7236 /*-----------------------------------------------------------------*/
7237 static void continueIfTrue (iCode *ic)
7238 {
7239   FENTRY;
7240   if(IC_TRUE(ic))
7241     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7242   ic->generated = 1;
7243 }
7244
7245 /*-----------------------------------------------------------------*/
7246 /* jmpIfTrue -                                                     */
7247 /*-----------------------------------------------------------------*/
7248 static void jumpIfTrue (iCode *ic)
7249 {
7250   FENTRY;
7251   if(!IC_TRUE(ic))
7252     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7253   ic->generated = 1;
7254 }
7255
7256 /*-----------------------------------------------------------------*/
7257 /* jmpTrueOrFalse -                                                */
7258 /*-----------------------------------------------------------------*/
7259 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7260 {
7261   // ugly but optimized by peephole
7262   FENTRY;
7263   if(IC_TRUE(ic)){
7264     symbol *nlbl = newiTempLabel(NULL);
7265       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7266       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7267       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7268       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7269   } else {
7270     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7271     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7272   }
7273   ic->generated = 1;
7274 }
7275
7276 /*-----------------------------------------------------------------*/
7277 /* genAnd  - code for and                                          */
7278 /*-----------------------------------------------------------------*/
7279 static void genAnd (iCode *ic, iCode *ifx)
7280 {
7281   operand *left, *right, *result;
7282   int size, offset=0;  
7283   unsigned long lit = 0L;
7284   int bytelit = 0;
7285   resolvedIfx rIfx;
7286
7287     FENTRY;
7288     
7289   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7290   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7291   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7292
7293   resolveIfx(&rIfx,ifx);
7294
7295   /* if left is a literal & right is not then exchange them */
7296   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7297       AOP_NEEDSACC(left)) {
7298     operand *tmp = right ;
7299     right = left;
7300     left = tmp;
7301   }
7302
7303   /* if result = right then exchange them */
7304   if(pic16_sameRegs(AOP(result),AOP(right))){
7305     operand *tmp = right ;
7306     right = left;
7307     left = tmp;
7308   }
7309
7310   /* if right is bit then exchange them */
7311   if (AOP_TYPE(right) == AOP_CRY &&
7312       AOP_TYPE(left) != AOP_CRY){
7313     operand *tmp = right ;
7314     right = left;
7315     left = tmp;
7316   }
7317   if(AOP_TYPE(right) == AOP_LIT)
7318     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7319
7320   size = AOP_SIZE(result);
7321
7322   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7323
7324   // if(bit & yy)
7325   // result = bit & yy;
7326   if (AOP_TYPE(left) == AOP_CRY){
7327     // c = bit & literal;
7328     if(AOP_TYPE(right) == AOP_LIT){
7329       if(lit & 1) {
7330         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7331           // no change
7332           goto release;
7333         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7334       } else {
7335         // bit(result) = 0;
7336         if(size && (AOP_TYPE(result) == AOP_CRY)){
7337           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7338           goto release;
7339         }
7340         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7341           jumpIfTrue(ifx);
7342           goto release;
7343         }
7344         pic16_emitcode("clr","c");
7345       }
7346     } else {
7347       if (AOP_TYPE(right) == AOP_CRY){
7348         // c = bit & bit;
7349         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7350         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7351       } else {
7352         // c = bit & val;
7353         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7354         // c = lsb
7355         pic16_emitcode("rrc","a");
7356         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7357       }
7358     }
7359     // bit = c
7360     // val = c
7361     if(size)
7362       pic16_outBitC(result);
7363     // if(bit & ...)
7364     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7365       genIfxJump(ifx, "c");           
7366     goto release ;
7367   }
7368
7369   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7370   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7371   if((AOP_TYPE(right) == AOP_LIT) &&
7372      (AOP_TYPE(result) == AOP_CRY) &&
7373      (AOP_TYPE(left) != AOP_CRY)){
7374     int posbit = isLiteralBit(lit);
7375     /* left &  2^n */
7376     if(posbit){
7377       posbit--;
7378       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7379       // bit = left & 2^n
7380       if(size)
7381         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7382       // if(left &  2^n)
7383       else{
7384         if(ifx){
7385 /*
7386           if(IC_TRUE(ifx)) {
7387             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7388             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7389           } else {
7390             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7391             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7392           }
7393 */
7394         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7395         size = AOP_SIZE(left);
7396
7397         {
7398           int bp = posbit, ofs=0;
7399           
7400             while(bp > 7) {
7401               bp -= 8;
7402               ofs++;
7403             }
7404
7405           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7406                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7407
7408         }
7409 /*
7410           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7411                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7412 */
7413           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7414           
7415           ifx->generated = 1;
7416         }
7417         goto release;
7418       }
7419     } else {
7420       symbol *tlbl = newiTempLabel(NULL);
7421       int sizel = AOP_SIZE(left);
7422
7423       if(size)
7424         emitSETC;
7425
7426       while(sizel--) {
7427         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7428
7429           /* patch provided by Aaron Colwell */
7430           if((posbit = isLiteralBit(bytelit)) != 0) {
7431               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7432                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7433                                                 (posbit-1),0, PO_GPR_REGISTER));
7434
7435               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7436 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7437           } else {
7438               if (bytelit == 0xff) {
7439                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7440                    * a peephole could optimize it out -- VR */
7441                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7442               } else {
7443                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7444                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7445               }
7446
7447               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7448                             pic16_popGetLabel(tlbl->key));
7449           }
7450         
7451 #if 0
7452           /* old code, left here for reference -- VR 09/2004 */
7453           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7454           // byte ==  2^n ?
7455           if((posbit = isLiteralBit(bytelit)) != 0)
7456             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7457           else{
7458             if(bytelit != 0x0FFL)
7459               pic16_emitcode("anl","a,%s",
7460                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7461             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7462           }
7463 #endif
7464         }
7465         offset++;
7466       }
7467       // bit = left & literal
7468       if(size) {
7469         emitCLRC;
7470         pic16_emitpLabel(tlbl->key);
7471       }
7472       // if(left & literal)
7473       else {
7474         if(ifx) {
7475           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7476           ifx->generated = 1;
7477         }
7478         pic16_emitpLabel(tlbl->key);
7479         goto release;
7480       }
7481     }
7482
7483     pic16_outBitC(result);
7484     goto release ;
7485   }
7486
7487   /* if left is same as result */
7488   if(pic16_sameRegs(AOP(result),AOP(left))){
7489     int know_W = -1;
7490     for(;size--; offset++,lit>>=8) {
7491       if(AOP_TYPE(right) == AOP_LIT){
7492         switch(lit & 0xff) {
7493         case 0x00:
7494           /*  and'ing with 0 has clears the result */
7495 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7496           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7497           break;
7498         case 0xff:
7499           /* and'ing with 0xff is a nop when the result and left are the same */
7500           break;
7501
7502         default:
7503           {
7504             int p = pic16_my_powof2( (~lit) & 0xff );
7505             if(p>=0) {
7506               /* only one bit is set in the literal, so use a bcf instruction */
7507 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7508               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7509
7510             } else {
7511               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7512               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7513               if(know_W != (lit&0xff))
7514                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7515               know_W = lit &0xff;
7516               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7517             }
7518           }    
7519         }
7520       } else {
7521         if (AOP_TYPE(left) == AOP_ACC) {
7522           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7523         } else {                    
7524           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7525           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7526
7527         }
7528       }
7529     }
7530
7531   } else {
7532     // left & result in different registers
7533     if(AOP_TYPE(result) == AOP_CRY){
7534       // result = bit
7535       // if(size), result in bit
7536       // if(!size && ifx), conditional oper: if(left & right)
7537       symbol *tlbl = newiTempLabel(NULL);
7538       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7539       if(size)
7540         pic16_emitcode("setb","c");
7541       while(sizer--){
7542         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7543         pic16_emitcode("anl","a,%s",
7544                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7545         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7546         offset++;
7547       }
7548       if(size){
7549         CLRC;
7550         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7551         pic16_outBitC(result);
7552       } else if(ifx)
7553         jmpTrueOrFalse(ifx, tlbl);
7554     } else {
7555       for(;(size--);offset++) {
7556         // normal case
7557         // result = left & right
7558         if(AOP_TYPE(right) == AOP_LIT){
7559           int t = (lit >> (offset*8)) & 0x0FFL;
7560           switch(t) { 
7561           case 0x00:
7562             pic16_emitcode("clrf","%s",
7563                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7564             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7565             break;
7566           case 0xff:
7567             pic16_emitcode("movf","%s,w",
7568                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7569             pic16_emitcode("movwf","%s",
7570                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7571             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7572             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7573             break;
7574           default:
7575             pic16_emitcode("movlw","0x%x",t);
7576             pic16_emitcode("andwf","%s,w",
7577                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7578             pic16_emitcode("movwf","%s",
7579                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7580               
7581             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7582             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7583             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7584           }
7585           continue;
7586         }
7587
7588         if (AOP_TYPE(left) == AOP_ACC) {
7589           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7590           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7591         } else {
7592           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7593           pic16_emitcode("andwf","%s,w",
7594                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7595           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7596           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7597         }
7598         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7599         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7600       }
7601     }
7602   }
7603
7604   release :
7605     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7606   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7607   pic16_freeAsmop(result,NULL,ic,TRUE);     
7608 }
7609
7610 /*-----------------------------------------------------------------*/
7611 /* genOr  - code for or                                            */
7612 /*-----------------------------------------------------------------*/
7613 static void genOr (iCode *ic, iCode *ifx)
7614 {
7615     operand *left, *right, *result;
7616     int size, offset=0;
7617     unsigned long lit = 0L;
7618
7619     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7620
7621     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7622     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7623     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7624
7625     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7626
7627     /* if left is a literal & right is not then exchange them */
7628     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7629         AOP_NEEDSACC(left)) {
7630         operand *tmp = right ;
7631         right = left;
7632         left = tmp;
7633     }
7634
7635     /* if result = right then exchange them */
7636     if(pic16_sameRegs(AOP(result),AOP(right))){
7637         operand *tmp = right ;
7638         right = left;
7639         left = tmp;
7640     }
7641
7642     /* if right is bit then exchange them */
7643     if (AOP_TYPE(right) == AOP_CRY &&
7644         AOP_TYPE(left) != AOP_CRY){
7645         operand *tmp = right ;
7646         right = left;
7647         left = tmp;
7648     }
7649
7650     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7651
7652     if(AOP_TYPE(right) == AOP_LIT)
7653         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7654
7655     size = AOP_SIZE(result);
7656
7657     // if(bit | yy)
7658     // xx = bit | yy;
7659     if (AOP_TYPE(left) == AOP_CRY){
7660         if(AOP_TYPE(right) == AOP_LIT){
7661             // c = bit & literal;
7662             if(lit){
7663                 // lit != 0 => result = 1
7664                 if(AOP_TYPE(result) == AOP_CRY){
7665                   if(size)
7666                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7667                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7668                   //     AOP(result)->aopu.aop_dir,
7669                   //     AOP(result)->aopu.aop_dir);
7670                     else if(ifx)
7671                         continueIfTrue(ifx);
7672                     goto release;
7673                 }
7674             } else {
7675                 // lit == 0 => result = left
7676                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7677                     goto release;
7678                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7679             }
7680         } else {
7681             if (AOP_TYPE(right) == AOP_CRY){
7682               if(pic16_sameRegs(AOP(result),AOP(left))){
7683                 // c = bit | bit;
7684                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7685                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7686                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7687
7688                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7689                          AOP(result)->aopu.aop_dir,
7690                          AOP(result)->aopu.aop_dir);
7691                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7692                          AOP(right)->aopu.aop_dir,
7693                          AOP(right)->aopu.aop_dir);
7694                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7695                          AOP(result)->aopu.aop_dir,
7696                          AOP(result)->aopu.aop_dir);
7697               } else {
7698                 if( AOP_TYPE(result) == AOP_ACC) {
7699                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7700                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7701                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7702                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7703
7704                 } else {
7705
7706                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7707                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7708                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7709                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7710
7711                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7712                                  AOP(result)->aopu.aop_dir,
7713                                  AOP(result)->aopu.aop_dir);
7714                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7715                                  AOP(right)->aopu.aop_dir,
7716                                  AOP(right)->aopu.aop_dir);
7717                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7718                                  AOP(left)->aopu.aop_dir,
7719                                  AOP(left)->aopu.aop_dir);
7720                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7721                                  AOP(result)->aopu.aop_dir,
7722                                  AOP(result)->aopu.aop_dir);
7723                 }
7724               }
7725             } else {
7726                 // c = bit | val;
7727                 symbol *tlbl = newiTempLabel(NULL);
7728                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7729
7730
7731                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7732                 if( AOP_TYPE(right) == AOP_ACC) {
7733                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7734                   emitSKPNZ;
7735                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7736                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7737                 }
7738
7739
7740
7741                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7742                     pic16_emitcode(";XXX setb","c");
7743                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7744                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7745                 pic16_toBoolean(right);
7746                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7747                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7748                     jmpTrueOrFalse(ifx, tlbl);
7749                     goto release;
7750                 } else {
7751                     CLRC;
7752                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7753                 }
7754             }
7755         }
7756         // bit = c
7757         // val = c
7758         if(size)
7759             pic16_outBitC(result);
7760         // if(bit | ...)
7761         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7762             genIfxJump(ifx, "c");           
7763         goto release ;
7764     }
7765
7766     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7767     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7768     if((AOP_TYPE(right) == AOP_LIT) &&
7769        (AOP_TYPE(result) == AOP_CRY) &&
7770        (AOP_TYPE(left) != AOP_CRY)){
7771         if(lit){
7772           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7773             // result = 1
7774             if(size)
7775                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7776             else 
7777                 continueIfTrue(ifx);
7778             goto release;
7779         } else {
7780           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7781             // lit = 0, result = boolean(left)
7782             if(size)
7783                 pic16_emitcode(";XXX setb","c");
7784             pic16_toBoolean(right);
7785             if(size){
7786                 symbol *tlbl = newiTempLabel(NULL);
7787                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7788                 CLRC;
7789                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7790             } else {
7791                 genIfxJump (ifx,"a");
7792                 goto release;
7793             }
7794         }
7795         pic16_outBitC(result);
7796         goto release ;
7797     }
7798
7799     /* if left is same as result */
7800     if(pic16_sameRegs(AOP(result),AOP(left))){
7801       int know_W = -1;
7802       for(;size--; offset++,lit>>=8) {
7803         if(AOP_TYPE(right) == AOP_LIT){
7804           if((lit & 0xff) == 0)
7805             /*  or'ing with 0 has no effect */
7806             continue;
7807           else {
7808             int p = pic16_my_powof2(lit & 0xff);
7809             if(p>=0) {
7810               /* only one bit is set in the literal, so use a bsf instruction */
7811               pic16_emitpcode(POC_BSF,
7812                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7813             } else {
7814               if(know_W != (lit & 0xff))
7815                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7816               know_W = lit & 0xff;
7817               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7818             }
7819                     
7820           }
7821         } else {
7822           if (AOP_TYPE(left) == AOP_ACC) {
7823             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7824             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7825           } else {                  
7826             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7827             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7828
7829             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7830             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7831
7832           }
7833         }
7834       }
7835     } else {
7836         // left & result in different registers
7837         if(AOP_TYPE(result) == AOP_CRY){
7838             // result = bit
7839             // if(size), result in bit
7840             // if(!size && ifx), conditional oper: if(left | right)
7841             symbol *tlbl = newiTempLabel(NULL);
7842             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7843             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7844
7845
7846             if(size)
7847                 pic16_emitcode(";XXX setb","c");
7848             while(sizer--){
7849                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7850                 pic16_emitcode(";XXX orl","a,%s",
7851                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7852                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7853                 offset++;
7854             }
7855             if(size){
7856                 CLRC;
7857                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7858                 pic16_outBitC(result);
7859             } else if(ifx)
7860                 jmpTrueOrFalse(ifx, tlbl);
7861         } else for(;(size--);offset++){
7862           // normal case
7863           // result = left & right
7864           if(AOP_TYPE(right) == AOP_LIT){
7865             int t = (lit >> (offset*8)) & 0x0FFL;
7866             switch(t) { 
7867             case 0x00:
7868               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7869               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7870
7871               pic16_emitcode("movf","%s,w",
7872                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7873               pic16_emitcode("movwf","%s",
7874                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7875               break;
7876             default:
7877               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7878               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7879               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7880
7881               pic16_emitcode("movlw","0x%x",t);
7882               pic16_emitcode("iorwf","%s,w",
7883                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7884               pic16_emitcode("movwf","%s",
7885                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7886               
7887             }
7888             continue;
7889           }
7890
7891           // faster than result <- left, anl result,right
7892           // and better if result is SFR
7893           if (AOP_TYPE(left) == AOP_ACC) {
7894             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7895             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7896           } else {
7897             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7898             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7899
7900             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7901             pic16_emitcode("iorwf","%s,w",
7902                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7903           }
7904           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7905           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7906         }
7907     }
7908
7909 release :
7910     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7911     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7912     pic16_freeAsmop(result,NULL,ic,TRUE);     
7913 }
7914
7915 /*-----------------------------------------------------------------*/
7916 /* genXor - code for xclusive or                                   */
7917 /*-----------------------------------------------------------------*/
7918 static void genXor (iCode *ic, iCode *ifx)
7919 {
7920   operand *left, *right, *result;
7921   int size, offset=0;
7922   unsigned long lit = 0L;
7923
7924   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7925
7926   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7927   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7928   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7929
7930   /* if left is a literal & right is not ||
7931      if left needs acc & right does not */
7932   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7933       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7934     operand *tmp = right ;
7935     right = left;
7936     left = tmp;
7937   }
7938
7939   /* if result = right then exchange them */
7940   if(pic16_sameRegs(AOP(result),AOP(right))){
7941     operand *tmp = right ;
7942     right = left;
7943     left = tmp;
7944   }
7945
7946   /* if right is bit then exchange them */
7947   if (AOP_TYPE(right) == AOP_CRY &&
7948       AOP_TYPE(left) != AOP_CRY){
7949     operand *tmp = right ;
7950     right = left;
7951     left = tmp;
7952   }
7953   if(AOP_TYPE(right) == AOP_LIT)
7954     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7955
7956   size = AOP_SIZE(result);
7957
7958   // if(bit ^ yy)
7959   // xx = bit ^ yy;
7960   if (AOP_TYPE(left) == AOP_CRY){
7961     if(AOP_TYPE(right) == AOP_LIT){
7962       // c = bit & literal;
7963       if(lit>>1){
7964         // lit>>1  != 0 => result = 1
7965         if(AOP_TYPE(result) == AOP_CRY){
7966           if(size)
7967             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7968             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7969           else if(ifx)
7970             continueIfTrue(ifx);
7971           goto release;
7972         }
7973         pic16_emitcode("setb","c");
7974       } else{
7975         // lit == (0 or 1)
7976         if(lit == 0){
7977           // lit == 0, result = left
7978           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7979             goto release;
7980           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7981         } else{
7982           // lit == 1, result = not(left)
7983           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7984             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7985             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7986             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7987             goto release;
7988           } else {
7989             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7990             pic16_emitcode("cpl","c");
7991           }
7992         }
7993       }
7994
7995     } else {
7996       // right != literal
7997       symbol *tlbl = newiTempLabel(NULL);
7998       if (AOP_TYPE(right) == AOP_CRY){
7999         // c = bit ^ bit;
8000         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8001       }
8002       else{
8003         int sizer = AOP_SIZE(right);
8004         // c = bit ^ val
8005         // if val>>1 != 0, result = 1
8006         pic16_emitcode("setb","c");
8007         while(sizer){
8008           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8009           if(sizer == 1)
8010             // test the msb of the lsb
8011             pic16_emitcode("anl","a,#0xfe");
8012           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8013           sizer--;
8014         }
8015         // val = (0,1)
8016         pic16_emitcode("rrc","a");
8017       }
8018       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8019       pic16_emitcode("cpl","c");
8020       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8021     }
8022     // bit = c
8023     // val = c
8024     if(size)
8025       pic16_outBitC(result);
8026     // if(bit | ...)
8027     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8028       genIfxJump(ifx, "c");           
8029     goto release ;
8030   }
8031
8032   if(pic16_sameRegs(AOP(result),AOP(left))){
8033     /* if left is same as result */
8034     for(;size--; offset++) {
8035       if(AOP_TYPE(right) == AOP_LIT){
8036         int t  = (lit >> (offset*8)) & 0x0FFL;
8037         if(t == 0x00L)
8038           continue;
8039         else
8040           if (IS_AOP_PREG(left)) {
8041             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8042             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8043             pic16_aopPut(AOP(result),"a",offset);
8044           } else {
8045             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8046             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8047             pic16_emitcode("xrl","%s,%s",
8048                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8049                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8050           }
8051       } else {
8052         if (AOP_TYPE(left) == AOP_ACC)
8053           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8054         else {
8055           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8056           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8057 /*
8058           if (IS_AOP_PREG(left)) {
8059             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8060             pic16_aopPut(AOP(result),"a",offset);
8061           } else
8062             pic16_emitcode("xrl","%s,a",
8063                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8064 */
8065         }
8066       }
8067     }
8068   } else {
8069     // left & result in different registers
8070     if(AOP_TYPE(result) == AOP_CRY){
8071       // result = bit
8072       // if(size), result in bit
8073       // if(!size && ifx), conditional oper: if(left ^ right)
8074       symbol *tlbl = newiTempLabel(NULL);
8075       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8076       if(size)
8077         pic16_emitcode("setb","c");
8078       while(sizer--){
8079         if((AOP_TYPE(right) == AOP_LIT) &&
8080            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8081           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8082         } else {
8083           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8084           pic16_emitcode("xrl","a,%s",
8085                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8086         }
8087         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8088         offset++;
8089       }
8090       if(size){
8091         CLRC;
8092         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8093         pic16_outBitC(result);
8094       } else if(ifx)
8095         jmpTrueOrFalse(ifx, tlbl);
8096     } else for(;(size--);offset++){
8097       // normal case
8098       // result = left & right
8099       if(AOP_TYPE(right) == AOP_LIT){
8100         int t = (lit >> (offset*8)) & 0x0FFL;
8101         switch(t) { 
8102         case 0x00:
8103           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8104           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8105           pic16_emitcode("movf","%s,w",
8106                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8107           pic16_emitcode("movwf","%s",
8108                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8109           break;
8110         case 0xff:
8111           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8112           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8113           pic16_emitcode("comf","%s,w",
8114                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8115           pic16_emitcode("movwf","%s",
8116                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8117           break;
8118         default:
8119           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8120           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8121           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8122           pic16_emitcode("movlw","0x%x",t);
8123           pic16_emitcode("xorwf","%s,w",
8124                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8125           pic16_emitcode("movwf","%s",
8126                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8127
8128         }
8129         continue;
8130       }
8131
8132       // faster than result <- left, anl result,right
8133       // and better if result is SFR
8134       if (AOP_TYPE(left) == AOP_ACC) {
8135         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8136         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8137       } else {
8138         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8139         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8140         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8141         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8142       }
8143       if ( AOP_TYPE(result) != AOP_ACC){
8144         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8145         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8146       }
8147     }
8148   }
8149
8150   release :
8151     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8152   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8153   pic16_freeAsmop(result,NULL,ic,TRUE);     
8154 }
8155
8156 /*-----------------------------------------------------------------*/
8157 /* genInline - write the inline code out                           */
8158 /*-----------------------------------------------------------------*/
8159 static void genInline (iCode *ic)
8160 {
8161   char *buffer, *bp, *bp1;
8162     
8163         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8164
8165         _G.inLine += (!options.asmpeep);
8166
8167         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8168         strcpy(buffer,IC_INLINE(ic));
8169         
8170         while((bp1=strstr(bp, "\\n"))) {
8171           *bp1++ = '\n';
8172           *bp1++ = ' ';
8173           bp = bp1;
8174         }
8175         bp = bp1 = buffer;
8176
8177 #if 0
8178   /* This is an experimental code for #pragma inline
8179      and is temporarily disabled for 2.5.0 release */
8180         if(asmInlineMap)
8181         {
8182           symbol *sym;
8183           char *s;
8184           char *cbuf;
8185           int cblen;
8186
8187             cbuf = Safe_strdup(buffer);
8188             cblen = strlen(buffer)+1;
8189             memset(cbuf, 0, cblen);
8190
8191             bp = buffer;
8192             bp1 = cbuf;
8193             while(*bp) {
8194               if(*bp != '%')*bp1++ = *bp++;
8195               else {
8196                 int i;
8197
8198                   bp++;
8199                   i = *bp - '0';
8200                   if(i>elementsInSet(asmInlineMap))break;
8201                   
8202                   bp++;
8203                   s = indexSet(asmInlineMap, i);
8204                   DEBUGpc("searching symbol s = `%s'", s);
8205                   sym = findSym(SymbolTab, NULL, s);
8206
8207                   if(sym->reqv) {
8208                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8209                   } else {
8210                     strcat(bp1, sym->rname);
8211                   }
8212                   
8213                   while(*bp1)bp1++;
8214               }
8215               
8216               if(strlen(bp1) > cblen - 16) {
8217                 int i = strlen(cbuf);
8218                 cblen += 50;
8219                 cbuf = realloc(cbuf, cblen);
8220                 memset(cbuf+i, 0, 50);
8221                 bp1 = cbuf + i;
8222               }
8223             }
8224             
8225             free(buffer);
8226             buffer = Safe_strdup( cbuf );
8227             free(cbuf);
8228             
8229             bp = bp1 = buffer;
8230         }
8231 #endif  /* 0 */
8232
8233         /* emit each line as a code */
8234         while (*bp) {
8235                 if (*bp == '\n') {
8236                         *bp++ = '\0';
8237
8238                         if(*bp1)
8239                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8240                         bp1 = bp;
8241                 } else {
8242                         if (*bp == ':') {
8243                                 bp++;
8244                                 *bp = '\0';
8245                                 bp++;
8246
8247                                 /* print label, use this special format with NULL directive
8248                                  * to denote that the argument should not be indented with tab */
8249                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8250                                 bp1 = bp;
8251                         } if (*bp == ';') {
8252                                 /* advance to end of line (prevent splitting of comments at ':' */
8253                                 while (*bp && *bp != '\n') {
8254                                         bp++;
8255                                 } // while
8256                         } else
8257                                 bp++;
8258                 }
8259         }
8260
8261         if ((bp1 != bp) && *bp1)
8262                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8263
8264
8265     Safe_free(buffer);
8266
8267     _G.inLine -= (!options.asmpeep);
8268 }
8269
8270 /*-----------------------------------------------------------------*/
8271 /* genRRC - rotate right with carry                                */
8272 /*-----------------------------------------------------------------*/
8273 static void genRRC (iCode *ic)
8274 {
8275   operand *left , *result ;
8276   int size, offset = 0, same;
8277
8278   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8279
8280   /* rotate right with carry */
8281   left = IC_LEFT(ic);
8282   result=IC_RESULT(ic);
8283   pic16_aopOp (left,ic,FALSE);
8284   pic16_aopOp (result,ic,TRUE);
8285
8286   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8287
8288   same = pic16_sameRegs(AOP(result),AOP(left));
8289
8290   size = AOP_SIZE(result);    
8291
8292   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8293
8294   /* get the lsb and put it into the carry */
8295   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8296
8297   offset = 0 ;
8298
8299   while(size--) {
8300
8301     if(same) {
8302       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8303     } else {
8304       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8305       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8306     }
8307
8308     offset++;
8309   }
8310
8311   pic16_freeAsmop(left,NULL,ic,TRUE);
8312   pic16_freeAsmop(result,NULL,ic,TRUE);
8313 }
8314
8315 /*-----------------------------------------------------------------*/
8316 /* genRLC - generate code for rotate left with carry               */
8317 /*-----------------------------------------------------------------*/
8318 static void genRLC (iCode *ic)
8319 {    
8320   operand *left , *result ;
8321   int size, offset = 0;
8322   int same;
8323
8324   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8325   /* rotate right with carry */
8326   left = IC_LEFT(ic);
8327   result=IC_RESULT(ic);
8328   pic16_aopOp (left,ic,FALSE);
8329   pic16_aopOp (result,ic,TRUE);
8330
8331   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8332
8333   same = pic16_sameRegs(AOP(result),AOP(left));
8334
8335   /* move it to the result */
8336   size = AOP_SIZE(result);    
8337
8338   /* get the msb and put it into the carry */
8339   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8340
8341   offset = 0 ;
8342
8343   while(size--) {
8344
8345     if(same) {
8346       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8347     } else {
8348       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8349       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8350     }
8351
8352     offset++;
8353   }
8354
8355
8356   pic16_freeAsmop(left,NULL,ic,TRUE);
8357   pic16_freeAsmop(result,NULL,ic,TRUE);
8358 }
8359
8360
8361 /* gpasm can get the highest order bit with HIGH/UPPER
8362  * so the following probably is not needed -- VR */
8363  
8364 /*-----------------------------------------------------------------*/
8365 /* genGetHbit - generates code get highest order bit               */
8366 /*-----------------------------------------------------------------*/
8367 static void genGetHbit (iCode *ic)
8368 {
8369     operand *left, *result;
8370     left = IC_LEFT(ic);
8371     result=IC_RESULT(ic);
8372     pic16_aopOp (left,ic,FALSE);
8373     pic16_aopOp (result,ic,FALSE);
8374
8375     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8376     /* get the highest order byte into a */
8377     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8378     if(AOP_TYPE(result) == AOP_CRY){
8379         pic16_emitcode("rlc","a");
8380         pic16_outBitC(result);
8381     }
8382     else{
8383         pic16_emitcode("rl","a");
8384         pic16_emitcode("anl","a,#0x01");
8385         pic16_outAcc(result);
8386     }
8387
8388
8389     pic16_freeAsmop(left,NULL,ic,TRUE);
8390     pic16_freeAsmop(result,NULL,ic,TRUE);
8391 }
8392
8393 #if 0
8394 /*-----------------------------------------------------------------*/
8395 /* AccRol - rotate left accumulator by known count                 */
8396 /*-----------------------------------------------------------------*/
8397 static void AccRol (int shCount)
8398 {
8399     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8400     shCount &= 0x0007;              // shCount : 0..7
8401     switch(shCount){
8402         case 0 :
8403             break;
8404         case 1 :
8405             pic16_emitcode("rl","a");
8406             break;
8407         case 2 :
8408             pic16_emitcode("rl","a");
8409             pic16_emitcode("rl","a");
8410             break;
8411         case 3 :
8412             pic16_emitcode("swap","a");
8413             pic16_emitcode("rr","a");
8414             break;
8415         case 4 :
8416             pic16_emitcode("swap","a");
8417             break;
8418         case 5 :
8419             pic16_emitcode("swap","a");
8420             pic16_emitcode("rl","a");
8421             break;
8422         case 6 :
8423             pic16_emitcode("rr","a");
8424             pic16_emitcode("rr","a");
8425             break;
8426         case 7 :
8427             pic16_emitcode("rr","a");
8428             break;
8429     }
8430 }
8431 #endif
8432
8433 /*-----------------------------------------------------------------*/
8434 /* AccLsh - left shift accumulator by known count                  */
8435 /*-----------------------------------------------------------------*/
8436 static void AccLsh (int shCount)
8437 {
8438         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8439         switch(shCount){
8440                 case 0 :
8441                         return;
8442                         break;
8443                 case 1 :
8444                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8445                         break;
8446                 case 2 :
8447                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8448                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8449                         break;
8450                 case 3 :
8451                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8452                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8453                         break;
8454                 case 4 :
8455                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8456                         break;
8457                 case 5 :
8458                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8459                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8460                         break;
8461                 case 6 :
8462                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8463                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8464                         break;
8465                 case 7 :
8466                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8467                         break;
8468         }
8469
8470         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8471 }
8472
8473 /*-----------------------------------------------------------------*/
8474 /* AccRsh - right shift accumulator by known count                 */
8475 /*-----------------------------------------------------------------*/
8476 static void AccRsh (int shCount, int andmask)
8477 {
8478         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8479         switch(shCount){
8480                 case 0 :
8481                         return; break;
8482                 case 1 :
8483                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8484                         break;
8485                 case 2 :
8486                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8487                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8488                         break;
8489                 case 3 :
8490                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8491                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8492                         break;
8493                 case 4 :
8494                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8495                         break;
8496                 case 5 :
8497                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8498                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8499                         break;
8500                 case 6 :
8501                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8502                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8503                         break;
8504                 case 7 :
8505                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8506                         break;
8507         }
8508         
8509         if(andmask)
8510                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8511         else
8512                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8513 }
8514
8515 #if 0
8516 /*-----------------------------------------------------------------*/
8517 /* AccSRsh - signed right shift accumulator by known count                 */
8518 /*-----------------------------------------------------------------*/
8519 static void AccSRsh (int shCount)
8520 {
8521     symbol *tlbl ;
8522     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8523     if(shCount != 0){
8524         if(shCount == 1){
8525             pic16_emitcode("mov","c,acc.7");
8526             pic16_emitcode("rrc","a");
8527         } else if(shCount == 2){
8528             pic16_emitcode("mov","c,acc.7");
8529             pic16_emitcode("rrc","a");
8530             pic16_emitcode("mov","c,acc.7");
8531             pic16_emitcode("rrc","a");
8532         } else {
8533             tlbl = newiTempLabel(NULL);
8534             /* rotate right accumulator */
8535             AccRol(8 - shCount);
8536             /* and kill the higher order bits */
8537             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8538             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8539             pic16_emitcode("orl","a,#0x%02x",
8540                      (unsigned char)~SRMask[shCount]);
8541             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8542         }
8543     }
8544 }
8545 #endif
8546
8547 /*-----------------------------------------------------------------*/
8548 /* shiftR1Left2Result - shift right one byte from left to result   */
8549 /*-----------------------------------------------------------------*/
8550 static void shiftR1Left2ResultSigned (operand *left, int offl,
8551                                 operand *result, int offr,
8552                                 int shCount)
8553 {
8554   int same;
8555
8556   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8557
8558   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8559
8560   switch(shCount) {
8561   case 1:
8562     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8563     if(same) 
8564       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8565     else {
8566       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8567       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8568     }
8569
8570     break;
8571   case 2:
8572
8573     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8574     if(same) 
8575       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8576     else {
8577       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8578       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8579     }
8580     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8581     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8582
8583     break;
8584
8585   case 3:
8586     if(same)
8587       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8588     else {
8589       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8590       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8591     }
8592
8593     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8594     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8595     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8596
8597     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8598     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8599
8600     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8601     break;
8602
8603   case 4:
8604     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8605     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8606     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8607     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8608     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8609     break;
8610   case 5:
8611     if(same) {
8612       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8613     } else {
8614       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8615       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8616     }
8617     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8618     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8619     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8620     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8621     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8622     break;
8623
8624   case 6:
8625     if(same) {
8626       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8627       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8628       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8629       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8630       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8631       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8632     } else {
8633       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8634       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8635       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8636       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8637       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8638     }
8639     break;
8640
8641   case 7:
8642     if(same) {
8643       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8644       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8645       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8646       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8647     } else {
8648       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8649       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8650       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8651     }
8652
8653   default:
8654     break;
8655   }
8656 }
8657
8658 /*-----------------------------------------------------------------*/
8659 /* shiftR1Left2Result - shift right one byte from left to result   */
8660 /*-----------------------------------------------------------------*/
8661 static void shiftR1Left2Result (operand *left, int offl,
8662                                 operand *result, int offr,
8663                                 int shCount, int sign)
8664 {
8665   int same;
8666
8667   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8668
8669   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8670
8671   /* Copy the msb into the carry if signed. */
8672   if(sign) {
8673     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8674     return;
8675   }
8676
8677
8678
8679   switch(shCount) {
8680   case 1:
8681     emitCLRC;
8682     if(same) 
8683       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8684     else {
8685       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8686       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8687     }
8688     break;
8689   case 2:
8690     emitCLRC;
8691     if(same) {
8692       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8693     } else {
8694       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8695       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8696     }
8697     emitCLRC;
8698     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8699
8700     break;
8701   case 3:
8702     if(same)
8703       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8704     else {
8705       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8706       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8707     }
8708
8709     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8710     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8711     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8712     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8713     break;
8714       
8715   case 4:
8716     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8717     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8718     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8719     break;
8720
8721   case 5:
8722     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8723     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8724     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8725     //emitCLRC;
8726     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8727
8728     break;
8729   case 6:
8730
8731     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8732     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8733     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8734     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8735     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8736     break;
8737
8738   case 7:
8739
8740     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8741     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8742     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8743
8744     break;
8745
8746   default:
8747     break;
8748   }
8749 }
8750
8751 /*-----------------------------------------------------------------*/
8752 /* shiftL1Left2Result - shift left one byte from left to result    */
8753 /*-----------------------------------------------------------------*/
8754 static void shiftL1Left2Result (operand *left, int offl,
8755                                 operand *result, int offr, int shCount)
8756 {
8757   int same;
8758
8759   //    char *l;
8760   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8761
8762   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8763   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8764     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8765     //    MOVA(l);
8766     /* shift left accumulator */
8767     //AccLsh(shCount); // don't comment out just yet...
8768   //    pic16_aopPut(AOP(result),"a",offr);
8769
8770   switch(shCount) {
8771   case 1:
8772     /* Shift left 1 bit position */
8773     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8774     if(same) {
8775       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8776     } else {
8777       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8778       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8779     }
8780     break;
8781   case 2:
8782     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8783     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8784     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8785     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8786     break;
8787   case 3:
8788     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8789     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8790     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8791     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8792     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8793     break;
8794   case 4:
8795     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8796     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8797     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8798     break;
8799   case 5:
8800     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8801     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8802     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8803     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8804     break;
8805   case 6:
8806     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8807     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8808     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8809     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8810     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8811     break;
8812   case 7:
8813     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8814     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8815     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8816     break;
8817
8818   default:
8819     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8820   }
8821
8822 }
8823
8824 /*-----------------------------------------------------------------*/
8825 /* movLeft2Result - move byte from left to result                  */
8826 /*-----------------------------------------------------------------*/
8827 static void movLeft2Result (operand *left, int offl,
8828                             operand *result, int offr)
8829 {
8830   char *l;
8831   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8832   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8833     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8834
8835     if (*l == '@' && (IS_AOP_PREG(result))) {
8836       pic16_emitcode("mov","a,%s",l);
8837       pic16_aopPut(AOP(result),"a",offr);
8838     } else {
8839       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8840       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8841     }
8842   }
8843 }
8844
8845 /*-----------------------------------------------------------------*/
8846 /* shiftL2Left2Result - shift left two bytes from left to result   */
8847 /*-----------------------------------------------------------------*/
8848 static void shiftL2Left2Result (operand *left, int offl,
8849                                 operand *result, int offr, int shCount)
8850 {
8851   int same = pic16_sameRegs(AOP(result), AOP(left));
8852   int i;
8853
8854   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8855
8856   if (same && (offl != offr)) { // shift bytes
8857     if (offr > offl) {
8858        for(i=1;i>-1;i--) {
8859          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8860          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8861        }
8862     } else { // just treat as different later on
8863                 same = 0;
8864     }
8865   }
8866
8867   if(same) {
8868     switch(shCount) {
8869     case 0:
8870       break;
8871     case 1:
8872     case 2:
8873     case 3:
8874
8875       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8876       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8877       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8878
8879       while(--shCount) {
8880                 emitCLRC;
8881                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8882                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8883       }
8884
8885       break;
8886     case 4:
8887     case 5:
8888       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8889       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8890       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8891       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8892       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8893       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8894       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8895       if(shCount >=5) {
8896                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8897                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8898       }
8899       break;
8900     case 6:
8901       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8902       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8903       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8904       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8905       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8906       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8907       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8908       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8909       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8910       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8911       break;
8912     case 7:
8913       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8914       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8915       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8916       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8917       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8918     }
8919
8920   } else {
8921     switch(shCount) {
8922     case 0:
8923       break;
8924     case 1:
8925     case 2:
8926     case 3:
8927       /* note, use a mov/add for the shift since the mov has a
8928          chance of getting optimized out */
8929       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8930       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8931       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8932       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8933       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8934
8935       while(--shCount) {
8936                 emitCLRC;
8937                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8938                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8939       }
8940       break;
8941
8942     case 4:
8943     case 5:
8944       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8945       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8946       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8947       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8948       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8949       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8950       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8951       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8952
8953
8954       if(shCount == 5) {
8955                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8956                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8957       }
8958       break;
8959     case 6:
8960       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8961       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8962       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8963       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8964
8965       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8966       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8967       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8968       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8969       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8971       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8973       break;
8974     case 7:
8975       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8976       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8977       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8978       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8979       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8980     }
8981   }
8982
8983 }
8984 /*-----------------------------------------------------------------*/
8985 /* shiftR2Left2Result - shift right two bytes from left to result  */
8986 /*-----------------------------------------------------------------*/
8987 static void shiftR2Left2Result (operand *left, int offl,
8988                                 operand *result, int offr,
8989                                 int shCount, int sign)
8990 {
8991   int same = pic16_sameRegs(AOP(result), AOP(left));
8992   int i;
8993   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8994
8995   if (same && (offl != offr)) { // shift right bytes
8996     if (offr < offl) {
8997        for(i=0;i<2;i++) {
8998          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8999          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9000        }
9001     } else { // just treat as different later on
9002                 same = 0;
9003     }
9004   }
9005
9006   switch(shCount) {
9007   case 0:
9008     break;
9009   case 1:
9010   case 2:
9011   case 3:
9012     if(sign)
9013       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9014     else
9015       emitCLRC;
9016
9017     if(same) {
9018       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9019       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9020     } else {
9021       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9022       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9023       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9024       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9025     }
9026
9027     while(--shCount) {
9028       if(sign)
9029                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9030       else
9031                 emitCLRC;
9032       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9033       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9034     }
9035     break;
9036   case 4:
9037   case 5:
9038     if(same) {
9039
9040       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9041       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9042       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9043
9044       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9045       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9046       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9047       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9048     } else {
9049       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9050       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9051       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9052
9053       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9054       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9055       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9056       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9057       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9058     }
9059
9060     if(shCount >=5) {
9061       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9062       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9063     }
9064
9065     if(sign) {
9066       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9067       pic16_emitpcode(POC_BTFSC, 
9068                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9069       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9070     }
9071
9072     break;
9073
9074   case 6:
9075     if(same) {
9076
9077       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9078       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9079
9080       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9081       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9082       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9083       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9084       if(sign) {
9085         pic16_emitpcode(POC_BTFSC, 
9086                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9087         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9088       }
9089       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9090       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9091       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9092       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9093     } else {
9094       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9095       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9096       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9097       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9098       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9099       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9100       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9101       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9102       if(sign) {
9103         pic16_emitpcode(POC_BTFSC, 
9104                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9105         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9106       }
9107       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9108       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9109
9110         
9111     }
9112
9113     break;
9114   case 7:
9115     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9116     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9117     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9118     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9119     if(sign) {
9120       emitSKPNC;
9121       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9122     } else 
9123       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9124   }
9125 }
9126
9127
9128 /*-----------------------------------------------------------------*/
9129 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9130 /*-----------------------------------------------------------------*/
9131 static void shiftLLeftOrResult (operand *left, int offl,
9132                                 operand *result, int offr, int shCount)
9133 {
9134     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9135
9136     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9137     /* shift left accumulator */
9138     AccLsh(shCount);
9139     /* or with result */
9140     /* back to result */
9141     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9142 }
9143
9144 /*-----------------------------------------------------------------*/
9145 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9146 /*-----------------------------------------------------------------*/
9147 static void shiftRLeftOrResult (operand *left, int offl,
9148                                 operand *result, int offr, int shCount)
9149 {
9150     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9151     
9152     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9153     /* shift right accumulator */
9154     AccRsh(shCount, 1);
9155     /* or with result */
9156     /* back to result */
9157     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9158 }
9159
9160 /*-----------------------------------------------------------------*/
9161 /* genlshOne - left shift a one byte quantity by known count       */
9162 /*-----------------------------------------------------------------*/
9163 static void genlshOne (operand *result, operand *left, int shCount)
9164 {       
9165     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9166     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9167 }
9168
9169 /*-----------------------------------------------------------------*/
9170 /* genlshTwo - left shift two bytes by known amount != 0           */
9171 /*-----------------------------------------------------------------*/
9172 static void genlshTwo (operand *result,operand *left, int shCount)
9173 {
9174     int size;
9175     
9176     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9177     size = pic16_getDataSize(result);
9178
9179     /* if shCount >= 8 */
9180     if (shCount >= 8) {
9181         shCount -= 8 ;
9182
9183         if (size > 1){
9184             if (shCount)
9185                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9186             else 
9187                 movLeft2Result(left, LSB, result, MSB16);
9188         }
9189         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9190     }
9191
9192     /*  1 <= shCount <= 7 */
9193     else {  
9194         if(size == 1)
9195             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9196         else 
9197             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9198     }
9199 }
9200
9201 /*-----------------------------------------------------------------*/
9202 /* shiftLLong - shift left one long from left to result            */
9203 /* offr = LSB or MSB16                                             */
9204 /*-----------------------------------------------------------------*/
9205 static void shiftLLong (operand *left, operand *result, int offr )
9206 {
9207     int size = AOP_SIZE(result);
9208     int same = pic16_sameRegs(AOP(left),AOP(result));
9209         int i;
9210
9211     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9212
9213         if (same && (offr == MSB16)) { //shift one byte
9214                 for(i=size-1;i>=MSB16;i--) {
9215                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9216                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9217                 }
9218         } else {
9219                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9220         }
9221         
9222     if (size > LSB+offr ){
9223                 if (same) {
9224                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9225                 } else {
9226                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9227                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9228                 }
9229          }
9230
9231     if(size > MSB16+offr){
9232                 if (same) {
9233                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9234                 } else {
9235                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9236                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9237                 }
9238     }
9239
9240     if(size > MSB24+offr){
9241                 if (same) {
9242                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9243                 } else {
9244                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9245                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9246                 }
9247     }
9248
9249     if(size > MSB32+offr){
9250                 if (same) {
9251                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9252                 } else {
9253                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9254                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9255                 }
9256     }
9257     if(offr != LSB)
9258                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9259
9260 }
9261
9262 /*-----------------------------------------------------------------*/
9263 /* genlshFour - shift four byte by a known amount != 0             */
9264 /*-----------------------------------------------------------------*/
9265 static void genlshFour (operand *result, operand *left, int shCount)
9266 {
9267     int size;
9268
9269     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9270     size = AOP_SIZE(result);
9271
9272     /* if shifting more that 3 bytes */
9273     if (shCount >= 24 ) {
9274         shCount -= 24;
9275         if (shCount)
9276             /* lowest order of left goes to the highest
9277             order of the destination */
9278             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9279         else
9280             movLeft2Result(left, LSB, result, MSB32);
9281
9282                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9283                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9284                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9285
9286         return;
9287     }
9288
9289     /* more than two bytes */
9290     else if ( shCount >= 16 ) {
9291         /* lower order two bytes goes to higher order two bytes */
9292         shCount -= 16;
9293         /* if some more remaining */
9294         if (shCount)
9295             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9296         else {
9297             movLeft2Result(left, MSB16, result, MSB32);
9298             movLeft2Result(left, LSB, result, MSB24);
9299         }
9300                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9301                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9302         return;
9303     }    
9304
9305     /* if more than 1 byte */
9306     else if ( shCount >= 8 ) {
9307         /* lower order three bytes goes to higher order  three bytes */
9308         shCount -= 8;
9309         if(size == 2){
9310             if(shCount)
9311                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9312             else
9313                 movLeft2Result(left, LSB, result, MSB16);
9314         }
9315         else{   /* size = 4 */
9316             if(shCount == 0){
9317                 movLeft2Result(left, MSB24, result, MSB32);
9318                 movLeft2Result(left, MSB16, result, MSB24);
9319                 movLeft2Result(left, LSB, result, MSB16);
9320                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9321             }
9322             else if(shCount == 1)
9323                 shiftLLong(left, result, MSB16);
9324             else{
9325                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9326                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9327                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9328                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9329             }
9330         }
9331     }
9332
9333     /* 1 <= shCount <= 7 */
9334     else if(shCount <= 3)
9335     { 
9336         shiftLLong(left, result, LSB);
9337         while(--shCount >= 1)
9338             shiftLLong(result, result, LSB);
9339     }
9340     /* 3 <= shCount <= 7, optimize */
9341     else{
9342         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9343         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9344         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9345     }
9346 }
9347
9348 /*-----------------------------------------------------------------*/
9349 /* genLeftShiftLiteral - left shifting by known count              */
9350 /*-----------------------------------------------------------------*/
9351 void pic16_genLeftShiftLiteral (operand *left,
9352                                  operand *right,
9353                                  operand *result,
9354                                  iCode *ic)
9355 {    
9356     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9357     int size;
9358
9359     FENTRY;
9360     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9361     pic16_freeAsmop(right,NULL,ic,TRUE);
9362
9363     pic16_aopOp(left,ic,FALSE);
9364     pic16_aopOp(result,ic,TRUE);
9365
9366     size = getSize(operandType(result));
9367
9368 #if VIEW_SIZE
9369     pic16_emitcode("; shift left ","result %d, left %d",size,
9370              AOP_SIZE(left));
9371 #endif
9372
9373     /* I suppose that the left size >= result size */
9374     if(shCount == 0){
9375         while(size--){
9376             movLeft2Result(left, size, result, size);
9377         }
9378     }
9379
9380     else if(shCount >= (size * 8))
9381         while(size--)
9382             pic16_aopPut(AOP(result),zero,size);
9383     else{
9384         switch (size) {
9385             case 1:
9386                 genlshOne (result,left,shCount);
9387                 break;
9388
9389             case 2:
9390             case 3:
9391                 genlshTwo (result,left,shCount);
9392                 break;
9393
9394             case 4:
9395                 genlshFour (result,left,shCount);
9396                 break;
9397         }
9398     }
9399     pic16_freeAsmop(left,NULL,ic,TRUE);
9400     pic16_freeAsmop(result,NULL,ic,TRUE);
9401 }
9402
9403 /*-----------------------------------------------------------------*
9404  * genMultiAsm - repeat assembly instruction for size of register.
9405  * if endian == 1, then the high byte (i.e base address + size of 
9406  * register) is used first else the low byte is used first;
9407  *-----------------------------------------------------------------*/
9408 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9409 {
9410
9411   int offset = 0;
9412
9413   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9414
9415   if(!reg)
9416     return;
9417
9418   if(!endian) {
9419     endian = 1;
9420   } else {
9421     endian = -1;
9422     offset = size-1;
9423   }
9424
9425   while(size--) {
9426     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9427     offset += endian;
9428   }
9429
9430 }
9431
9432 #if !(USE_GENERIC_SIGNED_SHIFT)
9433 /*-----------------------------------------------------------------*/
9434 /* genLeftShift - generates code for left shifting                 */
9435 /*-----------------------------------------------------------------*/
9436 static void genLeftShift (iCode *ic)
9437 {
9438   operand *left,*right, *result;
9439   int size, offset;
9440 //  char *l;
9441   symbol *tlbl , *tlbl1;
9442   pCodeOp *pctemp;
9443
9444   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9445
9446   right = IC_RIGHT(ic);
9447   left  = IC_LEFT(ic);
9448   result = IC_RESULT(ic);
9449
9450   pic16_aopOp(right,ic,FALSE);
9451
9452   /* if the shift count is known then do it 
9453      as efficiently as possible */
9454   if (AOP_TYPE(right) == AOP_LIT) {
9455     pic16_genLeftShiftLiteral (left,right,result,ic);
9456     return ;
9457   }
9458
9459   /* shift count is unknown then we have to form
9460    * a loop. Get the loop count in WREG : Note: we take
9461    * only the lower order byte since shifting
9462    * more than 32 bits make no sense anyway, ( the
9463    * largest size of an object can be only 32 bits ) */
9464   
9465   pic16_aopOp(left,ic,FALSE);
9466   pic16_aopOp(result,ic,FALSE);
9467
9468   /* now move the left to the result if they are not the
9469    * same, and if size > 1,
9470    * and if right is not same to result (!!!) -- VR */
9471   if (!pic16_sameRegs(AOP(left),AOP(result))
9472       && (AOP_SIZE(result) > 1)) {
9473
9474     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9475
9476     size = AOP_SIZE(result);
9477     offset=0;
9478     while (size--) {
9479
9480 #if 0
9481       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9482       if (*l == '@' && (IS_AOP_PREG(result))) {
9483
9484           pic16_emitcode("mov","a,%s",l);
9485           pic16_aopPut(AOP(result),"a",offset);
9486       } else
9487 #endif
9488       {
9489         /* we don't know if left is a literal or a register, take care -- VR */
9490         pic16_mov2f(AOP(result), AOP(left), offset);
9491       }
9492       offset++;
9493     }
9494   }
9495
9496   size = AOP_SIZE(result);
9497
9498   /* if it is only one byte then */
9499   if (size == 1) {
9500     if(optimized_for_speed) {
9501       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9502       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9503       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9504       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9505       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9506       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9507       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9508       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9509       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9510       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9511       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9512       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9513     } else {
9514
9515       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9516
9517       tlbl = newiTempLabel(NULL);
9518
9519 #if 1
9520       /* this is already done, why change it? */
9521       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9522                 pic16_mov2f(AOP(result), AOP(left), 0);
9523       }
9524 #endif
9525
9526       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9527       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9528       pic16_emitpLabel(tlbl->key);
9529       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9530       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9531       emitSKPC;
9532       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9533     }
9534     goto release ;
9535   }
9536     
9537   if (pic16_sameRegs(AOP(left),AOP(result))) {
9538
9539     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9540     
9541     tlbl = newiTempLabel(NULL);
9542     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9543     genMultiAsm(POC_RRCF, result, size,1);
9544     pic16_emitpLabel(tlbl->key);
9545     genMultiAsm(POC_RLCF, result, size,0);
9546     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9547     emitSKPC;
9548     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9549     goto release;
9550   }
9551
9552   //tlbl = newiTempLabel(NULL);
9553   //offset = 0 ;   
9554   //tlbl1 = newiTempLabel(NULL);
9555
9556   //reAdjustPreg(AOP(result));    
9557     
9558   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9559   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9560   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9561   //MOVA(l);
9562   //pic16_emitcode("add","a,acc");         
9563   //pic16_aopPut(AOP(result),"a",offset++);
9564   //while (--size) {
9565   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9566   //  MOVA(l);
9567   //  pic16_emitcode("rlc","a");         
9568   //  pic16_aopPut(AOP(result),"a",offset++);
9569   //}
9570   //reAdjustPreg(AOP(result));
9571
9572   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9573   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9574
9575
9576   tlbl = newiTempLabel(NULL);
9577   tlbl1= newiTempLabel(NULL);
9578
9579   size = AOP_SIZE(result);
9580   offset = 1;
9581
9582   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9583
9584   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9585
9586   /* offset should be 0, 1 or 3 */
9587   
9588   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9589   emitSKPNZ;
9590   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9591
9592   pic16_emitpcode(POC_MOVWF, pctemp);
9593
9594
9595   pic16_emitpLabel(tlbl->key);
9596
9597   emitCLRC;
9598   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9599   while(--size)
9600     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9601
9602   pic16_emitpcode(POC_DECFSZ,  pctemp);
9603   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9604   pic16_emitpLabel(tlbl1->key);
9605
9606   pic16_popReleaseTempReg(pctemp,1);
9607
9608
9609  release:
9610   pic16_freeAsmop (right,NULL,ic,TRUE);
9611   pic16_freeAsmop(left,NULL,ic,TRUE);
9612   pic16_freeAsmop(result,NULL,ic,TRUE);
9613 }
9614 #endif
9615
9616
9617 #if 0
9618 #error old code (left here for reference)
9619 /*-----------------------------------------------------------------*/
9620 /* genLeftShift - generates code for left shifting                 */
9621 /*-----------------------------------------------------------------*/
9622 static void genLeftShift (iCode *ic)
9623 {
9624   operand *left,*right, *result;
9625   int size, offset;
9626   char *l;
9627   symbol *tlbl , *tlbl1;
9628   pCodeOp *pctemp;
9629
9630   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9631
9632   right = IC_RIGHT(ic);
9633   left  = IC_LEFT(ic);
9634   result = IC_RESULT(ic);
9635
9636   pic16_aopOp(right,ic,FALSE);
9637
9638   /* if the shift count is known then do it 
9639      as efficiently as possible */
9640   if (AOP_TYPE(right) == AOP_LIT) {
9641     pic16_genLeftShiftLiteral (left,right,result,ic);
9642     return ;
9643   }
9644
9645   /* shift count is unknown then we have to form 
9646      a loop get the loop count in B : Note: we take
9647      only the lower order byte since shifting
9648      more that 32 bits make no sense anyway, ( the
9649      largest size of an object can be only 32 bits ) */  
9650
9651     
9652   pic16_aopOp(left,ic,FALSE);
9653   pic16_aopOp(result,ic,FALSE);
9654
9655   /* now move the left to the result if they are not the
9656      same */
9657   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9658       AOP_SIZE(result) > 1) {
9659
9660     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9661
9662     size = AOP_SIZE(result);
9663     offset=0;
9664     while (size--) {
9665       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9666       if (*l == '@' && (IS_AOP_PREG(result))) {
9667
9668         pic16_emitcode("mov","a,%s",l);
9669         pic16_aopPut(AOP(result),"a",offset);
9670       } else {
9671
9672         /* we don't know if left is a literal or a register, take care -- VR */
9673         pic16_mov2f(AOP(result), AOP(left), offset);
9674       }
9675       offset++;
9676     }
9677   }
9678
9679   size = AOP_SIZE(result);
9680
9681   /* if it is only one byte then */
9682   if (size == 1) {
9683     if(optimized_for_speed) {
9684       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9685       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9686       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9687       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9688       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9689       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9690       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9691       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9692       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9693       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9694       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9695       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9696     } else {
9697
9698       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9699
9700       tlbl = newiTempLabel(NULL);
9701       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9702                 pic16_mov2f(AOP(result), AOP(left), 0);
9703                 
9704 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9705 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9706       }
9707
9708       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9709       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9710       pic16_emitpLabel(tlbl->key);
9711       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9712       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9713       emitSKPC;
9714       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9715     }
9716     goto release ;
9717   }
9718     
9719   if (pic16_sameRegs(AOP(left),AOP(result))) {
9720
9721     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9722     
9723     tlbl = newiTempLabel(NULL);
9724     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9725     genMultiAsm(POC_RRCF, result, size,1);
9726     pic16_emitpLabel(tlbl->key);
9727     genMultiAsm(POC_RLCF, result, size,0);
9728     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9729     emitSKPC;
9730     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9731     goto release;
9732   }
9733
9734   //tlbl = newiTempLabel(NULL);
9735   //offset = 0 ;   
9736   //tlbl1 = newiTempLabel(NULL);
9737
9738   //reAdjustPreg(AOP(result));    
9739     
9740   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9741   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9742   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9743   //MOVA(l);
9744   //pic16_emitcode("add","a,acc");         
9745   //pic16_aopPut(AOP(result),"a",offset++);
9746   //while (--size) {
9747   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9748   //  MOVA(l);
9749   //  pic16_emitcode("rlc","a");         
9750   //  pic16_aopPut(AOP(result),"a",offset++);
9751   //}
9752   //reAdjustPreg(AOP(result));
9753
9754   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9755   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9756
9757
9758   tlbl = newiTempLabel(NULL);
9759   tlbl1= newiTempLabel(NULL);
9760
9761   size = AOP_SIZE(result);
9762   offset = 1;
9763
9764   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9765
9766   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9767
9768   /* offset should be 0, 1 or 3 */
9769   
9770   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9771   emitSKPNZ;
9772   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9773
9774   pic16_emitpcode(POC_MOVWF, pctemp);
9775
9776
9777   pic16_emitpLabel(tlbl->key);
9778
9779   emitCLRC;
9780   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9781   while(--size)
9782     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9783
9784   pic16_emitpcode(POC_DECFSZ,  pctemp);
9785   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9786   pic16_emitpLabel(tlbl1->key);
9787
9788   pic16_popReleaseTempReg(pctemp,1);
9789
9790
9791  release:
9792   pic16_freeAsmop (right,NULL,ic,TRUE);
9793   pic16_freeAsmop(left,NULL,ic,TRUE);
9794   pic16_freeAsmop(result,NULL,ic,TRUE);
9795 }
9796 #endif
9797
9798 /*-----------------------------------------------------------------*/
9799 /* genrshOne - right shift a one byte quantity by known count      */
9800 /*-----------------------------------------------------------------*/
9801 static void genrshOne (operand *result, operand *left,
9802                        int shCount, int sign)
9803 {
9804     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9805     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9806 }
9807
9808 /*-----------------------------------------------------------------*/
9809 /* genrshTwo - right shift two bytes by known amount != 0          */
9810 /*-----------------------------------------------------------------*/
9811 static void genrshTwo (operand *result,operand *left,
9812                        int shCount, int sign)
9813 {
9814   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9815   /* if shCount >= 8 */
9816   if (shCount >= 8) {
9817     shCount -= 8 ;
9818     if (shCount)
9819       shiftR1Left2Result(left, MSB16, result, LSB,
9820                          shCount, sign);
9821     else
9822       movLeft2Result(left, MSB16, result, LSB);
9823
9824     pic16_addSign (result, 1, sign);
9825   }
9826
9827   /*  1 <= shCount <= 7 */
9828   else
9829     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9830 }
9831
9832 /*-----------------------------------------------------------------*/
9833 /* shiftRLong - shift right one long from left to result           */
9834 /* offl = LSB or MSB16                                             */
9835 /*-----------------------------------------------------------------*/
9836 static void shiftRLong (operand *left, int offl,
9837                         operand *result, int sign)
9838 {
9839     int size = AOP_SIZE(result);
9840     int same = pic16_sameRegs(AOP(left),AOP(result));
9841     int i;
9842     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9843
9844         if (same && (offl == MSB16)) { //shift one byte right
9845                 for(i=MSB16;i<size;i++) {
9846                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9847                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9848                 }
9849         }
9850
9851     if(sign)
9852                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9853         else
9854                 emitCLRC;
9855
9856         if (same) {
9857                 if (offl == LSB)
9858                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9859         } else {
9860         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9861         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9862         }
9863
9864     if(offl == MSB16) {
9865         /* add sign of "a" */
9866         pic16_addSign(result, MSB32, sign);
9867         }
9868
9869         if (same) {
9870         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9871         } else {
9872         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9873         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9874         }
9875         
9876         if (same) {
9877         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9878         } else {
9879         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9880         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9881         }
9882
9883         if (same) {
9884         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9885         } else {
9886         if(offl == LSB){
9887                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9888                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9889         }
9890         }
9891 }
9892
9893 /*-----------------------------------------------------------------*/
9894 /* genrshFour - shift four byte by a known amount != 0             */
9895 /*-----------------------------------------------------------------*/
9896 static void genrshFour (operand *result, operand *left,
9897                         int shCount, int sign)
9898 {
9899   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9900   /* if shifting more that 3 bytes */
9901   if(shCount >= 24 ) {
9902     shCount -= 24;
9903     if(shCount)
9904       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9905     else
9906       movLeft2Result(left, MSB32, result, LSB);
9907
9908     pic16_addSign(result, MSB16, sign);
9909   }
9910   else if(shCount >= 16){
9911     shCount -= 16;
9912     if(shCount)
9913       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9914     else{
9915       movLeft2Result(left, MSB24, result, LSB);
9916       movLeft2Result(left, MSB32, result, MSB16);
9917     }
9918     pic16_addSign(result, MSB24, sign);
9919   }
9920   else if(shCount >= 8){
9921     shCount -= 8;
9922     if(shCount == 1)
9923       shiftRLong(left, MSB16, result, sign);
9924     else if(shCount == 0){
9925       movLeft2Result(left, MSB16, result, LSB);
9926       movLeft2Result(left, MSB24, result, MSB16);
9927       movLeft2Result(left, MSB32, result, MSB24);
9928       pic16_addSign(result, MSB32, sign);
9929     }
9930     else{ //shcount >= 2
9931       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9932       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9933       /* the last shift is signed */
9934       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9935       pic16_addSign(result, MSB32, sign);
9936     }
9937   }
9938   else{   /* 1 <= shCount <= 7 */
9939     if(shCount <= 2){
9940       shiftRLong(left, LSB, result, sign);
9941       if(shCount == 2)
9942         shiftRLong(result, LSB, result, sign);
9943     }
9944     else{
9945       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9946       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9947       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9948     }
9949   }
9950 }
9951
9952 /*-----------------------------------------------------------------*/
9953 /* genRightShiftLiteral - right shifting by known count            */
9954 /*-----------------------------------------------------------------*/
9955 static void genRightShiftLiteral (operand *left,
9956                                   operand *right,
9957                                   operand *result,
9958                                   iCode *ic,
9959                                   int sign)
9960 {    
9961   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9962   int lsize,res_size;
9963
9964   pic16_freeAsmop(right,NULL,ic,TRUE);
9965
9966   pic16_aopOp(left,ic,FALSE);
9967   pic16_aopOp(result,ic,TRUE);
9968
9969   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9970
9971 #if VIEW_SIZE
9972   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9973                  AOP_SIZE(left));
9974 #endif
9975
9976   lsize = pic16_getDataSize(left);
9977   res_size = pic16_getDataSize(result);
9978   /* test the LEFT size !!! */
9979
9980   /* I suppose that the left size >= result size */
9981   if(shCount == 0){
9982     assert (res_size <= lsize);
9983     while (res_size--) {
9984       pic16_mov2f (AOP(result), AOP(left), res_size);
9985     } // for
9986   }
9987
9988   else if(shCount >= (lsize * 8)){
9989
9990     if(res_size == 1) {
9991       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9992       if(sign) {
9993         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9994         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9995       }
9996     } else {
9997
9998       if(sign) {
9999         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10000         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10001         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10002         while(res_size--)
10003           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10004
10005       } else {
10006
10007         while(res_size--)
10008           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10009       }
10010     }
10011   } else {
10012
10013     switch (res_size) {
10014     case 1:
10015       genrshOne (result,left,shCount,sign);
10016       break;
10017
10018     case 2:
10019       genrshTwo (result,left,shCount,sign);
10020       break;
10021
10022     case 4:
10023       genrshFour (result,left,shCount,sign);
10024       break;
10025     default :
10026       break;
10027     }
10028
10029   }
10030
10031   pic16_freeAsmop(left,NULL,ic,TRUE);
10032   pic16_freeAsmop(result,NULL,ic,TRUE);
10033 }
10034
10035 #if !(USE_GENERIC_SIGNED_SHIFT)
10036 /*-----------------------------------------------------------------*/
10037 /* genSignedRightShift - right shift of signed number              */
10038 /*-----------------------------------------------------------------*/
10039 static void genSignedRightShift (iCode *ic)
10040 {
10041   operand *right, *left, *result;
10042   int size, offset;
10043   //  char *l;
10044   symbol *tlbl, *tlbl1 ;
10045   pCodeOp *pctemp;
10046
10047   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10048
10049   /* we do it the hard way put the shift count in b
10050      and loop thru preserving the sign */
10051   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10052
10053   right = IC_RIGHT(ic);
10054   left  = IC_LEFT(ic);
10055   result = IC_RESULT(ic);
10056
10057   pic16_aopOp(right,ic,FALSE);  
10058   pic16_aopOp(left,ic,FALSE);
10059   pic16_aopOp(result,ic,FALSE);
10060
10061
10062   if ( AOP_TYPE(right) == AOP_LIT) {
10063     genRightShiftLiteral (left,right,result,ic,1);
10064     return ;
10065   }
10066   /* shift count is unknown then we have to form 
10067      a loop get the loop count in B : Note: we take
10068      only the lower order byte since shifting
10069      more that 32 bits make no sense anyway, ( the
10070      largest size of an object can be only 32 bits ) */  
10071
10072   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10073   //pic16_emitcode("inc","b");
10074   //pic16_freeAsmop (right,NULL,ic,TRUE);
10075   //pic16_aopOp(left,ic,FALSE);
10076   //pic16_aopOp(result,ic,FALSE);
10077
10078   /* now move the left to the result if they are not the
10079      same */
10080   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10081       AOP_SIZE(result) > 1) {
10082
10083     size = AOP_SIZE(result);
10084     offset=0;
10085     while (size--) { 
10086       /*
10087         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10088         if (*l == '@' && IS_AOP_PREG(result)) {
10089
10090         pic16_emitcode("mov","a,%s",l);
10091         pic16_aopPut(AOP(result),"a",offset);
10092         } else
10093         pic16_aopPut(AOP(result),l,offset);
10094       */
10095       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10096       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10097
10098       offset++;
10099     }
10100   }
10101
10102   /* mov the highest order bit to OVR */    
10103   tlbl = newiTempLabel(NULL);
10104   tlbl1= newiTempLabel(NULL);
10105
10106   size = AOP_SIZE(result);
10107   offset = size - 1;
10108
10109   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10110
10111   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10112
10113   /* offset should be 0, 1 or 3 */
10114   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10115   emitSKPNZ;
10116   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10117
10118   pic16_emitpcode(POC_MOVWF, pctemp);
10119
10120
10121   pic16_emitpLabel(tlbl->key);
10122
10123   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10124   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10125
10126   while(--size) {
10127     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10128   }
10129
10130   pic16_emitpcode(POC_DECFSZ,  pctemp);
10131   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10132   pic16_emitpLabel(tlbl1->key);
10133
10134   pic16_popReleaseTempReg(pctemp,1);
10135 #if 0
10136   size = AOP_SIZE(result);
10137   offset = size - 1;
10138   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10139   pic16_emitcode("rlc","a");
10140   pic16_emitcode("mov","ov,c");
10141   /* if it is only one byte then */
10142   if (size == 1) {
10143     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10144     MOVA(l);
10145     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10146     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10147     pic16_emitcode("mov","c,ov");
10148     pic16_emitcode("rrc","a");
10149     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10150     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10151     pic16_aopPut(AOP(result),"a",0);
10152     goto release ;
10153   }
10154
10155   reAdjustPreg(AOP(result));
10156   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10157   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10158   pic16_emitcode("mov","c,ov");
10159   while (size--) {
10160     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10161     MOVA(l);
10162     pic16_emitcode("rrc","a");         
10163     pic16_aopPut(AOP(result),"a",offset--);
10164   }
10165   reAdjustPreg(AOP(result));
10166   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10167   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10168
10169  release:
10170 #endif
10171
10172   pic16_freeAsmop(left,NULL,ic,TRUE);
10173   pic16_freeAsmop(result,NULL,ic,TRUE);
10174   pic16_freeAsmop(right,NULL,ic,TRUE);
10175 }
10176 #endif
10177
10178 #if !(USE_GENERIC_SIGNED_SHIFT)
10179 #warning This implementation of genRightShift() is incomplete!
10180 /*-----------------------------------------------------------------*/
10181 /* genRightShift - generate code for right shifting                */
10182 /*-----------------------------------------------------------------*/
10183 static void genRightShift (iCode *ic)
10184 {
10185     operand *right, *left, *result;
10186     sym_link *letype ;
10187     int size, offset;
10188     char *l;
10189     symbol *tlbl, *tlbl1 ;
10190
10191     /* if signed then we do it the hard way preserve the
10192     sign bit moving it inwards */
10193     letype = getSpec(operandType(IC_LEFT(ic)));
10194     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10195
10196     if (!SPEC_USIGN(letype)) {
10197         genSignedRightShift (ic);
10198         return ;
10199     }
10200
10201     /* signed & unsigned types are treated the same : i.e. the
10202     signed is NOT propagated inwards : quoting from the
10203     ANSI - standard : "for E1 >> E2, is equivalent to division
10204     by 2**E2 if unsigned or if it has a non-negative value,
10205     otherwise the result is implementation defined ", MY definition
10206     is that the sign does not get propagated */
10207
10208     right = IC_RIGHT(ic);
10209     left  = IC_LEFT(ic);
10210     result = IC_RESULT(ic);
10211
10212     pic16_aopOp(right,ic,FALSE);
10213
10214     /* if the shift count is known then do it 
10215     as efficiently as possible */
10216     if (AOP_TYPE(right) == AOP_LIT) {
10217         genRightShiftLiteral (left,right,result,ic, 0);
10218         return ;
10219     }
10220
10221     /* shift count is unknown then we have to form 
10222     a loop get the loop count in B : Note: we take
10223     only the lower order byte since shifting
10224     more that 32 bits make no sense anyway, ( the
10225     largest size of an object can be only 32 bits ) */  
10226
10227     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10228     pic16_emitcode("inc","b");
10229     pic16_aopOp(left,ic,FALSE);
10230     pic16_aopOp(result,ic,FALSE);
10231
10232     /* now move the left to the result if they are not the
10233     same */
10234     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10235         AOP_SIZE(result) > 1) {
10236
10237         size = AOP_SIZE(result);
10238         offset=0;
10239         while (size--) {
10240             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10241             if (*l == '@' && IS_AOP_PREG(result)) {
10242
10243                 pic16_emitcode("mov","a,%s",l);
10244                 pic16_aopPut(AOP(result),"a",offset);
10245             } else
10246                 pic16_aopPut(AOP(result),l,offset);
10247             offset++;
10248         }
10249     }
10250
10251     tlbl = newiTempLabel(NULL);
10252     tlbl1= newiTempLabel(NULL);
10253     size = AOP_SIZE(result);
10254     offset = size - 1;
10255
10256     /* if it is only one byte then */
10257     if (size == 1) {
10258
10259       tlbl = newiTempLabel(NULL);
10260       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10261         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10262         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10263       }
10264
10265       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10266       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10267       pic16_emitpLabel(tlbl->key);
10268       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10269       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10270       emitSKPC;
10271       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10272
10273       goto release ;
10274     }
10275
10276     reAdjustPreg(AOP(result));
10277     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10278     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10279     CLRC;
10280     while (size--) {
10281         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10282         MOVA(l);
10283         pic16_emitcode("rrc","a");         
10284         pic16_aopPut(AOP(result),"a",offset--);
10285     }
10286     reAdjustPreg(AOP(result));
10287
10288     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10289     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10290
10291 release:
10292     pic16_freeAsmop(left,NULL,ic,TRUE);
10293     pic16_freeAsmop (right,NULL,ic,TRUE);
10294     pic16_freeAsmop(result,NULL,ic,TRUE);
10295 }
10296 #endif
10297
10298 #if (USE_GENERIC_SIGNED_SHIFT)
10299 /*-----------------------------------------------------------------*/
10300 /* genGenericShift - generates code for left or right shifting     */
10301 /*-----------------------------------------------------------------*/
10302 static void genGenericShift (iCode *ic, int isShiftLeft) {
10303   operand *left,*right, *result;
10304   int offset;
10305   int sign, signedCount;
10306   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10307   PIC_OPCODE pos_shift, neg_shift;
10308
10309   FENTRY;
10310
10311   right = IC_RIGHT(ic);
10312   left  = IC_LEFT(ic);
10313   result = IC_RESULT(ic);
10314
10315   pic16_aopOp(right,ic,FALSE);
10316   pic16_aopOp(left,ic,FALSE);
10317   pic16_aopOp(result,ic,TRUE);
10318
10319   sign = !SPEC_USIGN(operandType (left));
10320   signedCount = !SPEC_USIGN(operandType (right));
10321
10322   /* if the shift count is known then do it 
10323      as efficiently as possible */
10324   if (AOP_TYPE(right) == AOP_LIT) {
10325     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10326     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10327     // we should modify right->aopu.aop_lit here!
10328     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10329     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10330     if (isShiftLeft)
10331       pic16_genLeftShiftLiteral (left,right,result,ic);
10332     else
10333       genRightShiftLiteral (left,right,result,ic, sign);
10334
10335     goto release;
10336   } // if (right is literal)
10337
10338   /* shift count is unknown then we have to form a loop.
10339    * Note: we take only the lower order byte since shifting
10340    * more than 32 bits make no sense anyway, ( the
10341    * largest size of an object can be only 32 bits )
10342    * Note: we perform arithmetic shifts if the left operand is
10343    * signed and we do an (effective) right shift, i. e. we
10344    * shift in the sign bit from the left. */
10345    
10346   label_complete = newiTempLabel ( NULL );
10347   label_loop_pos = newiTempLabel ( NULL );
10348   label_loop_neg = NULL;
10349   label_negative = NULL;
10350   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10351   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10352
10353   if (signedCount) {
10354     // additional labels needed
10355     label_loop_neg = newiTempLabel ( NULL );
10356     label_negative = newiTempLabel ( NULL );
10357   } // if
10358
10359   // copy source to result -- this will effectively truncate the left operand to the size of result!
10360   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10361   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10362   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10363     pic16_mov2f (AOP(result),AOP(left), offset);
10364   } // for
10365
10366   // if result is longer than left, fill with zeros (or sign)
10367   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10368     if (sign && AOP_SIZE(left) > 0) {
10369       // shift signed operand -- fill with sign
10370       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10371       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10372       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10373       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10374         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10375       } // for
10376     } else {
10377       // shift unsigned operand -- fill result with zeros
10378       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10379         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10380       } // for
10381     }
10382   } // if (size mismatch)
10383
10384   pic16_mov2w (AOP(right), 0);
10385   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10386   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10387   
10388 #if 0
10389   // perform a shift by one (shift count is positive)
10390   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10391   // 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])
10392   pic16_emitpLabel (label_loop_pos->key);
10393   emitCLRC;
10394   if (sign && (pos_shift == POC_RRCF)) {
10395     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10396     emitSETC;
10397   } // if
10398   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10399   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10400   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10401 #else
10402   // perform a shift by one (shift count is positive)
10403   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10404   // 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])
10405   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10406   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10407   emitCLRC;
10408   pic16_emitpLabel (label_loop_pos->key);
10409   if (sign && (pos_shift == POC_RRCF)) {
10410     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10411     emitSETC;
10412   } // if
10413   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10414   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10415   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10416   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10417 #endif
10418
10419   if (signedCount) {
10420     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10421
10422     pic16_emitpLabel (label_negative->key);
10423     // perform a shift by -1 (shift count is negative)
10424     // 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)
10425     emitCLRC;
10426     pic16_emitpLabel (label_loop_neg->key);
10427     if (sign && (neg_shift == POC_RRCF)) {
10428       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10429       emitSETC;
10430     } // if
10431     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10432     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10433     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10434     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10435   } // if (signedCount)
10436
10437   pic16_emitpLabel (label_complete->key);
10438
10439 release:
10440   pic16_freeAsmop (right,NULL,ic,TRUE);
10441   pic16_freeAsmop(left,NULL,ic,TRUE);
10442   pic16_freeAsmop(result,NULL,ic,TRUE);
10443 }
10444
10445 static void genLeftShift (iCode *ic) {
10446   genGenericShift (ic, 1);
10447 }
10448
10449 static void genRightShift (iCode *ic) {
10450   genGenericShift (ic, 0);
10451 }
10452 #endif
10453
10454
10455 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10456 void pic16_loadFSR0(operand *op, int lit)
10457 {
10458   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10459     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10460   } else {
10461     assert (!OP_SYMBOL(op)->remat);
10462     // set up FSR0 with address of result
10463     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10464     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10465   }
10466 }
10467
10468 /*----------------------------------------------------------------*/
10469 /* pic16_derefPtr - move one byte from the location ptr points to */
10470 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10471 /*                  to the location ptr points to (doWrite != 0)   */
10472 /*----------------------------------------------------------------*/
10473 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10474 {
10475   if (!IS_PTR(operandType(ptr)))
10476   {
10477     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10478     else pic16_mov2w (AOP(ptr), 0);
10479     return;
10480   }
10481
10482   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10483   /* We might determine pointer type right here: */
10484   p_type = DCL_TYPE(operandType(ptr));
10485
10486   switch (p_type) {
10487     case FPOINTER:
10488     case POINTER:
10489       if (!fsr0_setup || !*fsr0_setup)
10490       {
10491         pic16_loadFSR0( ptr, 0 );
10492         if (fsr0_setup) *fsr0_setup = 1;
10493       }
10494       if (doWrite)
10495         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10496       else
10497         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10498       break;
10499
10500     case GPOINTER:
10501       if (AOP(ptr)->aopu.aop_reg[2]) {
10502         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10503         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10504         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10505         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10506         pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10507         pic16_callGenericPointerRW(doWrite, 1);
10508       } else {
10509         // data pointer (just 2 byte given)
10510         if (!fsr0_setup || !*fsr0_setup)
10511         {
10512           pic16_loadFSR0( ptr, 0 );
10513           if (fsr0_setup) *fsr0_setup = 1;
10514         }
10515         if (doWrite)
10516           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10517         else
10518           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10519       }
10520       break;
10521
10522     default:
10523       assert (0 && "invalid pointer type specified");
10524       break;
10525   }
10526 }
10527
10528 /*-----------------------------------------------------------------*/
10529 /* genUnpackBits - generates code for unpacking bits               */
10530 /*-----------------------------------------------------------------*/
10531 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10532 {    
10533   int shCnt ;
10534   sym_link *etype, *letype;
10535   int blen=0, bstr=0;
10536   int lbstr;
10537   int same;
10538   pCodeOp *op;
10539
10540   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10541   etype = getSpec(operandType(result));
10542   letype = getSpec(operandType(left));
10543
10544   //    if(IS_BITFIELD(etype)) {
10545   blen = SPEC_BLEN(etype);
10546   bstr = SPEC_BSTR(etype);
10547   //    }
10548
10549   lbstr = SPEC_BSTR( letype );
10550
10551   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10552       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10553
10554 #if 1
10555   if((blen == 1) && (bstr < 8)
10556       && (!IS_PTR(operandType(left)) || PIC_IS_DATA_PTR(operandType(left)))) {
10557     /* it is a single bit, so use the appropriate bit instructions */
10558     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10559
10560     same = pic16_sameRegs(AOP(left),AOP(result));
10561     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10562     pic16_emitpcode(POC_CLRF, op);
10563
10564     if(!IS_PTR(operandType(left))) {
10565       /* workaround to reduce the extra lfsr instruction */
10566       pic16_emitpcode(POC_BTFSC,
10567           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10568     } else {
10569       assert (PIC_IS_DATA_PTR (operandType(left)));
10570       pic16_loadFSR0 (left, 0);
10571       pic16_emitpcode(POC_BTFSC,
10572           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10573     }
10574
10575     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10576       /* unsigned bitfields result in either 0 or 1 */
10577       pic16_emitpcode(POC_INCF, op);
10578     } else {
10579       /* signed bitfields result in either 0 or -1 */
10580       pic16_emitpcode(POC_DECF, op);
10581     }
10582     if (same) {
10583       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10584     }
10585
10586     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10587     return;
10588   }
10589
10590 #endif
10591
10592   if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10593     // access symbol directly
10594     pic16_mov2w (AOP(left), 0);
10595   } else {
10596     pic16_derefPtr (left, ptype, 0, NULL);
10597   }
10598
10599   /* if we have bitdisplacement then it fits   */
10600   /* into this byte completely or if length is */
10601   /* less than a byte                          */
10602   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10603
10604     /* shift right acc */
10605     AccRsh(shCnt, 0);
10606
10607     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10608           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10609
10610     /* VR -- normally I would use the following, but since we use the hack,
10611      * to avoid the masking from AccRsh, why not mask it right now? */
10612
10613     /*
10614        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10615      */
10616
10617     /* extend signed bitfields to 8 bits */
10618     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10619     {
10620       assert (blen + bstr > 0);
10621       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10622       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10623     }
10624
10625     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10626
10627     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10628     return ;
10629   }
10630
10631   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10632   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10633   exit(-1);
10634
10635   return ;
10636 }
10637
10638
10639 static void genDataPointerGet(operand *left,
10640                               operand *result,
10641                               iCode *ic)
10642 {
10643   int size, offset = 0, leoffset=0 ;
10644
10645         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10646         pic16_aopOp(result, ic, TRUE);
10647
10648         FENTRY;
10649
10650         size = AOP_SIZE(result);
10651 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10652
10653
10654 #if 0
10655         /* The following tests may save a redudant movff instruction when
10656          * accessing unions */
10657          
10658         /* if they are the same */
10659         if (operandsEqu (left, result)) {
10660                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10661                 goto release;
10662         }
10663 #endif
10664
10665 #if 0
10666         /* if they are the same registers */
10667         if (pic16_sameRegs(AOP(left),AOP(result))) {
10668                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10669                 goto release;
10670         }
10671 #endif
10672
10673 #if 1
10674         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10675                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10676                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10677                 goto release;
10678         }
10679 #endif
10680
10681
10682 #if 0
10683         if ( AOP_TYPE(left) == AOP_PCODE) {
10684                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10685                                 AOP(left)->aopu.pcop->name,
10686                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10687                                 PCOR(AOP(left)->aopu.pcop)->instance:
10688                                 PCOI(AOP(left)->aopu.pcop)->offset);
10689         }
10690 #endif
10691
10692         if(AOP(left)->aopu.pcop->type == PO_DIR)
10693                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10694
10695         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10696
10697         while (size--) {
10698                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10699                 
10700 //              pic16_DumpOp("(result)",result);
10701                 if(is_LitAOp(AOP(result))) {
10702                         pic16_mov2w(AOP(left), offset); // patch 8
10703                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10704                 } else {
10705                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10706                                 pic16_popGet(AOP(left), offset), //patch 8
10707                                 pic16_popGet(AOP(result), offset)));
10708                 }
10709
10710                 offset++;
10711                 leoffset++;
10712         }
10713
10714 release:
10715     pic16_freeAsmop(result,NULL,ic,TRUE);
10716 }
10717
10718
10719
10720 /*-----------------------------------------------------------------*/
10721 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10722 /*-----------------------------------------------------------------*/
10723 static void genNearPointerGet (operand *left, 
10724                                operand *result, 
10725                                iCode *ic)
10726 {
10727 //  asmop *aop = NULL;
10728   //regs *preg = NULL ;
10729   sym_link *rtype, *retype;
10730   sym_link *ltype, *letype;
10731
10732     FENTRY;
10733     
10734     rtype = operandType(result);
10735     retype= getSpec(rtype);
10736     ltype = operandType(left);
10737     letype= getSpec(ltype);
10738     
10739     pic16_aopOp(left,ic,FALSE);
10740
10741 //    pic16_DumpOp("(left)",left);
10742 //    pic16_DumpOp("(result)",result);
10743
10744     /* if left is rematerialisable and
10745      * result is not bit variable type and
10746      * the left is pointer to data space i.e
10747      * lower 128 bytes of space */
10748     
10749     if (AOP_TYPE(left) == AOP_PCODE
10750       && !IS_BITFIELD(retype)
10751       && DCL_TYPE(ltype) == POINTER) {
10752
10753         genDataPointerGet (left,result,ic);
10754         pic16_freeAsmop(left, NULL, ic, TRUE);
10755         return ;
10756     }
10757     
10758     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10759     pic16_aopOp (result,ic,TRUE);
10760     
10761     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10762
10763 #if 1
10764     if(IS_BITFIELD( retype )
10765       && (SPEC_BLEN(operandType(result))==1)
10766     ) {
10767       iCode *nextic;
10768       pCodeOp *jop;
10769       int bitstrt, bytestrt;
10770
10771         /* if this is bitfield of size 1, see if we are checking the value
10772          * of a single bit in an if-statement,
10773          * if yes, then don't generate usual code, but execute the
10774          * genIfx directly -- VR */
10775
10776         nextic = ic->next;
10777
10778         /* CHECK: if next iCode is IFX
10779          * and current result operand is nextic's conditional operand
10780          * and current result operand live ranges ends at nextic's key number
10781          */
10782         if((nextic->op == IFX)
10783           && (result == IC_COND(nextic))
10784           && (OP_LIVETO(result) == nextic->seq)
10785           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10786           ) {
10787             /* everything is ok then */
10788             /* find a way to optimize the genIfx iCode */
10789
10790             bytestrt = SPEC_BSTR(operandType(result))/8;
10791             bitstrt = SPEC_BSTR(operandType(result))%8;
10792             
10793             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10794
10795             genIfxpCOpJump(nextic, jop);
10796             
10797             pic16_freeAsmop(left, NULL, ic, TRUE);
10798             pic16_freeAsmop(result, NULL, ic, TRUE);
10799             return;
10800         }
10801     }
10802 #endif
10803
10804     /* if bitfield then unpack the bits */
10805     if (IS_BITFIELD(letype)) 
10806       genUnpackBits (result, left, NULL, POINTER);
10807     else {
10808       /* we have can just get the values */
10809       int size = AOP_SIZE(result);
10810       int offset = 0;   
10811         
10812       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10813
10814       pic16_loadFSR0( left, 0 );
10815
10816       while(size--) {
10817         if(size) {
10818           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10819                 pic16_popGet(AOP(result), offset++)));
10820         } else {
10821           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10822                 pic16_popGet(AOP(result), offset++)));
10823         }
10824       }
10825     }
10826
10827 #if 0
10828     /* now some housekeeping stuff */
10829     if (aop) {
10830       /* we had to allocate for this iCode */
10831       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10832       pic16_freeAsmop(NULL,aop,ic,TRUE);
10833     } else { 
10834       /* we did not allocate which means left
10835        * already in a pointer register, then
10836        * if size > 0 && this could be used again
10837        * we have to point it back to where it 
10838        * belongs */
10839       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10840       if (AOP_SIZE(result) > 1
10841         && !OP_SYMBOL(left)->remat
10842         && ( OP_SYMBOL(left)->liveTo > ic->seq
10843             || ic->depth )) {
10844 //        int size = AOP_SIZE(result) - 1;
10845 //        while (size--)
10846 //          pic16_emitcode("dec","%s",rname);
10847         }
10848     }
10849 #endif
10850
10851     /* done */
10852     pic16_freeAsmop(left,NULL,ic,TRUE);
10853     pic16_freeAsmop(result,NULL,ic,TRUE);
10854 }
10855
10856 /*-----------------------------------------------------------------*/
10857 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10858 /*-----------------------------------------------------------------*/
10859 static void genPagedPointerGet (operand *left, 
10860                                operand *result, 
10861                                iCode *ic)
10862 {
10863     asmop *aop = NULL;
10864     regs *preg = NULL ;
10865     char *rname ;
10866     sym_link *rtype, *retype;    
10867
10868     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10869
10870     rtype = operandType(result);
10871     retype= getSpec(rtype);
10872     
10873     pic16_aopOp(left,ic,FALSE);
10874
10875   /* if the value is already in a pointer register
10876        then don't need anything more */
10877     if (!AOP_INPREG(AOP(left))) {
10878         /* otherwise get a free pointer register */
10879         aop = newAsmop(0);
10880         preg = getFreePtr(ic,&aop,FALSE);
10881         pic16_emitcode("mov","%s,%s",
10882                 preg->name,
10883                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10884         rname = preg->name ;
10885     } else
10886         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10887     
10888     pic16_freeAsmop(left,NULL,ic,TRUE);
10889     pic16_aopOp (result,ic,TRUE);
10890
10891     /* if bitfield then unpack the bits */
10892     if (IS_BITFIELD(retype)) 
10893         genUnpackBits (result,left,rname,PPOINTER);
10894     else {
10895         /* we have can just get the values */
10896         int size = AOP_SIZE(result);
10897         int offset = 0 ;        
10898         
10899         while (size--) {
10900             
10901             pic16_emitcode("movx","a,@%s",rname);
10902             pic16_aopPut(AOP(result),"a",offset);
10903             
10904             offset++ ;
10905             
10906             if (size)
10907                 pic16_emitcode("inc","%s",rname);
10908         }
10909     }
10910
10911     /* now some housekeeping stuff */
10912     if (aop) {
10913         /* we had to allocate for this iCode */
10914         pic16_freeAsmop(NULL,aop,ic,TRUE);
10915     } else { 
10916         /* we did not allocate which means left
10917            already in a pointer register, then
10918            if size > 0 && this could be used again
10919            we have to point it back to where it 
10920            belongs */
10921         if (AOP_SIZE(result) > 1 &&
10922             !OP_SYMBOL(left)->remat &&
10923             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10924               ic->depth )) {
10925             int size = AOP_SIZE(result) - 1;
10926             while (size--)
10927                 pic16_emitcode("dec","%s",rname);
10928         }
10929     }
10930
10931     /* done */
10932     pic16_freeAsmop(result,NULL,ic,TRUE);
10933     
10934         
10935 }
10936
10937 #if 0
10938 /* This code is not adjusted to PIC16 and fails utterly.
10939  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10940
10941 /*-----------------------------------------------------------------*/
10942 /* genFarPointerGet - gget value from far space                    */
10943 /*-----------------------------------------------------------------*/
10944 static void genFarPointerGet (operand *left,
10945                               operand *result, iCode *ic)
10946 {
10947     int size, offset ;
10948     sym_link *retype = getSpec(operandType(result));
10949
10950     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10951
10952     pic16_aopOp(left,ic,FALSE);
10953
10954     /* if the operand is already in dptr 
10955     then we do nothing else we move the value to dptr */
10956     if (AOP_TYPE(left) != AOP_STR) {
10957         /* if this is remateriazable */
10958         if (AOP_TYPE(left) == AOP_IMMD)
10959             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10960         else { /* we need to get it byte by byte */
10961             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10962             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10963             if (options.model == MODEL_FLAT24)
10964             {
10965                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10966             }
10967         }
10968     }
10969     /* so dptr know contains the address */
10970     pic16_freeAsmop(left,NULL,ic,TRUE);
10971     pic16_aopOp(result,ic,TRUE);
10972
10973     /* if bit then unpack */
10974     if (IS_BITFIELD(retype)) 
10975         genUnpackBits(result,left,"dptr",FPOINTER);
10976     else {
10977         size = AOP_SIZE(result);
10978         offset = 0 ;
10979
10980         while (size--) {
10981             pic16_emitcode("movx","a,@dptr");
10982             pic16_aopPut(AOP(result),"a",offset++);
10983             if (size)
10984                 pic16_emitcode("inc","dptr");
10985         }
10986     }
10987
10988     pic16_freeAsmop(result,NULL,ic,TRUE);
10989 }
10990 #endif
10991
10992 #if 0
10993 /*-----------------------------------------------------------------*/
10994 /* genCodePointerGet - get value from code space                  */
10995 /*-----------------------------------------------------------------*/
10996 static void genCodePointerGet (operand *left,
10997                                 operand *result, iCode *ic)
10998 {
10999     int size, offset ;
11000     sym_link *retype = getSpec(operandType(result));
11001
11002     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11003
11004     pic16_aopOp(left,ic,FALSE);
11005
11006     /* if the operand is already in dptr 
11007     then we do nothing else we move the value to dptr */
11008     if (AOP_TYPE(left) != AOP_STR) {
11009         /* if this is remateriazable */
11010         if (AOP_TYPE(left) == AOP_IMMD)
11011             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11012         else { /* we need to get it byte by byte */
11013             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11014             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11015             if (options.model == MODEL_FLAT24)
11016             {
11017                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11018             }
11019         }
11020     }
11021     /* so dptr know contains the address */
11022     pic16_freeAsmop(left,NULL,ic,TRUE);
11023     pic16_aopOp(result,ic,FALSE);
11024
11025     /* if bit then unpack */
11026     if (IS_BITFIELD(retype)) 
11027         genUnpackBits(result,left,"dptr",CPOINTER);
11028     else {
11029         size = AOP_SIZE(result);
11030         offset = 0 ;
11031
11032         while (size--) {
11033             pic16_emitcode("clr","a");
11034             pic16_emitcode("movc","a,@a+dptr");
11035             pic16_aopPut(AOP(result),"a",offset++);
11036             if (size)
11037                 pic16_emitcode("inc","dptr");
11038         }
11039     }
11040
11041     pic16_freeAsmop(result,NULL,ic,TRUE);
11042 }
11043 #endif
11044
11045 #if 0
11046 /*-----------------------------------------------------------------*/
11047 /* genGenPointerGet - gget value from generic pointer space        */
11048 /*-----------------------------------------------------------------*/
11049 static void genGenPointerGet (operand *left,
11050                               operand *result, iCode *ic)
11051 {
11052   int size, offset, lit;
11053   sym_link *retype = getSpec(operandType(result));
11054
11055         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11056         pic16_aopOp(left,ic,FALSE);
11057         pic16_aopOp(result,ic,FALSE);
11058         size = AOP_SIZE(result);
11059
11060         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11061
11062         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11063
11064                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11065                 // load FSR0 from immediate
11066                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11067
11068 //              pic16_loadFSR0( left );
11069
11070                 offset = 0;
11071                 while(size--) {
11072                         if(size) {
11073                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11074                         } else {
11075                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11076                         }
11077                         offset++;
11078                 }
11079                 goto release;
11080
11081         }
11082         else { /* we need to get it byte by byte */
11083                 // set up FSR0 with address from left
11084                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11085                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11086                 
11087                 offset = 0 ;
11088
11089                 while(size--) {
11090                         if(size) {
11091                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11092                         } else {
11093                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11094                         }
11095                         offset++;
11096                 }
11097                 goto release;
11098         }
11099
11100   /* if bit then unpack */
11101         if (IS_BITFIELD(retype)) 
11102                 genUnpackBits(result,left,"BAD",GPOINTER);
11103
11104         release:
11105         pic16_freeAsmop(left,NULL,ic,TRUE);
11106         pic16_freeAsmop(result,NULL,ic,TRUE);
11107
11108 }
11109 #endif
11110
11111
11112 /*-----------------------------------------------------------------*/
11113 /* genGenPointerGet - gget value from generic pointer space        */
11114 /*-----------------------------------------------------------------*/
11115 static void genGenPointerGet (operand *left,
11116                               operand *result, iCode *ic)
11117 {
11118   int size, offset, lit;
11119   sym_link *letype = getSpec(operandType(left));
11120
11121     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11122     pic16_aopOp(left,ic,FALSE);
11123     pic16_aopOp(result,ic,TRUE);
11124     size = AOP_SIZE(result);
11125
11126     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11127   
11128     /* if bit then unpack */
11129     if (IS_BITFIELD(letype)) {
11130       genUnpackBits(result,left,"BAD",GPOINTER);
11131       goto release;
11132     }
11133
11134     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11135
11136       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11137       // load FSR0 from immediate
11138       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11139
11140       werror(W_POSSBUG2, __FILE__, __LINE__);
11141
11142       offset = 0;
11143       while(size--) {
11144         if(size) {
11145           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11146         } else {
11147           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11148         }
11149         offset++;
11150       }
11151
11152       goto release;
11153
11154     } else { /* we need to get it byte by byte */
11155
11156       /* set up WREG:PRODL:FSR0L with address from left */
11157       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11158       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11159       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11160       
11161       pic16_callGenericPointerRW(0, size);
11162       
11163       assignResultValue(result, 1);
11164       
11165       goto release;
11166     }
11167
11168 release:
11169   pic16_freeAsmop(left,NULL,ic,TRUE);
11170   pic16_freeAsmop(result,NULL,ic,TRUE);
11171 }
11172
11173 /*-----------------------------------------------------------------*/
11174 /* genConstPointerGet - get value from const generic pointer space */
11175 /*-----------------------------------------------------------------*/
11176 static void genConstPointerGet (operand *left,
11177                                 operand *result, iCode *ic)
11178 {
11179   //sym_link *retype = getSpec(operandType(result));
11180   // symbol *albl = newiTempLabel(NULL);        // patch 15
11181   // symbol *blbl = newiTempLabel(NULL);        //
11182   // PIC_OPCODE poc;                            // patch 15
11183   int size;
11184   int offset = 0;
11185
11186   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11187   pic16_aopOp(left,ic,FALSE);
11188   pic16_aopOp(result,ic,TRUE);
11189   size = AOP_SIZE(result);
11190
11191   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11192
11193   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11194
11195   // set up table pointer
11196   if( (AOP_TYPE(left) == AOP_PCODE) 
11197       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11198           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11199     {
11200       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11201       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11202       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11203       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11204       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11205       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11206   } else {
11207     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11208     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11209     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11210   }
11211
11212   while(size--) {
11213     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11214     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11215     offset++;
11216   }
11217     
11218   pic16_freeAsmop(left,NULL,ic,TRUE);
11219   pic16_freeAsmop(result,NULL,ic,TRUE);
11220 }
11221
11222
11223 /*-----------------------------------------------------------------*/
11224 /* genPointerGet - generate code for pointer get                   */
11225 /*-----------------------------------------------------------------*/
11226 static void genPointerGet (iCode *ic)
11227 {
11228   operand *left, *result ;
11229   sym_link *type, *etype;
11230   int p_type;
11231
11232     FENTRY;
11233     
11234     left = IC_LEFT(ic);
11235     result = IC_RESULT(ic) ;
11236
11237     /* depending on the type of pointer we need to
11238     move it to the correct pointer register */
11239     type = operandType(left);
11240     etype = getSpec(type);
11241
11242 #if 0
11243     if (IS_PTR_CONST(type))
11244 #else
11245     if (IS_CODEPTR(type))
11246 #endif
11247       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11248
11249     /* if left is of type of pointer then it is simple */
11250     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11251       p_type = DCL_TYPE(type);
11252     else {
11253       /* we have to go by the storage class */
11254       p_type = PTR_TYPE(SPEC_OCLS(etype));
11255
11256       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11257
11258       if (SPEC_OCLS(etype)->codesp ) {
11259         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11260         //p_type = CPOINTER ;   
11261       } else
11262       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11263         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11264         /*p_type = FPOINTER ;*/ 
11265       } else
11266       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11267         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11268         /* p_type = PPOINTER; */
11269       } else
11270       if (SPEC_OCLS(etype) == idata ) {
11271         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11272         /* p_type = IPOINTER; */
11273       } else {
11274         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11275         /* p_type = POINTER ; */
11276       }
11277     }
11278
11279     /* now that we have the pointer type we assign
11280     the pointer values */
11281     switch (p_type) {
11282       case POINTER:     
11283       case FPOINTER:
11284       case IPOINTER:
11285         genNearPointerGet (left,result,ic);
11286         break;
11287
11288       case PPOINTER:
11289         genPagedPointerGet(left,result,ic);
11290         break;
11291
11292 #if 0
11293       /* PICs do not support FAR pointers... */
11294       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11295       case FPOINTER:
11296         genFarPointerGet (left,result,ic);
11297         break;
11298 #endif
11299
11300       case CPOINTER:
11301         genConstPointerGet (left,result,ic);
11302         //pic16_emitcodePointerGet (left,result,ic);
11303         break;
11304
11305       case GPOINTER:
11306 #if 0
11307       if (IS_PTR_CONST(type))
11308         genConstPointerGet (left,result,ic);
11309       else
11310 #endif
11311         genGenPointerGet (left,result,ic);
11312       break;
11313
11314     default:
11315       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11316               "genPointerGet: illegal pointer type");
11317     
11318     }
11319 }
11320
11321 /*-----------------------------------------------------------------*/
11322 /* genPackBits - generates code for packed bit storage             */
11323 /*-----------------------------------------------------------------*/
11324 static void genPackBits (sym_link    *etype , operand *result,
11325                          operand *right ,
11326                          char *rname, int p_type)
11327 {
11328   int shCnt = 0 ;
11329   int offset = 0  ;
11330   int rLen = 0 ;
11331   int blen, bstr ;   
11332   sym_link *retype;
11333
11334   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11335   blen = SPEC_BLEN(etype);
11336   bstr = SPEC_BSTR(etype);
11337
11338   retype = getSpec(operandType(right));
11339
11340   if(AOP_TYPE(right) == AOP_LIT) {
11341     if((blen == 1) && (bstr < 8)) {
11342       unsigned long lit;
11343       /* it is a single bit, so use the appropriate bit instructions */
11344
11345       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11346
11347       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11348       //                        pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11349       if(!IS_PTR(operandType(result))) {
11350         /* workaround to reduce the extra lfsr instruction */
11351         if(lit) {
11352           pic16_emitpcode(POC_BSF,
11353               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11354         } else {
11355           pic16_emitpcode(POC_BCF,
11356               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11357         }
11358       } else {
11359         if (PIC_IS_DATA_PTR(operandType(result))) {
11360           pic16_loadFSR0(result, 0);
11361           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11362               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11363         } else {
11364           /* get old value */
11365           pic16_derefPtr (result, p_type, 0, NULL);
11366           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11367               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11368           /* write back new value */
11369           pic16_derefPtr (result, p_type, 1, NULL);
11370         }
11371       }
11372
11373       return;
11374     }
11375     /* move literal to W */
11376     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11377     offset++;
11378   } else
11379     if(IS_BITFIELD(retype) 
11380         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11381         && (blen == 1)) {
11382       int rblen, rbstr;
11383
11384       rblen = SPEC_BLEN( retype );
11385       rbstr = SPEC_BSTR( retype );
11386
11387
11388       if(IS_BITFIELD(etype)) {
11389         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11390         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11391       } else {
11392         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11393       }
11394
11395       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11396
11397       if(IS_BITFIELD(etype)) {
11398         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11399       } else {
11400         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11401       }
11402
11403       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11404
11405       return;
11406     } else {
11407       /* move right to W */
11408       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11409     }
11410
11411   /* if the bit length is less than or   */
11412   /* it exactly fits a byte then         */
11413   if((shCnt=SPEC_BSTR(etype))
11414       || SPEC_BLEN(etype) <= 8 )  {
11415     int fsr0_setup = 0;
11416
11417     if (blen != 8 || bstr != 0) {
11418       // we need to combine the value with the old value
11419       pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11420
11421       DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11422           SPEC_BSTR(etype), SPEC_BLEN(etype));
11423
11424       /* shift left acc */
11425       AccLsh(shCnt);
11426
11427       /* using PRODH as a temporary register here */
11428       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11429
11430       if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11431         /* access symbol directly */
11432         pic16_mov2w (AOP(result), 0);
11433       } else {
11434         /* get old value */
11435         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11436       }
11437 #if 1
11438       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11439             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11440                             (unsigned char)(0xff >> (8-bstr))) ));
11441       pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11442     } // if (blen != 8 || bstr != 0)
11443
11444     /* write new value back */
11445     if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11446       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11447     } else {
11448       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11449     }
11450 #endif
11451
11452     return;
11453   }
11454
11455
11456 #if 0
11457   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11458   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11459   exit(-1);
11460 #endif
11461
11462
11463   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11464   rLen = SPEC_BLEN(etype)-8;
11465
11466   /* now generate for lengths greater than one byte */
11467   while (1) {
11468     rLen -= 8 ;
11469     if (rLen <= 0 ) {
11470       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11471       break ;
11472     }
11473
11474     switch (p_type) {
11475       case POINTER:
11476         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11477         break;
11478
11479         /*
11480            case FPOINTER:
11481            MOVA(l);
11482            pic16_emitcode("movx","@dptr,a");
11483            break;
11484
11485            case GPOINTER:
11486            MOVA(l);
11487            DEBUGpic16_emitcode(";lcall","__gptrput");
11488            break;  
11489          */
11490       default:
11491         assert(0);
11492     }   
11493
11494
11495     pic16_mov2w(AOP(right), offset++);
11496   }
11497
11498   /* last last was not complete */
11499   if (rLen)   {
11500     /* save the byte & read byte */
11501     switch (p_type) {
11502       case POINTER:
11503         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11504         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11505         break;
11506
11507         /*
11508            case FPOINTER:
11509            pic16_emitcode ("mov","b,a");
11510            pic16_emitcode("movx","a,@dptr");
11511            break;
11512
11513            case GPOINTER:
11514            pic16_emitcode ("push","b");
11515            pic16_emitcode ("push","acc");
11516            pic16_emitcode ("lcall","__gptrget");
11517            pic16_emitcode ("pop","b");
11518            break;
11519          */
11520       default:
11521         assert(0);
11522     }
11523     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11524     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11525     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11526     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11527     //        pic16_emitcode ("orl","a,b");
11528   }
11529
11530   //    if (p_type == GPOINTER)
11531   //        pic16_emitcode("pop","b");
11532
11533   switch (p_type) {
11534
11535     case POINTER:
11536       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11537       //        pic16_emitcode("mov","@%s,a",rname);
11538       break;
11539       /*
11540          case FPOINTER:
11541          pic16_emitcode("movx","@dptr,a");
11542          break;
11543
11544          case GPOINTER:
11545          DEBUGpic16_emitcode(";lcall","__gptrput");
11546          break;                 
11547        */
11548     default:
11549       assert(0);
11550   }
11551
11552   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11553 }
11554
11555 /*-----------------------------------------------------------------*/
11556 /* genDataPointerSet - remat pointer to data space                 */
11557 /*-----------------------------------------------------------------*/
11558 static void genDataPointerSet(operand *right,
11559                               operand *result,
11560                               iCode *ic)
11561 {
11562     int size, offset = 0, resoffset=0 ;
11563
11564     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11565     pic16_aopOp(right,ic,FALSE);
11566
11567     size = AOP_SIZE(right);
11568
11569 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11570
11571 #if 0
11572     if ( AOP_TYPE(result) == AOP_PCODE) {
11573       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11574               AOP(result)->aopu.pcop->name,
11575                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11576               PCOR(AOP(result)->aopu.pcop)->instance:
11577               PCOI(AOP(result)->aopu.pcop)->offset);
11578     }
11579 #endif
11580
11581         if(AOP(result)->aopu.pcop->type == PO_DIR)
11582                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11583
11584         while (size--) {
11585                 if (AOP_TYPE(right) == AOP_LIT) {
11586                   unsigned int lit;
11587
11588                     if(!IS_FLOAT(operandType( right )))
11589                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11590                     else {
11591                       union {
11592                         unsigned long lit_int;
11593                         float lit_float;
11594                       } info;
11595         
11596                         /* take care if literal is a float */
11597                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11598                         lit = info.lit_int;
11599                     }
11600
11601                     lit = lit >> (8*offset);
11602                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11603                 } else {
11604                   pic16_mov2w(AOP(right), offset);
11605                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11606                 }
11607                 offset++;
11608                 resoffset++;
11609         }
11610
11611     pic16_freeAsmop(right,NULL,ic,TRUE);
11612 }
11613
11614
11615
11616 /*-----------------------------------------------------------------*/
11617 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11618 /*-----------------------------------------------------------------*/
11619 static void genNearPointerSet (operand *right,
11620                                operand *result, 
11621                                iCode *ic)
11622 {
11623   asmop *aop = NULL;
11624   sym_link *retype;
11625   sym_link *ptype = operandType(result);
11626   sym_link *resetype;
11627     
11628         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11629         retype= getSpec(operandType(right));
11630         resetype = getSpec(operandType(result));
11631   
11632         pic16_aopOp(result,ic,FALSE);
11633     
11634         /* if the result is rematerializable &
11635          * in data space & not a bit variable */
11636         
11637         /* and result is not a bit variable */
11638         if (AOP_TYPE(result) == AOP_PCODE
11639 //              && AOP_TYPE(result) == AOP_IMMD
11640                 && DCL_TYPE(ptype) == POINTER
11641                 && !IS_BITFIELD(retype)
11642                 && !IS_BITFIELD(resetype)) {
11643
11644                 genDataPointerSet (right,result,ic);
11645                 pic16_freeAsmop(result,NULL,ic,TRUE);
11646           return;
11647         }
11648
11649         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11650         pic16_aopOp(right,ic,FALSE);
11651         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11652
11653         /* if bitfield then unpack the bits */
11654         if (IS_BITFIELD(resetype)) {
11655                 genPackBits (resetype, result, right, NULL, POINTER);
11656         } else {
11657                 /* we have can just get the values */
11658           int size = AOP_SIZE(right);
11659           int offset = 0 ;    
11660
11661             pic16_loadFSR0(result, 0);
11662             
11663                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11664                 while (size--) {
11665                                 if (AOP_TYPE(right) == AOP_LIT) {
11666                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11667                                         if (size) {
11668                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11669                                         } else {
11670                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11671                                         }
11672                                 } else { // no literal
11673                                         if(size) {
11674                                                 pic16_emitpcode(POC_MOVFF,
11675                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11676                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11677                                         } else {
11678                                                 pic16_emitpcode(POC_MOVFF,
11679                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11680                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11681                                         }
11682                                 }
11683                         offset++;
11684                 }
11685         }
11686
11687         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11688         /* now some housekeeping stuff */
11689         if (aop) {
11690           /* we had to allocate for this iCode */
11691           pic16_freeAsmop(NULL,aop,ic,TRUE);
11692         } else { 
11693           /* we did not allocate which means left
11694            * already in a pointer register, then
11695            * if size > 0 && this could be used again
11696            * we have to point it back to where it 
11697            * belongs */
11698           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11699           if (AOP_SIZE(right) > 1
11700             && !OP_SYMBOL(result)->remat
11701             && ( OP_SYMBOL(result)->liveTo > ic->seq
11702             || ic->depth )) {
11703
11704               int size = AOP_SIZE(right) - 1;
11705
11706                 while (size--)
11707                   pic16_emitcode("decf","fsr0,f");
11708                   //pic16_emitcode("dec","%s",rname);
11709             }
11710         }
11711
11712     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11713     /* done */
11714 //release:
11715     pic16_freeAsmop(right,NULL,ic,TRUE);
11716     pic16_freeAsmop(result,NULL,ic,TRUE);
11717 }
11718
11719 /*-----------------------------------------------------------------*/
11720 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11721 /*-----------------------------------------------------------------*/
11722 static void genPagedPointerSet (operand *right,
11723                                operand *result, 
11724                                iCode *ic)
11725 {
11726     asmop *aop = NULL;
11727     regs *preg = NULL ;
11728     char *rname , *l;
11729     sym_link *retype;
11730        
11731     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11732
11733     retype= getSpec(operandType(right));
11734     
11735     pic16_aopOp(result,ic,FALSE);
11736     
11737     /* if the value is already in a pointer register
11738        then don't need anything more */
11739     if (!AOP_INPREG(AOP(result))) {
11740         /* otherwise get a free pointer register */
11741         aop = newAsmop(0);
11742         preg = getFreePtr(ic,&aop,FALSE);
11743         pic16_emitcode("mov","%s,%s",
11744                 preg->name,
11745                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11746         rname = preg->name ;
11747     } else
11748         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11749     
11750     pic16_freeAsmop(result,NULL,ic,TRUE);
11751     pic16_aopOp (right,ic,FALSE);
11752
11753     /* if bitfield then unpack the bits */
11754     if (IS_BITFIELD(retype)) 
11755         genPackBits (retype,result,right,rname,PPOINTER);
11756     else {
11757         /* we have can just get the values */
11758         int size = AOP_SIZE(right);
11759         int offset = 0 ;        
11760         
11761         while (size--) {
11762             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11763             
11764             MOVA(l);
11765             pic16_emitcode("movx","@%s,a",rname);
11766
11767             if (size)
11768                 pic16_emitcode("inc","%s",rname);
11769
11770             offset++;
11771         }
11772     }
11773     
11774     /* now some housekeeping stuff */
11775     if (aop) {
11776         /* we had to allocate for this iCode */
11777         pic16_freeAsmop(NULL,aop,ic,TRUE);
11778     } else { 
11779         /* we did not allocate which means left
11780            already in a pointer register, then
11781            if size > 0 && this could be used again
11782            we have to point it back to where it 
11783            belongs */
11784         if (AOP_SIZE(right) > 1 &&
11785             !OP_SYMBOL(result)->remat &&
11786             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11787               ic->depth )) {
11788             int size = AOP_SIZE(right) - 1;
11789             while (size--)
11790                 pic16_emitcode("dec","%s",rname);
11791         }
11792     }
11793
11794     /* done */
11795     pic16_freeAsmop(right,NULL,ic,TRUE);
11796     
11797         
11798 }
11799
11800 #if 0
11801 /* This code is not adjusted to PIC16 and fails utterly...
11802  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11803
11804 /*-----------------------------------------------------------------*/
11805 /* genFarPointerSet - set value from far space                     */
11806 /*-----------------------------------------------------------------*/
11807 static void genFarPointerSet (operand *right,
11808                               operand *result, iCode *ic)
11809 {
11810     int size, offset ;
11811     sym_link *retype = getSpec(operandType(right));
11812
11813     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11814     pic16_aopOp(result,ic,FALSE);
11815
11816     /* if the operand is already in dptr 
11817     then we do nothing else we move the value to dptr */
11818     if (AOP_TYPE(result) != AOP_STR) {
11819         /* if this is remateriazable */
11820         if (AOP_TYPE(result) == AOP_IMMD)
11821             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11822         else { /* we need to get it byte by byte */
11823             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11824             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11825             if (options.model == MODEL_FLAT24)
11826             {
11827                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11828             }
11829         }
11830     }
11831     /* so dptr know contains the address */
11832     pic16_freeAsmop(result,NULL,ic,TRUE);
11833     pic16_aopOp(right,ic,FALSE);
11834
11835     /* if bit then unpack */
11836     if (IS_BITFIELD(retype)) 
11837         genPackBits(retype,result,right,"dptr",FPOINTER);
11838     else {
11839         size = AOP_SIZE(right);
11840         offset = 0 ;
11841
11842         while (size--) {
11843             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11844             MOVA(l);
11845             pic16_emitcode("movx","@dptr,a");
11846             if (size)
11847                 pic16_emitcode("inc","dptr");
11848         }
11849     }
11850
11851     pic16_freeAsmop(right,NULL,ic,TRUE);
11852 }
11853 #endif
11854
11855 /*-----------------------------------------------------------------*/
11856 /* genGenPointerSet - set value from generic pointer space         */
11857 /*-----------------------------------------------------------------*/
11858 #if 0
11859 static void genGenPointerSet (operand *right,
11860                               operand *result, iCode *ic)
11861 {
11862         int i, size, offset, lit;
11863         sym_link *retype = getSpec(operandType(right));
11864
11865         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11866
11867         pic16_aopOp(result,ic,FALSE);
11868         pic16_aopOp(right,ic,FALSE);
11869         size = AOP_SIZE(right);
11870         offset = 0;
11871
11872         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11873
11874         /* if the operand is already in dptr 
11875                 then we do nothing else we move the value to dptr */
11876         if (AOP_TYPE(result) != AOP_STR) {
11877                 /* if this is remateriazable */
11878                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11879                 // WARNING: anythig until "else" is untested!
11880                 if (AOP_TYPE(result) == AOP_IMMD) {
11881                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11882                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11883                         // load FSR0 from immediate
11884                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11885                         offset = 0;
11886                         while(size--) {
11887                                 if(size) {
11888                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11889                                 } else {
11890                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11891                                 }
11892                                 offset++;
11893                         }
11894                         goto release;
11895                 }
11896                 else { /* we need to get it byte by byte */
11897                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11898                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11899
11900                         // set up FSR0 with address of result
11901                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11902                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11903
11904                         /* hack hack! see if this the FSR. If so don't load W */
11905                         if(AOP_TYPE(right) != AOP_ACC) {
11906
11907                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11908
11909                                 if(AOP_TYPE(right) == AOP_LIT)
11910                                 {
11911                                         // copy literal
11912                                         // note: pic16_popGet handles sign extension
11913                                         for(i=0;i<size;i++) {
11914                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11915                                                 if(i < size-1)
11916                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11917                                                 else
11918                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11919                                         }
11920                                 } else {
11921                                         // copy regs
11922
11923                                         for(i=0;i<size;i++) {
11924                                                 if(i < size-1)
11925                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11926                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11927                                                 else
11928                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11929                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11930                                         }
11931                                 }
11932                                 goto release;
11933                         } 
11934                         // right = ACC
11935                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11936                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11937                         goto release;
11938         } // if (AOP_TYPE(result) != AOP_IMMD)
11939
11940         } // if (AOP_TYPE(result) != AOP_STR)
11941         /* so dptr know contains the address */
11942
11943
11944         /* if bit then unpack */
11945         if (IS_BITFIELD(retype)) 
11946                 genPackBits(retype,result,right,"dptr",GPOINTER);
11947         else {
11948                 size = AOP_SIZE(right);
11949                 offset = 0 ;
11950
11951                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11952
11953                 // set up FSR0 with address of result
11954                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11955                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11956         
11957                 while (size--) {
11958                         if (AOP_TYPE(right) == AOP_LIT) {
11959                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11960                                 if (size) {
11961                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11962                                 } else {
11963                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11964                                 }
11965                         } else { // no literal
11966                                 if(size) {
11967                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11968                                 } else {
11969                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11970                                 }
11971                         }
11972                         offset++;
11973                 }
11974         }
11975
11976         release:
11977         pic16_freeAsmop(right,NULL,ic,TRUE);
11978         pic16_freeAsmop(result,NULL,ic,TRUE);
11979 }
11980 #endif
11981
11982 static void genGenPointerSet (operand *right,
11983                               operand *result, iCode *ic)
11984 {
11985   int size;
11986   sym_link *retype = getSpec(operandType(result));
11987
11988     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11989
11990     pic16_aopOp(result,ic,FALSE);
11991     pic16_aopOp(right,ic,FALSE);
11992     size = AOP_SIZE(right);
11993
11994     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11995
11996
11997     /* if bit then unpack */
11998     if (IS_BITFIELD(retype)) {
11999 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12000       genPackBits(retype,result,right,"dptr",GPOINTER);
12001       goto release;
12002     }
12003
12004     size = AOP_SIZE(right);
12005
12006     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12007
12008
12009     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12010
12011     /* value of right+0 is placed on stack, which will be retrieved
12012      * by the support function this restoring the stack. The important
12013      * thing is that there is no need to manually restore stack pointer
12014      * here */
12015     pushaop(AOP(right), 0);
12016 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12017     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12018     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12019     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12020     
12021     /* load address to write to in WREG:FSR0H:FSR0L */
12022     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12023                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12024     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12025                                 pic16_popCopyReg(&pic16_pc_prodl)));
12026     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12027     
12028     pic16_callGenericPointerRW(1, size);
12029
12030 release:
12031     pic16_freeAsmop(right,NULL,ic,TRUE);
12032     pic16_freeAsmop(result,NULL,ic,TRUE);
12033 }
12034
12035 /*-----------------------------------------------------------------*/
12036 /* genPointerSet - stores the value into a pointer location        */
12037 /*-----------------------------------------------------------------*/
12038 static void genPointerSet (iCode *ic)
12039 {    
12040   operand *right, *result ;
12041   sym_link *type, *etype;
12042   int p_type;
12043
12044     FENTRY;
12045
12046     right = IC_RIGHT(ic);
12047     result = IC_RESULT(ic) ;
12048
12049     /* depending on the type of pointer we need to
12050     move it to the correct pointer register */
12051     type = operandType(result);
12052     etype = getSpec(type);
12053     
12054     /* if left is of type of pointer then it is simple */
12055     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12056         p_type = DCL_TYPE(type);
12057     }
12058     else {
12059         /* we have to go by the storage class */
12060         p_type = PTR_TYPE(SPEC_OCLS(etype));
12061
12062 /*      if (SPEC_OCLS(etype)->codesp ) { */
12063 /*          p_type = CPOINTER ;  */
12064 /*      } */
12065 /*      else */
12066 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12067 /*              p_type = FPOINTER ; */
12068 /*          else */
12069 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12070 /*                  p_type = PPOINTER ; */
12071 /*              else */
12072 /*                  if (SPEC_OCLS(etype) == idata ) */
12073 /*                      p_type = IPOINTER ; */
12074 /*                  else */
12075 /*                      p_type = POINTER ; */
12076     }
12077
12078     /* now that we have the pointer type we assign
12079     the pointer values */
12080     switch (p_type) {
12081       case POINTER:
12082       case FPOINTER:
12083       case IPOINTER:
12084         genNearPointerSet (right,result,ic);
12085         break;
12086
12087       case PPOINTER:
12088         genPagedPointerSet (right,result,ic);
12089         break;
12090
12091 #if 0
12092       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12093       case FPOINTER:
12094         genFarPointerSet (right,result,ic);
12095         break;
12096 #endif
12097         
12098       case GPOINTER:
12099         genGenPointerSet (right,result,ic);
12100         break;
12101
12102       default:
12103         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12104           "genPointerSet: illegal pointer type");
12105     }
12106 }
12107
12108 /*-----------------------------------------------------------------*/
12109 /* genIfx - generate code for Ifx statement                        */
12110 /*-----------------------------------------------------------------*/
12111 static void genIfx (iCode *ic, iCode *popIc)
12112 {
12113   operand *cond = IC_COND(ic);
12114   int isbit =0;
12115
12116     FENTRY;
12117
12118     pic16_aopOp(cond,ic,FALSE);
12119
12120     /* get the value into acc */
12121     if (AOP_TYPE(cond) != AOP_CRY)
12122       pic16_toBoolean(cond);
12123     else
12124       isbit = 1;
12125     /* the result is now in the accumulator */
12126     pic16_freeAsmop(cond,NULL,ic,TRUE);
12127
12128     /* if there was something to be popped then do it */
12129     if (popIc)
12130       genIpop(popIc);
12131
12132     /* if the condition is  a bit variable */
12133     if (isbit && IS_ITEMP(cond) && 
12134         SPIL_LOC(cond)) {
12135       genIfxJump(ic,"c");
12136       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12137     } else {
12138       if (isbit && !IS_ITEMP(cond))
12139         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12140         else
12141         genIfxJump(ic,"a");
12142     }
12143     ic->generated = 1;
12144 }
12145
12146 /*-----------------------------------------------------------------*/
12147 /* genAddrOf - generates code for address of                       */
12148 /*-----------------------------------------------------------------*/
12149 static void genAddrOf (iCode *ic)
12150 {
12151   operand *result, *left;
12152   int size;
12153   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12154   pCodeOp *pcop0, *pcop1, *pcop2;
12155
12156     FENTRY;
12157
12158     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12159
12160     sym = OP_SYMBOL( IC_LEFT(ic) );
12161     
12162     if(sym->onStack) {
12163       /* get address of symbol on stack */
12164       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12165 #if 0
12166       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12167                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12168 #endif
12169
12170       // operands on stack are accessible via "FSR2 + index" with index
12171       // starting at 2 for arguments and growing from 0 downwards for
12172       // local variables (index == 0 is not assigned so we add one here)
12173       {
12174         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12175         if (soffs <= 0) {
12176           assert (soffs < 0);
12177           soffs++;
12178         } // if
12179         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12180         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12181         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12182         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12183         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12184         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12185         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12186       }
12187
12188       goto release;
12189     }
12190         
12191 //      if(pic16_debug_verbose) {
12192 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12193 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12194 //      }
12195         
12196     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12197     size = AOP_SIZE(IC_RESULT(ic));
12198
12199     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12200     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12201     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12202         
12203     if (size == 3) {
12204       pic16_emitpcode(POC_MOVLW, pcop0);
12205       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12206       pic16_emitpcode(POC_MOVLW, pcop1);
12207       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12208       pic16_emitpcode(POC_MOVLW, pcop2);
12209       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12210     } else
12211     if (size == 2) {
12212       pic16_emitpcode(POC_MOVLW, pcop0);
12213       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12214       pic16_emitpcode(POC_MOVLW, pcop1);
12215     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12216     } else {
12217       pic16_emitpcode(POC_MOVLW, pcop0);
12218       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12219     }
12220
12221     pic16_freeAsmop(left, NULL, ic, FALSE);
12222 release:
12223     pic16_freeAsmop(result,NULL,ic,TRUE);
12224 }
12225
12226
12227 #if 0
12228 /*-----------------------------------------------------------------*/
12229 /* genFarFarAssign - assignment when both are in far space         */
12230 /*-----------------------------------------------------------------*/
12231 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12232 {
12233     int size = AOP_SIZE(right);
12234     int offset = 0;
12235     char *l ;
12236     /* first push the right side on to the stack */
12237     while (size--) {
12238         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12239         MOVA(l);
12240         pic16_emitcode ("push","acc");
12241     }
12242     
12243     pic16_freeAsmop(right,NULL,ic,FALSE);
12244     /* now assign DPTR to result */
12245     pic16_aopOp(result,ic,FALSE);
12246     size = AOP_SIZE(result);
12247     while (size--) {
12248         pic16_emitcode ("pop","acc");
12249         pic16_aopPut(AOP(result),"a",--offset);
12250     }
12251     pic16_freeAsmop(result,NULL,ic,FALSE);
12252         
12253 }
12254 #endif
12255
12256 /*-----------------------------------------------------------------*/
12257 /* genAssign - generate code for assignment                        */
12258 /*-----------------------------------------------------------------*/
12259 static void genAssign (iCode *ic)
12260 {
12261   operand *result, *right;
12262   sym_link *restype, *rtype;
12263   int size, offset,know_W;
12264   unsigned long lit = 0L;
12265
12266   result = IC_RESULT(ic);
12267   right  = IC_RIGHT(ic) ;
12268
12269   FENTRY;
12270   
12271   /* if they are the same */
12272   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12273     return ;
12274
12275   /* reversed order operands are aopOp'ed so that result operand
12276    * is effective in case right is a stack symbol. This maneauver
12277    * allows to use the _G.resDirect flag later */
12278   pic16_aopOp(result,ic,TRUE);
12279   pic16_aopOp(right,ic,FALSE);
12280
12281   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12282
12283   /* if they are the same registers */
12284   if (pic16_sameRegs(AOP(right),AOP(result)))
12285     goto release;
12286
12287   /* if the result is a bit */
12288   if (AOP_TYPE(result) == AOP_CRY) {
12289     /* if the right size is a literal then
12290        we know what the value is */
12291     if (AOP_TYPE(right) == AOP_LIT) {
12292           
12293       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12294                   pic16_popGet(AOP(result),0));
12295
12296       if (((int) operandLitValue(right))) 
12297         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12298                        AOP(result)->aopu.aop_dir,
12299                        AOP(result)->aopu.aop_dir);
12300       else
12301         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12302                        AOP(result)->aopu.aop_dir,
12303                        AOP(result)->aopu.aop_dir);
12304       goto release;
12305     }
12306
12307     /* the right is also a bit variable */
12308     if (AOP_TYPE(right) == AOP_CRY) {
12309       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12310       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12311       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12312
12313       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12314                      AOP(result)->aopu.aop_dir,
12315                      AOP(result)->aopu.aop_dir);
12316       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12317                      AOP(right)->aopu.aop_dir,
12318                      AOP(right)->aopu.aop_dir);
12319       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12320                      AOP(result)->aopu.aop_dir,
12321                      AOP(result)->aopu.aop_dir);
12322       goto release ;
12323     }
12324
12325     /* we need to or */
12326     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12327     pic16_toBoolean(right);
12328     emitSKPZ;
12329     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12330     //pic16_aopPut(AOP(result),"a",0);
12331     goto release ;
12332   }
12333
12334   /* bit variables done */
12335   /* general case */
12336   size = AOP_SIZE(result);
12337   restype = operandType(result);
12338   rtype = operandType(right);
12339   offset = 0 ;
12340
12341   if(AOP_TYPE(right) == AOP_LIT) {
12342     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12343     {
12344       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12345
12346       /* patch tag for literals that are cast to pointers */
12347       if (IS_CODEPTR(restype)) {
12348         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12349         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12350       } else {
12351         if (IS_GENPTR(restype))
12352         {
12353           if (IS_CODEPTR(rtype)) {
12354             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12355             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12356           } else if (PIC_IS_DATA_PTR(rtype)) {
12357             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12358             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12359           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12360             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12361           } else if (IS_PTR(rtype)) {
12362             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12363             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12364           }
12365         }
12366       }
12367     } else {
12368       union {
12369         unsigned long lit_int;
12370         float lit_float;
12371       } info;
12372
12373
12374       if(IS_FIXED16X16(operandType(right))) {
12375         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12376       } else {
12377         /* take care if literal is a float */
12378         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12379         lit = info.lit_int;
12380       }
12381     }
12382   }
12383
12384 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12385 //                      sizeof(unsigned long int), sizeof(float));
12386
12387
12388   if (AOP_TYPE(right) == AOP_REG) {
12389     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12390     while (size--) {
12391       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12392     } // while
12393     goto release;
12394   }
12395
12396   /* when do we have to read the program memory?
12397    * - if right itself is a symbol in code space
12398    *   (we don't care what it points to if it's a pointer)
12399    * - AND right is not a function (we would want its address)
12400    */
12401   if(AOP_TYPE(right) != AOP_LIT
12402         && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12403         && !IS_FUNC(OP_SYM_TYPE(right))
12404         && !IS_ITEMP(right))
12405   {
12406         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12407         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12408
12409         // set up table pointer
12410         if(is_LitOp(right)) {
12411 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12412                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12413                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12414                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12415                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12416                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12417                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12418         } else {
12419 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12420                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12421                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12422                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12423                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12424                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12425                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12426         }
12427
12428         /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12429         size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12430         while(size--) {
12431                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12432                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12433                         pic16_popGet(AOP(result),offset)));
12434                 offset++;
12435         }
12436
12437         /* FIXME: for pointers we need to extend differently (according
12438          * to pointer type DATA/CODE/EEPROM/... :*/
12439         size = getSize(OP_SYM_TYPE(right));
12440         if(AOP_SIZE(result) > size) {
12441                 size = AOP_SIZE(result) - size;
12442                 while(size--) {
12443                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12444                         offset++;
12445                 }
12446         }
12447         goto release;
12448   }
12449
12450 #if 0
12451 /* VR - What is this?! */
12452   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12453     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12454     if(aopIdx(AOP(result),0) == 4) {
12455
12456       /* this is a workaround to save value of right into wreg too,
12457        * value of wreg is going to be used later */
12458       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12459       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12460       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12461       goto release;
12462     } else
12463 //      assert(0);
12464       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12465   }
12466 #endif
12467
12468   know_W=-1;
12469   while (size--) {
12470     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12471     if(AOP_TYPE(right) == AOP_LIT) {
12472       if(lit&0xff) {
12473         if(know_W != (lit&0xff))
12474           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12475         know_W = lit&0xff;
12476         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12477       } else
12478         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12479
12480       lit >>= 8;
12481
12482     } else if (AOP_TYPE(right) == AOP_CRY) {
12483       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12484       if(offset == 0) {
12485         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12486         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12487         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12488       }
12489     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12490         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12491         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12492     } else {
12493       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12494
12495       if(!_G.resDirect)         /* use this aopForSym feature */
12496         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12497     }
12498             
12499     offset++;
12500   }
12501   
12502  release:
12503   pic16_freeAsmop (right,NULL,ic,FALSE);
12504   pic16_freeAsmop (result,NULL,ic,TRUE);
12505
12506
12507 /*-----------------------------------------------------------------*/
12508 /* genJumpTab - generates code for jump table                       */
12509 /*-----------------------------------------------------------------*/
12510 static void genJumpTab (iCode *ic)
12511 {
12512   symbol *jtab;
12513   char *l;
12514   pCodeOp *jt_offs;
12515   pCodeOp *jt_offs_hi;
12516   pCodeOp *jt_label;
12517
12518     FENTRY;
12519
12520     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12521     /* get the condition into accumulator */
12522     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12523     MOVA(l);
12524     /* multiply by three */
12525     pic16_emitcode("add","a,acc");
12526     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12527
12528     jtab = newiTempLabel(NULL);
12529     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12530     pic16_emitcode("jmp","@a+dptr");
12531     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12532
12533 #if 0
12534     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12535     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12536     emitSKPNC;
12537     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12538     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12539     pic16_emitpLabel(jtab->key);
12540
12541 #else
12542
12543     jt_offs = pic16_popGetTempReg(0);
12544     jt_offs_hi = pic16_popGetTempReg(1);
12545     jt_label = pic16_popGetLabel (jtab->key);
12546     //fprintf (stderr, "Creating jump table...\n");
12547
12548     // calculate offset into jump table (idx * sizeof (GOTO))
12549     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12550     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12551     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12552     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12553     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12554     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12555     pic16_emitpcode(POC_MOVWF , jt_offs);
12556
12557     // prepare PCLATx (set to first entry in jump table)
12558     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12559     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12560     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12561     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12562     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12563
12564     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12565     pic16_emitpcode(POC_ADDWF , jt_offs);
12566     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12567     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12568     emitSKPNC;
12569     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12570
12571     // release temporaries and prepare jump into table (new PCL --> WREG)
12572     pic16_emitpcode(POC_MOVFW , jt_offs);
12573     pic16_popReleaseTempReg (jt_offs_hi, 1);
12574     pic16_popReleaseTempReg (jt_offs, 0);
12575
12576     // jump into the table
12577     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12578
12579     pic16_emitpLabelFORCE(jtab->key);
12580 #endif
12581
12582     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12583 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12584
12585     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12586     /* now generate the jump labels */
12587     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12588          jtab = setNextItem(IC_JTLABELS(ic))) {
12589 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12590         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12591         
12592     }
12593     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12594
12595 }
12596
12597 /*-----------------------------------------------------------------*/
12598 /* genMixedOperation - gen code for operators between mixed types  */
12599 /*-----------------------------------------------------------------*/
12600 /*
12601   TSD - Written for the PIC port - but this unfortunately is buggy.
12602   This routine is good in that it is able to efficiently promote 
12603   types to different (larger) sizes. Unfortunately, the temporary
12604   variables that are optimized out by this routine are sometimes
12605   used in other places. So until I know how to really parse the 
12606   iCode tree, I'm going to not be using this routine :(.
12607 */
12608 static int genMixedOperation (iCode *ic)
12609 {
12610 #if 0
12611   operand *result = IC_RESULT(ic);
12612   sym_link *ctype = operandType(IC_LEFT(ic));
12613   operand *right = IC_RIGHT(ic);
12614   int ret = 0;
12615   int big,small;
12616   int offset;
12617
12618   iCode *nextic;
12619   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12620
12621   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12622
12623   nextic = ic->next;
12624   if(!nextic)
12625     return 0;
12626
12627   nextright = IC_RIGHT(nextic);
12628   nextleft  = IC_LEFT(nextic);
12629   nextresult = IC_RESULT(nextic);
12630
12631   pic16_aopOp(right,ic,FALSE);
12632   pic16_aopOp(result,ic,FALSE);
12633   pic16_aopOp(nextright,  nextic, FALSE);
12634   pic16_aopOp(nextleft,   nextic, FALSE);
12635   pic16_aopOp(nextresult, nextic, FALSE);
12636
12637   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12638
12639     operand *t = right;
12640     right = nextright;
12641     nextright = t; 
12642
12643     pic16_emitcode(";remove right +","");
12644
12645   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12646 /*
12647     operand *t = right;
12648     right = nextleft;
12649     nextleft = t; 
12650 */
12651     pic16_emitcode(";remove left +","");
12652   } else
12653     return 0;
12654
12655   big = AOP_SIZE(nextleft);
12656   small = AOP_SIZE(nextright);
12657
12658   switch(nextic->op) {
12659
12660   case '+':
12661     pic16_emitcode(";optimize a +","");
12662     /* if unsigned or not an integral type */
12663     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12664       pic16_emitcode(";add a bit to something","");
12665     } else {
12666
12667       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12668
12669       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12670         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12671         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12672       } else
12673         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12674
12675       offset = 0;
12676       while(--big) {
12677
12678         offset++;
12679
12680         if(--small) {
12681           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12682             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12683             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12684           }
12685
12686           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12687           emitSKPNC;
12688           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12689                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12690                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12691           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12692           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12693
12694         } else {
12695           pic16_emitcode("rlf","known_zero,w");
12696
12697           /*
12698             if right is signed
12699               btfsc  right,7
12700                addlw ff
12701           */
12702           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12703             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12704             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12705           } else {
12706             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12707           }
12708         }
12709       }
12710       ret = 1;
12711     }
12712   }
12713   ret = 1;
12714
12715 release:
12716   pic16_freeAsmop(right,NULL,ic,TRUE);
12717   pic16_freeAsmop(result,NULL,ic,TRUE);
12718   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12719   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12720   if(ret)
12721     nextic->generated = 1;
12722
12723   return ret;
12724 #else
12725   return 0;
12726 #endif
12727 }
12728 /*-----------------------------------------------------------------*/
12729 /* genCast - gen code for casting                                  */
12730 /*-----------------------------------------------------------------*/
12731 static void genCast (iCode *ic)
12732 {
12733   operand *result = IC_RESULT(ic);
12734   sym_link *ctype = operandType(IC_LEFT(ic));
12735   sym_link *rtype = operandType(IC_RIGHT(ic));
12736   sym_link *restype = operandType(IC_RESULT(ic));
12737   operand *right = IC_RIGHT(ic);
12738   int size, offset ;
12739
12740
12741     FENTRY;
12742
12743         /* if they are equivalent then do nothing */
12744 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12745 //              return ;
12746
12747         pic16_aopOp(result,ic,FALSE);
12748         pic16_aopOp(right,ic,FALSE) ;
12749
12750         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12751
12752
12753         /* if the result is a bit */
12754         if (AOP_TYPE(result) == AOP_CRY) {
12755         
12756                 /* if the right size is a literal then
12757                  * we know what the value is */
12758                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12759
12760                 if (AOP_TYPE(right) == AOP_LIT) {
12761                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12762                                 pic16_popGet(AOP(result),0));
12763
12764                         if (((int) operandLitValue(right))) 
12765                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12766                                         AOP(result)->aopu.aop_dir,
12767                                         AOP(result)->aopu.aop_dir);
12768                         else
12769                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12770                                         AOP(result)->aopu.aop_dir,
12771                                         AOP(result)->aopu.aop_dir);
12772                         goto release;
12773                 }
12774
12775                 /* the right is also a bit variable */
12776                 if (AOP_TYPE(right) == AOP_CRY) {
12777                         emitCLRC;
12778                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12779
12780                         pic16_emitcode("clrc","");
12781                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12782                                 AOP(right)->aopu.aop_dir,
12783                                 AOP(right)->aopu.aop_dir);
12784                         pic16_aopPut(AOP(result),"c",0);
12785                         goto release ;
12786                 }
12787
12788                 /* we need to or */
12789                 if (AOP_TYPE(right) == AOP_REG) {
12790                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12791                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12792                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12793                 }
12794                 pic16_toBoolean(right);
12795                 pic16_aopPut(AOP(result),"a",0);
12796                 goto release ;
12797         }
12798
12799         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12800           int offset = 1;
12801
12802                 size = AOP_SIZE(result);
12803
12804                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12805
12806                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12807                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12808                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12809
12810                 while (size--)
12811                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12812
12813                 goto release;
12814         }
12815
12816         if(IS_BITFIELD(getSpec(restype))
12817           && IS_BITFIELD(getSpec(rtype))) {
12818           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12819         }
12820         
12821         /* port from pic14 to cope with generic pointers */
12822         if (PIC_IS_TAGGED(restype))
12823         {
12824           operand *result = IC_RESULT(ic);
12825           //operand *left = IC_LEFT(ic);
12826           operand *right = IC_RIGHT(ic);
12827           int tag = 0xff;
12828
12829           /* copy common part */
12830           int max, size = AOP_SIZE(result);
12831           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12832           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12833
12834           max = size;
12835           while (size--)
12836           {
12837             pic16_mov2w (AOP(right), size);
12838             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12839           } // while
12840
12841           /* upcast into generic pointer type? */
12842           if (IS_GENPTR(restype)
12843               && !PIC_IS_TAGGED(rtype)
12844               && (AOP_SIZE(result) > max))
12845           {
12846             /* determine appropriate tag for right */
12847             if (PIC_IS_DATA_PTR(rtype))
12848               tag = GPTR_TAG_DATA;
12849             else if (IS_CODEPTR(rtype))
12850               tag = GPTR_TAG_CODE;
12851             else if (PIC_IS_DATA_PTR(ctype)) {
12852               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12853               tag = GPTR_TAG_DATA;
12854             } else if (IS_CODEPTR(ctype)) {
12855               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12856               tag = GPTR_TAG_CODE;
12857             } else if (IS_PTR(rtype)) {
12858               PERFORM_ONCE(weirdcast,
12859               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12860               );
12861               tag = GPTR_TAG_DATA;
12862             } else {
12863               PERFORM_ONCE(weirdcast,
12864               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12865               );
12866               tag = GPTR_TAG_DATA;
12867             }
12868
12869             assert (AOP_SIZE(result) == 3);
12870             /* zero-extend address... */
12871             for (size = max; size < AOP_SIZE(result)-1; size++)
12872               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12873             /* ...and add tag */
12874             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12875           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12876             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12877             for (size = max; size < AOP_SIZE(result)-1; size++)
12878               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12879             /* add __code tag */
12880             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12881           } else if (AOP_SIZE(result) > max) {
12882             /* extend non-pointers */
12883             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12884             pic16_addSign(result, max, 0);
12885           } // if
12886           goto release;
12887         }
12888
12889         /* if they are the same size : or less */
12890         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12891
12892                 /* if they are in the same place */
12893                 if (pic16_sameRegs(AOP(right),AOP(result)))
12894                         goto release;
12895
12896                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12897 #if 0
12898                 if (IS_PTR_CONST(rtype))
12899 #else
12900                 if (IS_CODEPTR(rtype))
12901 #endif
12902                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12903
12904 #if 0
12905                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12906 #else
12907                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12908 #endif
12909                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12910
12911 #if 0
12912                 if(AOP_TYPE(right) == AOP_IMMD) {
12913                   pCodeOp *pcop0, *pcop1, *pcop2;
12914                   symbol *sym = OP_SYMBOL( right );
12915
12916                         size = AOP_SIZE(result);
12917                         /* low */
12918                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12919                         /* high */
12920                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12921                         /* upper */
12922                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12923         
12924                         if (size == 3) {
12925                                 pic16_emitpcode(POC_MOVLW, pcop0);
12926                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12927                                 pic16_emitpcode(POC_MOVLW, pcop1);
12928                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12929                                 pic16_emitpcode(POC_MOVLW, pcop2);
12930                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12931                         } else
12932                         if (size == 2) {
12933                                 pic16_emitpcode(POC_MOVLW, pcop0);
12934                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12935                                 pic16_emitpcode(POC_MOVLW, pcop1);
12936                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12937                         } else {
12938                                 pic16_emitpcode(POC_MOVLW, pcop0);
12939                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12940                         }
12941                 } else
12942 #endif
12943                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12944                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12945                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12946                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12947                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12948                         if(AOP_SIZE(result) <2)
12949                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12950                 } else {
12951                         /* if they in different places then copy */
12952                         size = AOP_SIZE(result);
12953                         offset = 0 ;
12954                         while (size--) {
12955                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12956                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12957                                 offset++;
12958                         }
12959                 }
12960                 goto release;
12961         }
12962
12963         /* if the result is of type pointer */
12964         if (IS_PTR(ctype)) {
12965           int p_type;
12966           sym_link *type = operandType(right);
12967           sym_link *etype = getSpec(type);
12968
12969                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12970
12971                 /* pointer to generic pointer */
12972                 if (IS_GENPTR(ctype)) {
12973                   char *l = zero;
12974             
12975                         if (IS_PTR(type)) 
12976                                 p_type = DCL_TYPE(type);
12977                         else {
12978                 /* we have to go by the storage class */
12979                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12980
12981 /*              if (SPEC_OCLS(etype)->codesp )  */
12982 /*                  p_type = CPOINTER ;  */
12983 /*              else */
12984 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12985 /*                      p_type = FPOINTER ; */
12986 /*                  else */
12987 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12988 /*                          p_type = PPOINTER; */
12989 /*                      else */
12990 /*                          if (SPEC_OCLS(etype) == idata ) */
12991 /*                              p_type = IPOINTER ; */
12992 /*                          else */
12993 /*                              p_type = POINTER ; */
12994             }
12995                 
12996             /* the first two bytes are known */
12997       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12998             size = GPTRSIZE - 1; 
12999             offset = 0 ;
13000             while (size--) {
13001               if(offset < AOP_SIZE(right)) {
13002                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13003                 pic16_mov2f(AOP(result), AOP(right), offset);
13004 /*
13005                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13006                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13007                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13008                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13009                 } else { 
13010                   
13011                   pic16_aopPut(AOP(result),
13012                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13013                          offset);
13014                 }
13015 */
13016               } else 
13017                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13018               offset++;
13019             }
13020             /* the last byte depending on type */
13021             switch (p_type) {
13022             case IPOINTER:
13023             case POINTER:
13024             case FPOINTER:
13025                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13026                 break;
13027
13028             case CPOINTER:
13029                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13030                 break;
13031
13032             case PPOINTER:
13033               pic16_emitcode(";BUG!? ","%d",__LINE__);
13034                 l = "#0x03";
13035                 break;
13036
13037             case GPOINTER:
13038                 if (GPTRSIZE > AOP_SIZE(right)) {
13039                   // assume __data pointer... THIS MIGHT BE WRONG!
13040                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13041                 } else {
13042                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13043                 }
13044               break;
13045               
13046             default:
13047                 /* this should never happen */
13048                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13049                        "got unknown pointer type");
13050                 exit(1);
13051             }
13052             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13053             goto release ;
13054         }
13055         
13056         
13057         assert( 0 );
13058         /* just copy the pointers */
13059         size = AOP_SIZE(result);
13060         offset = 0 ;
13061         while (size--) {
13062             pic16_aopPut(AOP(result),
13063                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13064                    offset);
13065             offset++;
13066         }
13067         goto release ;
13068     }
13069     
13070
13071
13072     /* so we now know that the size of destination is greater
13073     than the size of the source.
13074     Now, if the next iCode is an operator then we might be
13075     able to optimize the operation without performing a cast.
13076     */
13077     if(genMixedOperation(ic))
13078       goto release;
13079
13080     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13081     
13082     /* we move to result for the size of source */
13083     size = AOP_SIZE(right);
13084     offset = 0 ;
13085
13086     while (size--) {
13087       if(!_G.resDirect)
13088         pic16_mov2f(AOP(result), AOP(right), offset);
13089       offset++;
13090     }
13091
13092     /* now depending on the sign of the destination */
13093     size = AOP_SIZE(result) - AOP_SIZE(right);
13094     /* if unsigned or not an integral type */
13095     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13096       while (size--)
13097         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13098     } else {
13099       /* we need to extend the sign :( */
13100
13101       if(size == 1) {
13102         /* Save one instruction of casting char to int */
13103         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13104         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13105         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13106       } else {
13107         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13108
13109         if(offset)
13110           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13111         else
13112           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13113         
13114         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13115
13116         while (size--)
13117           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13118       }
13119     }
13120
13121 release:
13122     pic16_freeAsmop(right,NULL,ic,TRUE);
13123     pic16_freeAsmop(result,NULL,ic,TRUE);
13124
13125 }
13126
13127 /*-----------------------------------------------------------------*/
13128 /* genDjnz - generate decrement & jump if not zero instrucion      */
13129 /*-----------------------------------------------------------------*/
13130 static int genDjnz (iCode *ic, iCode *ifx)
13131 {
13132     symbol *lbl, *lbl1;
13133     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13134
13135     if (!ifx)
13136         return 0;
13137     
13138     /* if the if condition has a false label
13139        then we cannot save */
13140     if (IC_FALSE(ifx))
13141         return 0;
13142
13143     /* if the minus is not of the form 
13144        a = a - 1 */
13145     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13146         !IS_OP_LITERAL(IC_RIGHT(ic)))
13147         return 0;
13148
13149     if (operandLitValue(IC_RIGHT(ic)) != 1)
13150         return 0;
13151
13152     /* if the size of this greater than one then no
13153        saving */
13154     if (getSize(operandType(IC_RESULT(ic))) > 1)
13155         return 0;
13156
13157     /* otherwise we can save BIG */
13158     lbl = newiTempLabel(NULL);
13159     lbl1= newiTempLabel(NULL);
13160
13161     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13162     
13163     if (IS_AOP_PREG(IC_RESULT(ic))) {
13164         pic16_emitcode("dec","%s",
13165                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13166         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13167         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13168     } else {    
13169
13170
13171       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13172       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13173
13174       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13175       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13176
13177     }
13178     
13179     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13180     ifx->generated = 1;
13181     return 1;
13182 }
13183
13184 /*-----------------------------------------------------------------*/
13185 /* genReceive - generate code for a receive iCode                  */
13186 /*-----------------------------------------------------------------*/
13187 static void genReceive (iCode *ic)
13188 {    
13189
13190   FENTRY;
13191
13192 #if 0
13193   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13194         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13195 #endif
13196 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13197
13198   if (isOperandInFarSpace(IC_RESULT(ic))
13199       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13200           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13201
13202     int size = getSize(operandType(IC_RESULT(ic)));
13203     int offset =  pic16_fReturnSizePic - size;
13204
13205       assert( 0 );
13206       while (size--) {
13207         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13208                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13209                       offset++;
13210         }
13211
13212       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13213
13214       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13215       size = AOP_SIZE(IC_RESULT(ic));
13216       offset = 0;
13217       while (size--) {
13218         pic16_emitcode ("pop","acc");
13219         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13220       }
13221   } else {
13222     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13223     _G.accInUse++;
13224     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13225     _G.accInUse--;
13226
13227     /* set pseudo stack pointer to where it should be - dw*/
13228     GpsuedoStkPtr = ic->parmBytes;
13229
13230     /* setting GpsuedoStkPtr has side effects here: */
13231     assignResultValue(IC_RESULT(ic), 0);
13232   }
13233
13234   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13235 }
13236
13237 /*-----------------------------------------------------------------*/
13238 /* genDummyRead - generate code for dummy read of volatiles        */
13239 /*-----------------------------------------------------------------*/
13240 static void
13241 genDummyRead (iCode * ic)
13242 {
13243   operand *op;
13244   int i;
13245
13246   op = IC_RIGHT(ic);
13247   if (op && IS_SYMOP(op)) {
13248     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13249       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13250       return;
13251     }
13252     pic16_aopOp (op, ic, FALSE);
13253     for (i=0; i < AOP_SIZE(op); i++) {
13254       // may need to protect this from the peepholer -- this is not nice but works...
13255       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13256       pic16_mov2w (AOP(op),i);
13257       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13258     } // for i
13259     pic16_freeAsmop (op, NULL, ic, TRUE);
13260   } else if (op) {
13261     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13262   } // if
13263 }
13264
13265 /*-----------------------------------------------------------------*/
13266 /* genpic16Code - generate code for pic16 based controllers        */
13267 /*-----------------------------------------------------------------*/
13268 /*
13269  * At this point, ralloc.c has gone through the iCode and attempted
13270  * to optimize in a way suitable for a PIC. Now we've got to generate
13271  * PIC instructions that correspond to the iCode.
13272  *
13273  * Once the instructions are generated, we'll pass through both the
13274  * peep hole optimizer and the pCode optimizer.
13275  *-----------------------------------------------------------------*/
13276
13277 void genpic16Code (iCode *lic)
13278 {
13279   iCode *ic;
13280   int cln = 0;
13281
13282     lineHead = lineCurr = NULL;
13283
13284     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13285     pic16_addpBlock(pb);
13286
13287 #if 0
13288     /* if debug information required */
13289     if (options.debug && currFunc) {
13290       if (currFunc) {
13291         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13292       }
13293     }
13294 #endif
13295
13296     for (ic = lic ; ic ; ic = ic->next ) {
13297
13298       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13299       if ( cln != ic->lineno ) {
13300         if ( options.debug ) {
13301           debugFile->writeCLine (ic);
13302         }
13303         
13304         if(!options.noCcodeInAsm) {
13305           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13306               printCLine(ic->filename, ic->lineno)));
13307         }
13308
13309         cln = ic->lineno ;
13310       }
13311         
13312       if(options.iCodeInAsm) {
13313         char *l;
13314
13315           /* insert here code to print iCode as comment */
13316           l = Safe_strdup(printILine(ic));
13317           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13318       }
13319         
13320       /* if the result is marked as
13321        * spilt and rematerializable or code for
13322        * this has already been generated then
13323        * do nothing */
13324       if (resultRemat(ic) || ic->generated ) 
13325         continue ;
13326         
13327       /* depending on the operation */
13328       switch (ic->op) {
13329         case '!' :
13330           pic16_genNot(ic);
13331           break;
13332             
13333         case '~' :
13334           pic16_genCpl(ic);
13335           break;
13336             
13337         case UNARYMINUS:
13338           genUminus (ic);
13339           break;
13340             
13341         case IPUSH:
13342           genIpush (ic);
13343           break;
13344             
13345         case IPOP:
13346           /* IPOP happens only when trying to restore a 
13347            * spilt live range, if there is an ifx statement
13348            * following this pop then the if statement might
13349            * be using some of the registers being popped which
13350            * would destroy the contents of the register so
13351            * we need to check for this condition and handle it */
13352            if (ic->next
13353              && ic->next->op == IFX
13354              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13355                genIfx (ic->next,ic);
13356           else
13357             genIpop (ic);
13358           break; 
13359             
13360         case CALL:
13361           genCall (ic);
13362           break;
13363             
13364         case PCALL:
13365           genPcall (ic);
13366           break;
13367             
13368         case FUNCTION:
13369           genFunction (ic);
13370           break;
13371             
13372         case ENDFUNCTION:
13373           genEndFunction (ic);
13374           break;
13375             
13376         case RETURN:
13377           genRet (ic);
13378           break;
13379             
13380         case LABEL:
13381           genLabel (ic);
13382           break;
13383             
13384         case GOTO:
13385           genGoto (ic);
13386           break;
13387             
13388         case '+' :
13389           pic16_genPlus (ic) ;
13390           break;
13391             
13392         case '-' :
13393           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13394             pic16_genMinus (ic);
13395           break;
13396
13397         case '*' :
13398           genMult (ic);
13399           break;
13400             
13401         case '/' :
13402           genDiv (ic) ;
13403           break;
13404             
13405         case '%' :
13406           genMod (ic);
13407           break;
13408             
13409         case '>' :
13410           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13411           break;
13412             
13413         case '<' :
13414           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13415           break;
13416             
13417         case LE_OP:
13418         case GE_OP:
13419         case NE_OP:
13420           /* note these two are xlated by algebraic equivalence
13421            * during parsing SDCC.y */
13422           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13423             "got '>=' or '<=' shouldn't have come here");
13424           break;
13425
13426         case EQ_OP:
13427           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13428           break;            
13429             
13430         case AND_OP:
13431           genAndOp (ic);
13432           break;
13433             
13434         case OR_OP:
13435           genOrOp (ic);
13436           break;
13437             
13438         case '^' :
13439           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13440           break;
13441             
13442         case '|' :
13443           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13444           break;
13445             
13446         case BITWISEAND:
13447           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13448           break;
13449             
13450         case INLINEASM:
13451           genInline (ic);
13452           break;
13453             
13454         case RRC:
13455           genRRC (ic);
13456           break;
13457             
13458         case RLC:
13459           genRLC (ic);
13460           break;
13461             
13462         case GETHBIT:
13463           genGetHbit (ic);
13464           break;
13465             
13466         case LEFT_OP:
13467           genLeftShift (ic);
13468           break;
13469             
13470         case RIGHT_OP:
13471           genRightShift (ic);
13472           break;
13473             
13474         case GET_VALUE_AT_ADDRESS:
13475           genPointerGet(ic);
13476           break;
13477             
13478         case '=' :
13479           if (POINTER_SET(ic))
13480             genPointerSet(ic);
13481           else
13482             genAssign(ic);
13483           break;
13484             
13485         case IFX:
13486           genIfx (ic,NULL);
13487           break;
13488             
13489         case ADDRESS_OF:
13490           genAddrOf (ic);
13491           break;
13492             
13493         case JUMPTABLE:
13494           genJumpTab (ic);
13495           break;
13496             
13497         case CAST:
13498           genCast (ic);
13499           break;
13500             
13501         case RECEIVE:
13502           genReceive(ic);
13503           break;
13504             
13505         case SEND:
13506           addSet(&_G.sendSet,ic);
13507           break;
13508
13509         case DUMMY_READ_VOLATILE:
13510           genDummyRead (ic);
13511           break;
13512
13513         default :
13514           ic = ic;
13515       }
13516     }
13517
13518
13519     /* now we are ready to call the
13520        peep hole optimizer */
13521     if (!options.nopeep)
13522       peepHole (&lineHead);
13523
13524     /* now do the actual printing */
13525     printLine (lineHead, codeOutFile);
13526
13527 #ifdef PCODE_DEBUG
13528     DFPRINTF((stderr,"printing pBlock\n\n"));
13529     pic16_printpBlock(stdout,pb);
13530 #endif
13531
13532     return;
13533 }
13534