* src/regression/empty.c: suppress warning
[fw/sdcc] / src / pic16 / gen.c
1  /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
10   Bug Fixes  -  Raphael Neider <rneider AT web.de> (2004,2005)
11   Bug Fixes  -  Borut Razem <borut.razem AT siol.net> (2007)
12
13   This program is free software; you can redistribute it and/or modify it
14   under the terms of the GNU General Public License as published by the
15   Free Software Foundation; either version 2, or (at your option) any
16   later version.
17
18   This program is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details.
22
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27   In other words, you are welcome to use, share and improve this program.
28   You are forbidden to forbid anyone else to use, share and improve
29   what you give them.   Help stamp out software-hoarding!
30
31   Notes:
32   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
33                 Made everything static
34 -------------------------------------------------------------------------*/
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include "SDCCglobl.h"
41 #include "newalloc.h"
42
43 #include "common.h"
44 #include "SDCCpeeph.h"
45 #include "ralloc.h"
46 #include "pcode.h"
47 #include "gen.h"
48 #include "genutils.h"
49 #include "device.h"
50 #include "main.h"
51 #include "glue.h"
52
53 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
54 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
55 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
56 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
57 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
58
59 /* Wrapper to execute `code' at most once. */
60 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
61
62 void pic16_genMult8X8_n (operand *, operand *,operand *);
63 extern void pic16_printpBlock(FILE *of, pBlock *pb);
64 static asmop *newAsmop (short type);
65 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
66 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
67 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
68 static pCodeOp *pic16_popRegFromIdx(int rIdx);
69
70 int pic16_labelOffset=0;
71 extern int pic16_debug_verbose;
72
73 extern set *externs;
74
75 /* max_key keeps track of the largest label number used in
76    a function. This is then used to adjust the label offset
77    for the next function.
78 */
79 static int max_key=0;
80 static int GpsuedoStkPtr=0;
81
82 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
83
84 const char *pic16_AopType(short type);
85 static iCode *ifxForOp ( operand *op, iCode *ic );
86
87 void pic16_pushpCodeOp(pCodeOp *pcop);
88 void pic16_poppCodeOp(pCodeOp *pcop);
89
90
91 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
92
93 /* set the following macro to 1 to enable passing the
94  * first byte of functions parameters via WREG */
95 #define USE_WREG_IN_FUNC_PARAMS 0
96
97
98 /* this is the down and dirty file with all kinds of
99    kludgy & hacky stuff. This is what it is all about
100    CODE GENERATION for a specific MCU . some of the
101    routines may be reusable, will have to see */
102 static char *zero = "#0x00";
103 static char *one  = "#0x01";
104
105
106 /*
107  * Function return value policy (MSB-->LSB):
108  *  8 bits      -> WREG
109  * 16 bits      -> PRODL:WREG
110  * 24 bits      -> PRODH:PRODL:WREG
111  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
112  * >32 bits     -> on stack, and FSR0 points to the beginning
113  */
114 char *fReturnpic16[] = { "WREG", "PRODL", "PRODH", "FSR0L" };
115 int fReturnIdx[] = { IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
116 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
117 static char **fReturn = fReturnpic16;
118
119 static char *accUse[] = {"WREG"};
120
121 static struct {
122     short accInUse;
123     short inLine;
124     short debugLine;
125     short nRegsSaved;
126     set *sendSet;
127     set *stackRegSet;
128     int usefastretfie;
129     bitVect *fregsUsed;                 /* registers used in function */
130     bitVect *sregsAlloc;
131     set *sregsAllocSet;                 /* registers used to store stack variables */
132     int stack_lat;                      /* stack offset latency */
133     int resDirect;
134     int useWreg;                        /* flag when WREG is used to pass function parameter */
135 } _G;
136
137 extern struct dbuf_s *codeOutBuf;
138
139 static lineNode *lineHead = NULL;
140 static lineNode *lineCurr = NULL;
141
142 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
143 0xE0, 0xC0, 0x80, 0x00};
144 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
145 0x07, 0x03, 0x01, 0x00};
146
147 static  pBlock *pb;
148
149 /*-----------------------------------------------------------------*/
150 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
151 /*                 exponent of 2 is returned, otherwise -1 is      */
152 /*                 returned.                                       */
153 /* note that this is similar to the function `powof2' in SDCCsymt  */
154 /* if(n == 2^y)                                                    */
155 /*   return y;                                                     */
156 /* return -1;                                                      */
157 /*-----------------------------------------------------------------*/
158 int pic16_my_powof2 (unsigned long num)
159 {
160   if(num) {
161     if( (num & (num-1)) == 0) {
162       int nshifts = -1;
163       while(num) {
164         num>>=1;
165         nshifts++;
166       }
167       return nshifts;
168     }
169   }
170
171   return -1;
172 }
173
174 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
175 {
176   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
177                        line_no,
178                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
179                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
180                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
181                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
182                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
183                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
184                        ((result) ? AOP_SIZE(result) : 0));
185 }
186
187 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
188 {
189
190   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
191                        line_no,
192                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
193                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
194                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
195                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
196                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
197                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
198
199 }
200
201 void pic16_emitpcomment (char *fmt, ...)
202 {
203     va_list ap;
204     char lb[INITIAL_INLINEASM];
205     unsigned char *lbp = (unsigned char *)lb;
206
207     va_start(ap,fmt);
208
209     lb[0] = ';';
210     vsprintf(lb+1,fmt,ap);
211
212     while (isspace(*lbp)) lbp++;
213
214     if (lbp && *lbp)
215         lineCurr = (lineCurr ?
216                     connectLine(lineCurr,newLineNode(lb)) :
217                     (lineHead = newLineNode(lb)));
218     lineCurr->isInline = _G.inLine;
219     lineCurr->isDebug  = _G.debugLine;
220     lineCurr->isComment = 1;
221
222     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
223     va_end(ap);
224
225 //      fprintf(stderr, "%s\n", lb);
226 }
227
228 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
229 {
230     va_list ap;
231     char lb[INITIAL_INLINEASM];
232     unsigned char *lbp = (unsigned char *)lb;
233
234     if(!pic16_debug_verbose)
235       return;
236
237     va_start(ap,fmt);
238
239     if (inst && *inst) {
240         if (fmt && *fmt)
241             sprintf(lb,"%s\t",inst);
242         else
243             sprintf(lb,"%s",inst);
244         vsprintf(lb+(strlen(lb)),fmt,ap);
245     }  else
246         vsprintf(lb,fmt,ap);
247
248     while (isspace(*lbp)) lbp++;
249
250     if (lbp && *lbp)
251         lineCurr = (lineCurr ?
252                     connectLine(lineCurr,newLineNode(lb)) :
253                     (lineHead = newLineNode(lb)));
254     lineCurr->isInline = _G.inLine;
255     lineCurr->isDebug  = _G.debugLine;
256
257     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
258     va_end(ap);
259
260 //      fprintf(stderr, "%s\n", lb);
261 }
262
263
264
265 void pic16_emitpLabel(int key)
266 {
267   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
268 }
269
270 void pic16_emitpLabelFORCE(int key)
271 {
272   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
273 }
274
275 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
276  * NEVER call pic16_emitpcode_real directly, please... */
277 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
278 {
279
280   if(pcop)
281     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
282   else
283     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
284 }
285
286 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
287 {
288   if(pcop)
289     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
290   else
291     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
292 }
293
294 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
295 {
296
297   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
298
299 }
300
301
302 #if 1
303 #define pic16_emitcode  DEBUGpic16_emitcode
304 #else
305 /*-----------------------------------------------------------------*/
306 /* pic16_emitcode - writes the code into a file : for now it is simple    */
307 /*-----------------------------------------------------------------*/
308 void pic16_emitcode (char *inst,char *fmt, ...)
309 {
310     va_list ap;
311     char lb[INITIAL_INLINEASM];
312     unsigned char *lbp = lb;
313
314     va_start(ap,fmt);
315
316     if (inst && *inst) {
317         if (fmt && *fmt)
318             sprintf(lb,"%s\t",inst);
319         else
320             sprintf(lb,"%s",inst);
321         vsprintf(lb+(strlen(lb)),fmt,ap);
322     }  else
323         vsprintf(lb,fmt,ap);
324
325     while (isspace(*lbp)) lbp++;
326
327     if (lbp && *lbp)
328         lineCurr = (lineCurr ?
329                     connectLine(lineCurr,newLineNode(lb)) :
330                     (lineHead = newLineNode(lb)));
331     lineCurr->isInline = _G.inLine;
332     lineCurr->isDebug  = _G.debugLine;
333     lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
334     lineCurr->isComment = (*lbp == ';');
335
336 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
337
338 //    if(pic16_debug_verbose)
339 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
340
341     va_end(ap);
342 }
343 #endif
344
345
346 /*-----------------------------------------------------------------*/
347 /* pic16_emitDebuggerSymbol - associate the current code location  */
348 /*   with a debugger symbol                                        */
349 /*-----------------------------------------------------------------*/
350 void
351 pic16_emitDebuggerSymbol (char * debugSym)
352 {
353   _G.debugLine = 1;
354   pic16_emitcode (";", "%s ==.", debugSym);
355   _G.debugLine = 0;
356 }
357
358 /*-----------------------------------------------------------------*/
359 /* newAsmop - creates a new asmOp                                  */
360 /*-----------------------------------------------------------------*/
361 static asmop *newAsmop (short type)
362 {
363     asmop *aop;
364
365     aop = Safe_calloc(1,sizeof(asmop));
366     aop->type = type;
367     return aop;
368 }
369
370 /*-----------------------------------------------------------------*/
371 /* resolveIfx - converts an iCode ifx into a form more useful for  */
372 /*              generating code                                    */
373 /*-----------------------------------------------------------------*/
374 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
375 {
376   FENTRY2;
377
378 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
379
380   if(!resIfx)
381     return;
382
383
384   resIfx->condition = 1;    /* assume that the ifx is true */
385   resIfx->generated = 0;    /* indicate that the ifx has not been used */
386
387   if(!ifx) {
388     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
389
390 #if 1
391     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
392                         __FUNCTION__,__LINE__,resIfx->lbl->key);
393 #endif
394
395   } else {
396     if(IC_TRUE(ifx)) {
397       resIfx->lbl = IC_TRUE(ifx);
398     } else {
399       resIfx->lbl = IC_FALSE(ifx);
400       resIfx->condition = 0;
401     }
402
403 #if 1
404     if(IC_TRUE(ifx))
405       DEBUGpic16_emitcode("; +++","ifx true is non-null");
406     else
407       DEBUGpic16_emitcode("; +++","ifx true is null");
408     if(IC_FALSE(ifx))
409       DEBUGpic16_emitcode("; +++","ifx false is non-null");
410     else
411       DEBUGpic16_emitcode("; +++","ifx false is null");
412 #endif
413   }
414
415   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
416
417 }
418 #if 0
419 /*-----------------------------------------------------------------*/
420 /* pointerCode - returns the code for a pointer type               */
421 /*-----------------------------------------------------------------*/
422 static int pointerCode (sym_link *etype)
423 {
424
425     return PTR_TYPE(SPEC_OCLS(etype));
426
427 }
428 #endif
429
430 /*-----------------------------------------------------------------*/
431 /* aopForSym - for a true symbol                                   */
432 /*-----------------------------------------------------------------*/
433 static asmop *aopForSym (iCode *ic, operand *op, bool result)
434 {
435     symbol *sym=OP_SYMBOL(op);
436     asmop *aop;
437     memmap *space= SPEC_OCLS(sym->etype);
438
439     FENTRY2;
440
441     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
442
443 //    sym = OP_SYMBOL(op);
444
445     /* if already has one */
446     if (sym->aop) {
447             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
448         return sym->aop;
449     }
450
451 #if 0
452     /* if symbol was initially placed onStack then we must re-place it
453      * to direct memory, since pic16 does not have a specific stack */
454     if(sym->onStack) {
455         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
456     }
457 #endif
458
459
460 #if 0
461     if(sym->iaccess) {
462       if(space->paged) {
463         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
464
465         sym->aop = aop = newAsmop (AOP_PAGED);
466         aop->aopu.aop_dir = sym->rname ;
467         aop->size = getSize(sym->type);
468         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
469         pic16_allocDirReg( IC_LEFT(ic) );
470         return aop;
471       }
472       assert( 0 );
473     }
474 #endif
475
476 #if 1
477     /* assign depending on the storage class */
478     /* if it is on the stack or indirectly addressable */
479     /* space we need to assign either r0 or r1 to it   */
480     if (sym->onStack)   // || sym->iaccess)
481     {
482       pCodeOp *pcop[4];
483       int i;
484
485         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
486                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
487
488         /* acquire a temporary register -- it is saved in function */
489
490         sym->aop = aop = newAsmop(AOP_STA);
491         aop->aopu.stk.stk = sym->stack;
492         aop->size = getSize(sym->type);
493
494
495         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
496         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
497           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
498 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
499
500           for(i=0;i<aop->size;i++)
501             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
502             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
503         } else
504         if(1 && ic->op == SEND) {
505
506           /* if SEND do the send here */
507           _G.resDirect = 1;
508         } else {
509 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
510           for(i=0;i<aop->size;i++) {
511             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
512             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
513           }
514         }
515
516
517 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
518
519 #if 1
520         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
521
522         // we do not need to load the value if it is to be defined...
523         if (result) return aop;
524
525         if(_G.accInUse) {
526                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
527         }
528
529         for(i=0;i<aop->size;i++) {
530
531           /* initialise for stack access via frame pointer */
532           // operands on stack are accessible via "{FRAME POINTER} + index" with index
533           // starting at 2 for arguments and growing from 0 downwards for
534           // local variables (index == 0 is not assigned so we add one here)
535           {
536             int soffs = sym->stack;
537             if (soffs <= 0) {
538               assert (soffs < 0);
539               soffs++;
540             } // if
541
542             if(1 && ic->op == SEND) {
543               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
544               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
545                     pic16_popCopyReg( pic16_frame_plusw ),
546                     pic16_popCopyReg(pic16_stack_postdec )));
547             } else {
548               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
549               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
550                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
551             }
552           }
553         }
554
555         if(_G.accInUse) {
556                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
557         }
558
559         return (aop);
560 #endif
561
562 #if 0
563         /* now assign the address of the variable to
564         the pointer register */
565         if (aop->type != AOP_STK) {
566
567             if (sym->onStack) {
568                     if ( _G.accInUse )
569                         pic16_emitcode("push","acc");
570
571                     pic16_emitcode("mov","a,_bp");
572                     pic16_emitcode("add","a,#0x%02x",
573                              ((sym->stack < 0) ?
574                               ((char)(sym->stack - _G.nRegsSaved )) :
575                               ((char)sym->stack)) & 0xff);
576                     pic16_emitcode("mov","%s,a",
577                              aop->aopu.aop_ptr->name);
578
579                     if ( _G.accInUse )
580                         pic16_emitcode("pop","acc");
581             } else
582                 pic16_emitcode("mov","%s,#%s",
583                          aop->aopu.aop_ptr->name,
584                          sym->rname);
585             aop->paged = space->paged;
586         } else
587             aop->aopu.aop_stk = sym->stack;
588         return aop;
589 #endif
590
591     }
592 #endif
593
594 #if 1
595     /* special case for a function */
596     if (IS_FUNC(sym->type)) {
597         sym->aop = aop = newAsmop(AOP_PCODE);
598         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
599         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
600         PCOI(aop->aopu.pcop)->index = 0;
601         aop->size = FPTRSIZE;
602         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
603         return aop;
604     }
605 #endif
606
607
608
609     //DEBUGpic16_emitcode(";","%d",__LINE__);
610     /* if in bit space */
611     if (IN_BITSPACE(space)) {
612         sym->aop = aop = newAsmop (AOP_CRY);
613         aop->aopu.aop_dir = sym->rname ;
614         aop->size = getSize(sym->type);
615         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
616         return aop;
617     }
618     /* if it is in direct space */
619     if (IN_DIRSPACE(space)) {
620                 if(!strcmp(sym->rname, "_WREG")) {
621                         sym->aop = aop = newAsmop (AOP_ACC);
622                         aop->size = getSize(sym->type);         /* should always be 1 */
623                         assert(aop->size == 1);
624                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
625                         return (aop);
626                 } else {
627                         sym->aop = aop = newAsmop (AOP_DIR);
628                 aop->aopu.aop_dir = sym->rname ;
629             aop->size = getSize(sym->type);
630                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
631                         pic16_allocDirReg( IC_LEFT(ic) );
632                         return (aop);
633                 }
634         }
635
636     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
637         sym->aop = aop = newAsmop (AOP_DIR);
638         aop->aopu.aop_dir = sym->rname ;
639         aop->size = getSize(sym->type);
640         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
641         pic16_allocDirReg( IC_LEFT(ic) );
642         return aop;
643     }
644
645
646     /* only remaining is far space */
647     sym->aop = aop = newAsmop(AOP_PCODE);
648
649 /* change the next if to 1 to revert to good old immediate code */
650         if(IN_CODESPACE(space)) {
651                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
652                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
653                 PCOI(aop->aopu.pcop)->index = 0;
654         } else {
655                 /* try to allocate via direct register */
656                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
657 //              aop->size = getSize( sym->type );
658         }
659
660         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
661                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
662
663 #if 0
664         if(!pic16_allocDirReg (IC_LEFT(ic)))
665                 return NULL;
666 #endif
667
668         if(IN_DIRSPACE( space ))
669                 aop->size = PTRSIZE;
670         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
671                 aop->size = FPTRSIZE;
672         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
673         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
674         else if(sym->onStack) {
675                 aop->size = PTRSIZE;
676         } else {
677           if(SPEC_SCLS(sym->etype) == S_PDATA) {
678             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
679             aop->size = FPTRSIZE;
680           } else
681                 assert( 0 );
682         }
683
684     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
685
686     /* if it is in code space */
687     if (IN_CODESPACE(space))
688         aop->code = 1;
689
690     return aop;
691 }
692
693 /*-----------------------------------------------------------------*/
694 /* aopForRemat - rematerialzes an object                           */
695 /*-----------------------------------------------------------------*/
696 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
697 {
698   symbol *sym = OP_SYMBOL(op);
699   operand *refop;
700   iCode *ic = NULL, *oldic;
701   asmop *aop = newAsmop(AOP_PCODE);
702   int val = 0;
703   int offset = 0;
704   int viaimmd=0;
705
706     FENTRY2;
707
708         ic = sym->rematiCode;
709
710         if(IS_OP_POINTER(op)) {
711                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
712         }
713
714 //    if(!result)               /* fixme-vr */
715         for (;;) {
716                 oldic = ic;
717
718 //              chat *iLine = printILine(ic);
719 //              pic16_emitpcomment("ic: %s\n", iLine);
720 //              dbuf_free(iLine);
721
722                 if (ic->op == '+') {
723                         val += (int) operandLitValue(IC_RIGHT(ic));
724                 } else if (ic->op == '-') {
725                         val -= (int) operandLitValue(IC_RIGHT(ic));
726                 } else
727                         break;
728
729                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
730         }
731
732         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
733         refop = IC_LEFT(ic);
734
735         if(!op->isaddr)viaimmd++; else viaimmd=0;
736
737 /* set the following if to 1 to revert to good old immediate code */
738         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
739                 || viaimmd) {
740
741                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
742
743                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
744
745 #if 0
746                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
747 #else
748                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
749 #endif
750
751                 PCOI(aop->aopu.pcop)->index = val;
752
753                 aop->size = getSize( sym->type );
754         } else {
755                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
756
757                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
758                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
759
760                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
761         }
762
763
764         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
765                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
766 #if 0
767                 val, IS_PTR_CONST(operandType(op)));
768 #else
769                 val, IS_CODEPTR(operandType(op)));
770 #endif
771
772 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
773
774         pic16_allocDirReg (IC_LEFT(ic));
775
776         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
777                 aop->code = 1;
778
779   return aop;
780 }
781
782 #if 0
783 static int aopIdx (asmop *aop, int offset)
784 {
785   if(!aop)
786     return -1;
787
788   if(aop->type !=  AOP_REG)
789     return -2;
790
791   return aop->aopu.aop_reg[offset]->rIdx;
792
793 }
794 #endif
795
796 /*-----------------------------------------------------------------*/
797 /* regsInCommon - two operands have some registers in common       */
798 /*-----------------------------------------------------------------*/
799 static bool regsInCommon (operand *op1, operand *op2)
800 {
801     symbol *sym1, *sym2;
802     int i;
803
804     /* if they have registers in common */
805     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
806         return FALSE ;
807
808     sym1 = OP_SYMBOL(op1);
809     sym2 = OP_SYMBOL(op2);
810
811     if (sym1->nRegs == 0 || sym2->nRegs == 0)
812         return FALSE ;
813
814     for (i = 0 ; i < sym1->nRegs ; i++) {
815         int j;
816         if (!sym1->regs[i])
817             continue ;
818
819         for (j = 0 ; j < sym2->nRegs ;j++ ) {
820             if (!sym2->regs[j])
821                 continue ;
822
823             if (sym2->regs[j] == sym1->regs[i])
824                 return TRUE ;
825         }
826     }
827
828     return FALSE ;
829 }
830
831 /*-----------------------------------------------------------------*/
832 /* operandsEqu - equivalent                                        */
833 /*-----------------------------------------------------------------*/
834 static bool operandsEqu ( operand *op1, operand *op2)
835 {
836     symbol *sym1, *sym2;
837
838     /* if they not symbols */
839     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
840         return FALSE;
841
842     sym1 = OP_SYMBOL(op1);
843     sym2 = OP_SYMBOL(op2);
844
845     /* if both are itemps & one is spilt
846        and the other is not then false */
847     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
848         sym1->isspilt != sym2->isspilt )
849         return FALSE ;
850
851     /* if they are the same */
852     if (sym1 == sym2)
853         return TRUE ;
854
855     if (sym1->rname[0] && sym2->rname[0]
856         && strcmp (sym1->rname, sym2->rname) == 0)
857         return TRUE;
858
859
860     /* if left is a tmp & right is not */
861     if (IS_ITEMP(op1)  &&
862         !IS_ITEMP(op2) &&
863         sym1->isspilt  &&
864         (sym1->usl.spillLoc == sym2))
865         return TRUE;
866
867     if (IS_ITEMP(op2)  &&
868         !IS_ITEMP(op1) &&
869         sym2->isspilt  &&
870         sym1->level > 0 &&
871         (sym2->usl.spillLoc == sym1))
872         return TRUE ;
873
874     return FALSE ;
875 }
876
877 /*-----------------------------------------------------------------*/
878 /* pic16_sameRegs - two asmops have the same registers                   */
879 /*-----------------------------------------------------------------*/
880 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
881 {
882     int i;
883
884     if (aop1 == aop2)
885         return TRUE ;
886
887     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
888                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
889
890     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
891
892     if (aop1->type != AOP_REG ||
893         aop2->type != AOP_REG )
894         return FALSE ;
895
896     /* This is a bit too restrictive if one is a subset of the other...
897     if (aop1->size != aop2->size )
898         return FALSE ;
899     */
900
901     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
902 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
903
904 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
905         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
906             return FALSE ;
907     }
908
909     return TRUE ;
910 }
911
912 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
913 {
914     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
915                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
916
917     if(aop1 == aop2)return TRUE;
918     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
919
920       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
921
922   return TRUE;
923 }
924
925
926 /*-----------------------------------------------------------------*/
927 /* pic16_aopOp - allocates an asmop for an operand  :                    */
928 /*-----------------------------------------------------------------*/
929 void pic16_aopOp (operand *op, iCode *ic, bool result)
930 {
931     asmop *aop;
932     symbol *sym;
933     int i;
934
935     if (!op)
936         return ;
937
938     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
939
940     /* if this a literal */
941     if (IS_OP_LITERAL(op)) {
942         op->aop = aop = newAsmop(AOP_LIT);
943         aop->aopu.aop_lit = op->operand.valOperand;
944         aop->size = getSize(operandType(op));
945         return;
946     }
947
948     {
949       sym_link *type = operandType(op);
950 #if 0
951       if(IS_PTR_CONST(type))
952 #else
953       if(IS_CODEPTR(type))
954 #endif
955         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
956     }
957
958     /* if already has a asmop then continue */
959     if (op->aop)
960         return ;
961
962     /* if the underlying symbol has a aop */
963     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
964       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
965         op->aop = OP_SYMBOL(op)->aop;
966         return;
967     }
968
969     /* if this is a true symbol */
970     if (IS_TRUE_SYMOP(op)) {
971         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
972       op->aop = aopForSym(ic, op, result);
973       return ;
974     }
975
976     /* this is a temporary : this has
977     only four choices :
978     a) register
979     b) spillocation
980     c) rematerialize
981     d) conditional
982     e) can be a return use only */
983
984     sym = OP_SYMBOL(op);
985
986     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
987     /* if the type is a conditional */
988     if (sym->regType == REG_CND) {
989         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
990         aop->size = 0;
991         return;
992     }
993
994     /* if it is spilt then two situations
995     a) is rematerialize
996     b) has a spill location */
997     if (sym->isspilt || sym->nRegs == 0) {
998
999 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1000       DEBUGpic16_emitcode(";","%d",__LINE__);
1001         /* rematerialize it NOW */
1002         if (sym->remat) {
1003
1004             sym->aop = op->aop = aop = aopForRemat (op, result);
1005             return;
1006         }
1007
1008 #if 1
1009         if (sym->accuse) {
1010             int i;
1011             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1012             aop->size = getSize(sym->type);
1013             for ( i = 0 ; i < 1 ; i++ ) {
1014                 aop->aopu.aop_str[i] = accUse[i];
1015 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1016             }
1017             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1018             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1019             return;
1020         }
1021 #endif
1022
1023 #if 1
1024         if (sym->ruonly) {
1025           /*
1026           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1027           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1028           //pic16_allocDirReg (IC_LEFT(ic));
1029           aop->size = getSize(sym->type);
1030           */
1031
1032           unsigned i;
1033
1034           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1035           aop->size = getSize(sym->type);
1036           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1037             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1038
1039           DEBUGpic16_emitcode(";","%d",__LINE__);
1040           return;
1041         }
1042 #endif
1043         /* else spill location  */
1044         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1045             /* force a new aop if sizes differ */
1046             sym->usl.spillLoc->aop = NULL;
1047         }
1048
1049 #if 0
1050         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1051                             __FUNCTION__,__LINE__,
1052                             sym->usl.spillLoc->rname,
1053                             sym->rname, sym->usl.spillLoc->offset);
1054 #endif
1055
1056         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1057         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1058           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1059           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname,
1060                                                   getSize(sym->type),
1061                                                   sym->usl.spillLoc->offset, op);
1062         } else if (getSize(sym->type) <= 1) {
1063           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1064           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1065           assert (getSize(sym->type) <= 1);
1066           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1067           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1068         } else {
1069           /* We need some kind of dummy area for getSize(sym->type) byte,
1070            * use WREG for all storage locations.
1071            * XXX: This only works if we are implementing a `dummy read',
1072            *      the stored value will not be retrievable...
1073            *      See #1503234 for a case requiring this. */
1074           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1075           aop->size = getSize(sym->type);
1076           for ( i = 0 ; i < aop->size ;i++)
1077             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1078         }
1079         aop->size = getSize(sym->type);
1080
1081         return;
1082     }
1083
1084     {
1085       sym_link *type = operandType(op);
1086 #if 0
1087       if(IS_PTR_CONST(type))
1088 #else
1089       if(IS_CODEPTR(type))
1090 #endif
1091         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1092     }
1093
1094     /* must be in a register */
1095     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1096     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1097     aop->size = sym->nRegs;
1098     for ( i = 0 ; i < sym->nRegs ;i++)
1099         aop->aopu.aop_reg[i] = sym->regs[i];
1100 }
1101
1102 /*-----------------------------------------------------------------*/
1103 /* pic16_freeAsmop - free up the asmop given to an operand               */
1104 /*----------------------------------------------------------------*/
1105 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1106 {
1107     asmop *aop ;
1108
1109     if (!op)
1110         aop = aaop;
1111     else
1112         aop = op->aop;
1113
1114     if (!aop)
1115         return ;
1116
1117     if (aop->freed)
1118         goto dealloc;
1119
1120     aop->freed = 1;
1121
1122 #if 1
1123     switch (aop->type) {
1124         case AOP_STA:
1125           {
1126             int i;
1127
1128               /* we must store the result on stack */
1129               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1130                 // operands on stack are accessible via "FSR2 + index" with index
1131                 // starting at 2 for arguments and growing from 0 downwards for
1132                 // local variables (index == 0 is not assigned so we add one here)
1133                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1134                 if (soffs <= 0) {
1135                   assert (soffs < 0);
1136                   soffs++;
1137                 } // if
1138                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1139                 for(i=0;i<aop->size;i++) {
1140                   /* initialise for stack access via frame pointer */
1141                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1142                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1143                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1144                 }
1145
1146                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1147               }
1148
1149               if(!_G.resDirect) {
1150                 for(i=0;i<aop->size;i++) {
1151                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1152
1153                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1154                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1155 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1156                   }
1157                 }
1158
1159                 {
1160                   regs *sr;
1161
1162                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1163                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1164                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1165                       deleteSetItem( &_G.sregsAllocSet, sr );
1166                     }
1167                 }
1168               }
1169               _G.resDirect = 0;
1170           }
1171           break;
1172 #if 0
1173         case AOP_STK :
1174         {
1175             int sz = aop->size;
1176             int stk = aop->aopu.aop_stk + aop->size;
1177             bitVectUnSetBit(ic->rUsed,R0_IDX);
1178             bitVectUnSetBit(ic->rUsed,R1_IDX);
1179
1180             getFreePtr(ic,&aop,FALSE);
1181
1182             if (options.stack10bit)
1183             {
1184                 /* I'm not sure what to do here yet... */
1185                 /* #STUB */
1186                 fprintf(stderr,
1187                         "*** Warning: probably generating bad code for "
1188                         "10 bit stack mode.\n");
1189             }
1190
1191             if (stk) {
1192                 pic16_emitcode ("mov","a,_bp");
1193                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1194                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1195             } else {
1196                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1197             }
1198
1199             while (sz--) {
1200                 pic16_emitcode("pop","acc");
1201                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1202                 if (!sz) break;
1203                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1204             }
1205             op->aop = aop;
1206             pic16_freeAsmop(op,NULL,ic,TRUE);
1207             if (_G.r0Pushed) {
1208                 pic16_emitcode("pop","ar0");
1209                 _G.r0Pushed--;
1210             }
1211
1212             if (_G.r1Pushed) {
1213                 pic16_emitcode("pop","ar1");
1214                 _G.r1Pushed--;
1215             }
1216         }
1217 #endif
1218
1219     }
1220 #endif
1221
1222 dealloc:
1223     /* all other cases just dealloc */
1224     if (op ) {
1225         op->aop = NULL;
1226         if (IS_SYMOP(op)) {
1227             OP_SYMBOL(op)->aop = NULL;
1228             /* if the symbol has a spill */
1229             if (SPIL_LOC(op))
1230                 SPIL_LOC(op)->aop = NULL;
1231         }
1232     }
1233 }
1234
1235 /*-----------------------------------------------------------------*/
1236 /* pic16_aopGet - for fetching value of the aop                          */
1237 /*-----------------------------------------------------------------*/
1238 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1239 {
1240     char *s = buffer ;
1241     char *rs;
1242
1243     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1244
1245     /* offset is greater than size then zero */
1246     if (offset > (aop->size - 1) &&
1247         aop->type != AOP_LIT)
1248         return zero;
1249
1250     /* depending on type */
1251     switch (aop->type) {
1252     case AOP_DIR:
1253       if (offset) {
1254         sprintf(s,"(%s + %d)",
1255                 aop->aopu.aop_dir,
1256                 offset);
1257         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1258       } else
1259             sprintf(s,"%s",aop->aopu.aop_dir);
1260         rs = Safe_calloc(1,strlen(s)+1);
1261         strcpy(rs,s);
1262         return rs;
1263
1264     case AOP_REG:
1265       return aop->aopu.aop_reg[offset]->name;
1266
1267     case AOP_CRY:
1268       return aop->aopu.aop_dir;
1269
1270     case AOP_ACC:
1271         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1272 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1273 //        assert( 0 );
1274 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1275         rs = Safe_strdup("WREG");
1276         return (rs);
1277
1278     case AOP_LIT:
1279         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1280         rs = Safe_calloc(1,strlen(s)+1);
1281         strcpy(rs,s);
1282         return rs;
1283
1284     case AOP_STR:
1285         aop->coff = offset ;
1286
1287 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1288 //          dname)
1289 //          return "acc";
1290         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1291           aop->type = AOP_ACC;
1292           return Safe_strdup("_WREG");
1293         }
1294         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1295
1296         return aop->aopu.aop_str[offset];
1297
1298     case AOP_PCODE:
1299       {
1300         pCodeOp *pcop = aop->aopu.pcop;
1301         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1302         if(pcop->name) {
1303           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1304           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1305           if (offset) {
1306             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1307           } else {
1308             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1309           }
1310         } else
1311           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1312
1313       }
1314       rs = Safe_calloc(1,strlen(s)+1);
1315       strcpy(rs,s);
1316       return rs;
1317
1318 #if 0
1319     case AOP_PAGED:
1320       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1321       if (offset) {
1322         sprintf(s,"(%s + %d)",
1323                 aop->aopu.aop_dir,
1324                 offset);
1325       } else
1326             sprintf(s,"%s",aop->aopu.aop_dir);
1327       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1328       rs = Safe_calloc(1,strlen(s)+1);
1329       strcpy(rs,s);
1330       return rs;
1331 #endif
1332
1333     case AOP_STA:
1334         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1335         return (rs);
1336
1337     case AOP_STK:
1338 //        pCodeOp *pcop = aop->aop
1339         break;
1340
1341     }
1342
1343     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1344     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1345            "aopget got unsupported aop->type");
1346     exit(0);
1347 }
1348
1349
1350
1351 /* lock has the following meaning: When allocating temporary registers
1352  * for stack variables storage, the value of the temporary register is
1353  * saved on stack. Its value is restored at the end. This procedure is
1354  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1355  * a possibility that before a call to pic16_aopOp, a temporary register
1356  * is allocated for a while and it is freed after some time, this will
1357  * mess the stack and values will not be restored properly. So use lock=1
1358  * to allocate temporary registers used internally by the programmer, and
1359  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1360  * to inform the compiler developer about a possible bug. This is an internal
1361  * feature for developing the compiler -- VR */
1362
1363 int _TempReg_lock = 0;
1364 /*-----------------------------------------------------------------*/
1365 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1366 /*-----------------------------------------------------------------*/
1367 pCodeOp *pic16_popGetTempReg(int lock)
1368 {
1369   pCodeOp *pcop=NULL;
1370   symbol *cfunc;
1371
1372 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1373     if(_TempReg_lock) {
1374 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1375     }
1376
1377     _TempReg_lock += lock;
1378
1379     cfunc = currFunc;
1380     currFunc = NULL;
1381
1382     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1383     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1384       PCOR(pcop)->r->wasUsed=1;
1385       PCOR(pcop)->r->isFree=0;
1386
1387       /* push value on stack */
1388       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1389     }
1390
1391     currFunc = cfunc;
1392
1393   return pcop;
1394 }
1395
1396 /*-----------------------------------------------------------------*/
1397 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1398 /*                           is not part of f, but don't save if   */
1399 /*                           inside v                              */
1400 /*-----------------------------------------------------------------*/
1401 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1402 {
1403   pCodeOp *pcop=NULL;
1404   symbol *cfunc;
1405   int i;
1406
1407 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1408
1409     if(_TempReg_lock) {
1410 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1411     }
1412
1413     _TempReg_lock += lock;
1414
1415     cfunc = currFunc;
1416     currFunc = NULL;
1417
1418     i = bitVectFirstBit(f);
1419     while(i < 128) {
1420
1421       /* bypass registers that are used by function */
1422       if(!bitVectBitValue(f, i)) {
1423
1424         /* bypass registers that are already allocated for stack access */
1425         if(!bitVectBitValue(v, i))  {
1426
1427 //          debugf("getting register rIdx = %d\n", i);
1428           /* ok, get the operand */
1429           pcop = pic16_newpCodeOpReg( i );
1430
1431           /* should never by NULL */
1432           assert( pcop != NULL );
1433
1434
1435           /* sanity check */
1436           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1437             int found=0;
1438
1439               PCOR(pcop)->r->wasUsed=1;
1440               PCOR(pcop)->r->isFree=0;
1441
1442
1443               {
1444                 regs *sr;
1445
1446                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1447
1448                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1449                       /* already used in previous steps, break */
1450                       found=1;
1451                       break;
1452                     }
1453                   }
1454               }
1455
1456               /* caller takes care of the following */
1457 //              bitVectSetBit(v, i);
1458
1459               if(!found) {
1460                 /* push value on stack */
1461                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1462                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1463               }
1464
1465             break;
1466           }
1467         }
1468       }
1469       i++;
1470     }
1471
1472     currFunc = cfunc;
1473
1474   return pcop;
1475 }
1476
1477
1478 /*-----------------------------------------------------------------*/
1479 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1480 /*-----------------------------------------------------------------*/
1481 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1482 {
1483   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1484
1485   _TempReg_lock -= lock;
1486
1487   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1488     PCOR(pcop)->r->isFree = 1;
1489
1490     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1491   }
1492 }
1493 /*-----------------------------------------------------------------*/
1494 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1495 /*-----------------------------------------------------------------*/
1496 pCodeOp *pic16_popGetLabel(int key)
1497 {
1498
1499   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1500
1501   if(key>max_key)
1502     max_key = key;
1503
1504   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1505 }
1506
1507 /*-----------------------------------------------------------------*/
1508 /* pic16_popCopyReg - copy a pcode operator                              */
1509 /*-----------------------------------------------------------------*/
1510 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1511 {
1512   pCodeOpReg *pcor;
1513
1514   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1515   memcpy (pcor, pc, sizeof (pCodeOpReg));
1516   pcor->r->wasUsed = 1;
1517
1518   //pcor->pcop.type = pc->pcop.type;
1519   if(pc->pcop.name) {
1520     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1521       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1522   } else
1523     pcor->pcop.name = NULL;
1524
1525   //pcor->r = pc->r;
1526   //pcor->rIdx = pc->rIdx;
1527   //pcor->r->wasUsed=1;
1528   //pcor->instance = pc->instance;
1529
1530 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1531
1532   return PCOP(pcor);
1533 }
1534
1535 /*-----------------------------------------------------------------*/
1536 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1537 /*-----------------------------------------------------------------*/
1538 pCodeOp *pic16_popGetLit(int lit)
1539 {
1540   return pic16_newpCodeOpLit(lit);
1541 }
1542
1543 /* Allow for 12 bit literals (LFSR x, <here!>). */
1544 pCodeOp *pic16_popGetLit12(int lit)
1545 {
1546   return pic16_newpCodeOpLit12(lit);
1547 }
1548
1549 /*-----------------------------------------------------------------*/
1550 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1551 /*-----------------------------------------------------------------*/
1552 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1553 {
1554   return pic16_newpCodeOpLit2(lit, arg2);
1555 }
1556
1557
1558 /*-----------------------------------------------------------------*/
1559 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1560 /*-----------------------------------------------------------------*/
1561 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1562 {
1563   return pic16_newpCodeOpImmd(name, offset,index, 0);
1564 }
1565
1566
1567 /*-----------------------------------------------------------------*/
1568 /* pic16_popGet - asm operator to pcode operator conversion              */
1569 /*-----------------------------------------------------------------*/
1570 pCodeOp *pic16_popGetWithString(char *str)
1571 {
1572   pCodeOp *pcop;
1573
1574
1575   if(!str) {
1576     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1577     exit (1);
1578   }
1579
1580   pcop = pic16_newpCodeOp(str,PO_STR);
1581
1582   return pcop;
1583 }
1584
1585 /*-----------------------------------------------------------------*/
1586 /* pic16_popRegFromString -                                        */
1587 /*-----------------------------------------------------------------*/
1588 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1589 {
1590
1591   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1592   pcop->type = PO_DIR;
1593
1594   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1595   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1596
1597   if(!str)
1598     str = "BAD_STRING";
1599
1600   pcop->name = Safe_calloc(1,strlen(str)+1);
1601   strcpy(pcop->name,str);
1602
1603   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1604
1605   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1606 //  PCOR(pcop)->r->wasUsed = 1;
1607
1608   /* make sure that register doesn't exist,
1609    * and operand isn't NULL
1610    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1611   if((PCOR(pcop)->r == NULL)
1612     && (op)
1613     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1614 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1615 //              __FUNCTION__, __LINE__, str, size, offset);
1616
1617     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1618     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1619
1620   }
1621   PCOR(pcop)->instance = offset;
1622
1623   return pcop;
1624 }
1625
1626 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1627 {
1628   pCodeOp *pcop;
1629
1630 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1631 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1632
1633         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1634         PCOR(pcop)->rIdx = rIdx;
1635         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1636         if(!PCOR(pcop)->r)
1637                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1638
1639         PCOR(pcop)->r->isFree = 0;
1640         PCOR(pcop)->r->wasUsed = 1;
1641
1642         pcop->type = PCOR(pcop)->r->pc_type;
1643
1644   return pcop;
1645 }
1646
1647 /*---------------------------------------------------------------------------------*/
1648 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1649 /*                 VR 030601                                                       */
1650 /*---------------------------------------------------------------------------------*/
1651 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1652 {
1653   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1654         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
1655   return PCOP(pcop2);
1656 }
1657
1658
1659
1660 /*--------------------------------------------------------------------------------.-*/
1661 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1662 /*                  VR 030601 , adapted by Hans Dorn                                */
1663 /*--------------------------------------------------------------------------------.-*/
1664 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1665 {
1666   pCodeOp2 *pcop2;
1667   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
1668   return PCOP(pcop2);
1669 }
1670
1671 /*---------------------------------------------------------------------------------*/
1672 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1673 /*                     movff instruction                                           */
1674 /*---------------------------------------------------------------------------------*/
1675 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1676 {
1677   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1678         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
1679
1680   return PCOP(pcop2);
1681 }
1682
1683
1684 /*-----------------------------------------------------------------*/
1685 /* pic16_popGet - asm operator to pcode operator conversion              */
1686 /*-----------------------------------------------------------------*/
1687 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1688 {
1689 //  char *s = buffer ;
1690 //  char *rs;
1691   pCodeOp *pcop;
1692
1693     FENTRY2;
1694
1695       /* offset is greater than size then zero */
1696
1697 //    if (offset > (aop->size - 1) &&
1698 //        aop->type != AOP_LIT)
1699 //      return NULL;  //zero;
1700
1701     /* depending on type */
1702     switch (aop->type) {
1703                 case AOP_STA:
1704                         /* pCodeOp is already allocated from aopForSym */
1705                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1706                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1707                         return (pcop);
1708
1709                 case AOP_ACC:
1710                         {
1711                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
1712
1713                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1714
1715                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1716
1717                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1718                                 PCOR(pcop)->rIdx = rIdx;
1719                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1720                                 PCOR(pcop)->r->wasUsed=1;
1721                                 PCOR(pcop)->r->isFree=0;
1722
1723                                 PCOR(pcop)->instance = offset;
1724                                 pcop->type = PCOR(pcop)->r->pc_type;
1725 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1726                                 return pcop;
1727
1728
1729 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1730 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1731
1732 //      assert( 0 );
1733                         }
1734
1735     case AOP_DIR:
1736       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
1737       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1738
1739 #if 0
1740     case AOP_PAGED:
1741       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1742       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1743 #endif
1744
1745     case AOP_REG:
1746       {
1747         int rIdx;
1748
1749 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
1750 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
1751         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1752
1753         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1754
1755         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1756 //      pcop->type = PO_GPR_REGISTER;
1757         PCOR(pcop)->rIdx = rIdx;
1758         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1759         PCOR(pcop)->r->wasUsed=1;
1760         PCOR(pcop)->r->isFree=0;
1761
1762         PCOR(pcop)->instance = offset;
1763         pcop->type = PCOR(pcop)->r->pc_type;
1764
1765         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
1766 //      rs = aop->aopu.aop_reg[offset]->name;
1767 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1768         return pcop;
1769       }
1770
1771     case AOP_CRY:
1772         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1773
1774       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1775       PCOR(pcop)->instance = offset;
1776       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1777       //if(PCOR(pcop)->r == NULL)
1778       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1779       return pcop;
1780
1781     case AOP_LIT:
1782         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1783       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1784
1785     case AOP_STR:
1786       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1787       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1788
1789       /*
1790       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1791       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1792       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1793       pcop->type = PCOR(pcop)->r->pc_type;
1794       pcop->name = PCOR(pcop)->r->name;
1795
1796       return pcop;
1797       */
1798
1799     case AOP_PCODE:
1800       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1801                           __LINE__,
1802                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1803       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1804       switch( aop->aopu.pcop->type ) {
1805         case PO_DIR: PCOR(pcop)->instance += offset; break;
1806         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1807         case PO_WREG:
1808             assert (offset==0);
1809             break;
1810         default:
1811           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
1812           assert( 0 );  /* should never reach here */;
1813       }
1814       return pcop;
1815     }
1816
1817     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1818            "pic16_popGet got unsupported aop->type");
1819     exit(0);
1820 }
1821 /*-----------------------------------------------------------------*/
1822 /* pic16_aopPut - puts a string for a aop                                */
1823 /*-----------------------------------------------------------------*/
1824 void pic16_aopPut (asmop *aop, char *s, int offset)
1825 {
1826     char *d = buffer ;
1827     symbol *lbl ;
1828
1829     return;
1830
1831     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1832
1833     if (aop->size && offset > ( aop->size - 1)) {
1834         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1835                "pic16_aopPut got offset > aop->size");
1836         exit(0);
1837     }
1838
1839     /* will assign value to value */
1840     /* depending on where it is ofcourse */
1841     switch (aop->type) {
1842     case AOP_DIR:
1843       if (offset) {
1844         sprintf(d,"(%s + %d)",
1845                 aop->aopu.aop_dir,offset);
1846         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1847
1848       } else
1849             sprintf(d,"%s",aop->aopu.aop_dir);
1850
1851         if (strcmp(d,s)) {
1852           DEBUGpic16_emitcode(";","%d",__LINE__);
1853           if(strcmp(s,"W"))
1854             pic16_emitcode("movf","%s,w",s);
1855           pic16_emitcode("movwf","%s",d);
1856
1857           if(strcmp(s,"W")) {
1858             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1859             if(offset >= aop->size) {
1860               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1861               break;
1862             } else
1863               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1864           }
1865
1866           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1867
1868
1869         }
1870         break;
1871
1872     case AOP_REG:
1873       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1874         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1875           /*
1876             if (*s == '@'           ||
1877                 strcmp(s,"r0") == 0 ||
1878                 strcmp(s,"r1") == 0 ||
1879                 strcmp(s,"r2") == 0 ||
1880                 strcmp(s,"r3") == 0 ||
1881                 strcmp(s,"r4") == 0 ||
1882                 strcmp(s,"r5") == 0 ||
1883                 strcmp(s,"r6") == 0 ||
1884                 strcmp(s,"r7") == 0 )
1885                 pic16_emitcode("mov","%s,%s  ; %d",
1886                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1887             else
1888           */
1889
1890           if(strcmp(s,"W")==0 )
1891             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1892
1893           pic16_emitcode("movwf","%s",
1894                    aop->aopu.aop_reg[offset]->name);
1895
1896           if(strcmp(s,zero)==0) {
1897             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1898
1899           } else if(strcmp(s,"W")==0) {
1900             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1901             pcop->type = PO_GPR_REGISTER;
1902
1903             PCOR(pcop)->rIdx = -1;
1904             PCOR(pcop)->r = NULL;
1905
1906             DEBUGpic16_emitcode(";","%d",__LINE__);
1907             pcop->name = Safe_strdup(s);
1908             pic16_emitpcode(POC_MOVFW,pcop);
1909             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1910           } else if(strcmp(s,one)==0) {
1911             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1912             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1913           } else {
1914             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1915           }
1916         }
1917         break;
1918
1919     case AOP_STK:
1920         if (strcmp(s,"a") == 0)
1921             pic16_emitcode("push","acc");
1922         else
1923             pic16_emitcode("push","%s",s);
1924
1925         break;
1926
1927     case AOP_CRY:
1928         /* if bit variable */
1929         if (!aop->aopu.aop_dir) {
1930             pic16_emitcode("clr","a");
1931             pic16_emitcode("rlc","a");
1932         } else {
1933             if (s == zero)
1934                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1935             else
1936                 if (s == one)
1937                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1938                 else
1939                     if (!strcmp(s,"c"))
1940                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1941                     else {
1942                         lbl = newiTempLabel(NULL);
1943
1944                         if (strcmp(s,"a")) {
1945                             MOVA(s);
1946                         }
1947                         pic16_emitcode("clr","c");
1948                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1949                         pic16_emitcode("cpl","c");
1950                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1951                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1952                     }
1953         }
1954         break;
1955
1956     case AOP_STR:
1957         aop->coff = offset;
1958         if (strcmp(aop->aopu.aop_str[offset],s))
1959             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1960         break;
1961
1962     case AOP_ACC:
1963         aop->coff = offset;
1964         if (!offset && (strcmp(s,"acc") == 0))
1965             break;
1966
1967         if (strcmp(aop->aopu.aop_str[offset],s))
1968             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1969         break;
1970
1971     default :
1972         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
1973 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1974 //             "pic16_aopPut got unsupported aop->type");
1975 //      exit(0);
1976     }
1977
1978 }
1979
1980 /*-----------------------------------------------------------------*/
1981 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
1982 /*-----------------------------------------------------------------*/
1983 void pic16_mov2w (asmop *aop, int offset)
1984 {
1985   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1986
1987   if(pic16_isLitAop(aop))
1988     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1989   else
1990     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1991 }
1992
1993 void pic16_mov2w_volatile (asmop *aop)
1994 {
1995   int i;
1996
1997   if(!pic16_isLitAop(aop)) {
1998     // may need to protect this from the peepholer -- this is not nice but works...
1999     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
2000     for (i = 0; i < aop->size; i++) {
2001       if (i > 0) {
2002         pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - MORE"));
2003       } // if
2004       pic16_emitpcode(POC_MOVFW, pic16_popGet(aop, i));
2005     } // for
2006     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
2007   }
2008 }
2009
2010 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2011 {
2012   if(pic16_isLitAop(src)) {
2013     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2014     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2015   } else {
2016     if(pic16_sameRegsOfs(src, dst, offset))return;
2017     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2018                       pic16_popGet(dst, offset)));
2019   }
2020 }
2021
2022 static void pic16_movLit2f(pCodeOp *pc, int lit)
2023 {
2024   if (0 == (lit & 0x00ff))
2025   {
2026     pic16_emitpcode (POC_CLRF, pc);
2027   } else if (0xff == (lit & 0x00ff))
2028   {
2029     pic16_emitpcode (POC_SETF, pc);
2030   } else {
2031     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2032     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2033   }
2034 }
2035
2036 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2037 {
2038   if(pic16_isLitAop(src)) {
2039     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2040     pic16_emitpcode(POC_MOVWF, dst);
2041   } else {
2042     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2043   }
2044 }
2045
2046 void pic16_testStackOverflow(void)
2047 {
2048 #define GSTACK_TEST_NAME        "_gstack_test"
2049
2050   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2051
2052   {
2053     symbol *sym;
2054
2055       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2056       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2057 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2058       checkAddSym(&externs, sym);
2059   }
2060
2061 }
2062
2063 /* push pcop into stack */
2064 void pic16_pushpCodeOp(pCodeOp *pcop)
2065 {
2066 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2067   if (pcop->type == PO_LITERAL) {
2068     pic16_emitpcode(POC_MOVLW, pcop);
2069     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2070   } else {
2071     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2072   }
2073   if(pic16_options.gstack)
2074     pic16_testStackOverflow();
2075
2076 }
2077
2078 /* pop pcop from stack */
2079 void pic16_poppCodeOp(pCodeOp *pcop)
2080 {
2081   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2082   if(pic16_options.gstack)
2083     pic16_testStackOverflow();
2084 }
2085
2086
2087 /*-----------------------------------------------------------------*/
2088 /* pushw - pushes wreg to stack                                    */
2089 /*-----------------------------------------------------------------*/
2090 void pushw(void)
2091 {
2092   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2093   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2094   if(pic16_options.gstack)
2095     pic16_testStackOverflow();
2096 }
2097
2098
2099 /*-----------------------------------------------------------------*/
2100 /* pushaop - pushes aop to stack                                   */
2101 /*-----------------------------------------------------------------*/
2102 void pushaop(asmop *aop, int offset)
2103 {
2104   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2105
2106   if(_G.resDirect)return;
2107
2108   if(pic16_isLitAop(aop)) {
2109     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2110     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2111   } else {
2112     pic16_emitpcode(POC_MOVFF,
2113       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2114   }
2115
2116   if(pic16_options.gstack)
2117     pic16_testStackOverflow();
2118 }
2119
2120 /*-----------------------------------------------------------------*/
2121 /* popaop - pops aop from stack                                    */
2122 /*-----------------------------------------------------------------*/
2123 void popaop(asmop *aop, int offset)
2124 {
2125   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2126   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2127   if(pic16_options.gstack)
2128     pic16_testStackOverflow();
2129 }
2130
2131 void popaopidx(asmop *aop, int offset, int index)
2132 {
2133   int ofs=1;
2134
2135     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2136
2137     if(STACK_MODEL_LARGE)ofs++;
2138
2139     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2140     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2141     if(pic16_options.gstack)
2142       pic16_testStackOverflow();
2143 }
2144
2145 /*-----------------------------------------------------------------*/
2146 /* pic16_getDataSize - get the operand data size                         */
2147 /*-----------------------------------------------------------------*/
2148 int pic16_getDataSize(operand *op)
2149 {
2150     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2151
2152
2153     return AOP_SIZE(op);
2154
2155     // tsd- in the pic port, the genptr size is 1, so this code here
2156     // fails. ( in the 8051 port, the size was 4).
2157 #if 0
2158     int size;
2159     size = AOP_SIZE(op);
2160     if (size == GPTRSIZE)
2161     {
2162         sym_link *type = operandType(op);
2163         if (IS_GENPTR(type))
2164         {
2165             /* generic pointer; arithmetic operations
2166              * should ignore the high byte (pointer type).
2167              */
2168             size--;
2169     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2170         }
2171     }
2172     return size;
2173 #endif
2174 }
2175
2176 /*-----------------------------------------------------------------*/
2177 /* pic16_outAcc - output Acc                                             */
2178 /*-----------------------------------------------------------------*/
2179 void pic16_outAcc(operand *result)
2180 {
2181   int size,offset;
2182   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2183   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2184
2185
2186   size = pic16_getDataSize(result);
2187   if(size){
2188     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2189     size--;
2190     offset = 1;
2191     /* unsigned or positive */
2192     while(size--)
2193       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2194   }
2195
2196 }
2197
2198 /*-----------------------------------------------------------------*/
2199 /* pic16_outBitC - output a bit C                                  */
2200 /*                 Move to result the value of Carry flag -- VR    */
2201 /*-----------------------------------------------------------------*/
2202 void pic16_outBitC(operand *result)
2203 {
2204   int i;
2205
2206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2207
2208     /* if the result is bit */
2209     if (AOP_TYPE(result) == AOP_CRY) {
2210         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2211         pic16_aopPut(AOP(result),"c",0);
2212     } else {
2213
2214         i = AOP_SIZE(result);
2215         while(i--) {
2216                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2217         }
2218         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2219     }
2220 }
2221
2222 /*-----------------------------------------------------------------*/
2223 /* pic16_outBitOp - output a bit from Op                           */
2224 /*                 Move to result the value of set/clr op -- VR    */
2225 /*-----------------------------------------------------------------*/
2226 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2227 {
2228   int i;
2229
2230     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2231
2232     /* if the result is bit */
2233     if (AOP_TYPE(result) == AOP_CRY) {
2234         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2235         pic16_aopPut(AOP(result),"c",0);
2236     } else {
2237
2238         i = AOP_SIZE(result);
2239         while(i--) {
2240                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2241         }
2242         pic16_emitpcode(POC_RRCF, pcop);
2243         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2244     }
2245 }
2246
2247 /*-----------------------------------------------------------------*/
2248 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2249 /*-----------------------------------------------------------------*/
2250 void pic16_toBoolean(operand *oper)
2251 {
2252     int size = AOP_SIZE(oper) - 1;
2253     int offset = 1;
2254
2255     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2256
2257     if ( AOP_TYPE(oper) != AOP_ACC) {
2258       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2259     }
2260     while (size--) {
2261       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2262     }
2263 }
2264
2265 /*-----------------------------------------------------------------*/
2266 /* genUminusFloat - unary minus for floating points                */
2267 /*-----------------------------------------------------------------*/
2268 static void genUminusFloat(operand *op,operand *result)
2269 {
2270   int size ,offset =0 ;
2271
2272     FENTRY;
2273     /* for this we just need to flip the
2274     first it then copy the rest in place */
2275     size = AOP_SIZE(op);
2276     assert( size == AOP_SIZE(result) );
2277
2278     while(size--) {
2279       pic16_mov2f(AOP(result), AOP(op), offset);
2280       offset++;
2281     }
2282
2283     /* toggle the MSB's highest bit */
2284     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2285 }
2286
2287 /*-----------------------------------------------------------------*/
2288 /* genUminus - unary minus code generation                         */
2289 /*-----------------------------------------------------------------*/
2290 static void genUminus (iCode *ic)
2291 {
2292   int size, i;
2293   sym_link *optype, *rtype;
2294   symbol *label;
2295   int needLabel=0;
2296
2297     FENTRY;
2298
2299     /* assign asmops */
2300     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2301     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2302
2303     /* if both in bit space then special case */
2304     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2305       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2306
2307         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2308         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2309         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2310         goto release;
2311     }
2312
2313     optype = operandType(IC_LEFT(ic));
2314     rtype = operandType(IC_RESULT(ic));
2315
2316
2317     /* if float then do float stuff */
2318     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2319       if(IS_FIXED(optype))
2320         debugf("implement fixed16x16 type\n", 0);
2321
2322         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2323         goto release;
2324     }
2325
2326     /* otherwise subtract from zero by taking the 2's complement */
2327     size = AOP_SIZE(IC_LEFT(ic));
2328     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2329     label = newiTempLabel ( NULL );
2330
2331     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2332       for (i=size-1; i > 0; i--) {
2333         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2334       } // for
2335       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2336       for (i=1; i < size; i++) {
2337         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2338         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2339       } // for
2340     } else {
2341       for (i=size-1; i >= 0; i--) {
2342         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2343         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2344       } // for
2345       if (size > 1) {
2346         for (i=0; i < size-2; i++) {
2347           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2348           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2349         } // for
2350         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2351       } // if
2352       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2353     }
2354     if (needLabel)
2355       pic16_emitpLabel (label->key);
2356
2357 release:
2358     /* release the aops */
2359     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2360     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2361 }
2362
2363 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2364 {
2365   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2366     pic16_emitpcode(POC_MOVFW, src);
2367     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2368   } else {
2369     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2370         src, pic16_popGet(AOP(op), offset)));
2371   }
2372 }
2373
2374
2375 /*-----------------------------------------------------------------*/
2376 /* assignResultValue - assign results to oper, rescall==1 is       */
2377 /*                     called from genCall() or genPcall()         */
2378 /*-----------------------------------------------------------------*/
2379 static void assignResultValue(operand * oper, int res_size, int rescall)
2380 {
2381   int size = AOP_SIZE(oper);
2382   int offset=0;
2383
2384     FENTRY2;
2385 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2386     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2387
2388     if(rescall) {
2389       /* assign result from a call/pcall function() */
2390
2391       /* function results are stored in a special order,
2392        * see top of file with Function return policy, or manual */
2393
2394       if(size <= 4) {
2395         /* 8-bits, result in WREG */
2396         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2397
2398         if(size > 1 && res_size > 1) {
2399           /* 16-bits, result in PRODL:WREG */
2400           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2401         }
2402
2403         if(size > 2 && res_size > 2) {
2404           /* 24-bits, result in PRODH:PRODL:WREG */
2405           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2406         }
2407
2408         if(size > 3 && res_size > 3) {
2409           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2410           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2411         }
2412
2413         pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
2414
2415       } else {
2416         /* >32-bits, result on stack, and FSR0 points to beginning.
2417          * Fix stack when done */
2418         /* FIXME FIXME */
2419 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2420         while (size--) {
2421 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2422 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2423
2424           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2425           GpsuedoStkPtr++;
2426         }
2427
2428         /* fix stack */
2429         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2430         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2431         if(STACK_MODEL_LARGE) {
2432           emitSKPNC;
2433           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2434         }
2435       }
2436     } else {
2437       int areg = 0;             /* matching argument register */
2438
2439 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2440       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2441
2442
2443       /* its called from genReceive (probably) -- VR */
2444       /* I hope this code will not be called from somewhere else in the future!
2445        * We manually set the pseudo stack pointer in genReceive. - dw
2446        */
2447       if(!GpsuedoStkPtr && _G.useWreg) {
2448 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2449
2450         /* The last byte in the assignment is in W */
2451         if(areg <= GpsuedoStkPtr) {
2452           size--;
2453           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2454           offset++;
2455 //          debugf("receive from WREG\n", 0);
2456         }
2457         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2458       }
2459 //      GpsuedoStkPtr++;
2460       _G.stack_lat = AOP_SIZE(oper)-1;
2461
2462       while (size) {
2463         size--;
2464         GpsuedoStkPtr++;
2465         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2466 //        debugf("receive from STACK\n", 0);
2467         offset++;
2468       }
2469     }
2470 }
2471
2472
2473 /*-----------------------------------------------------------------*/
2474 /* genIpush - generate code for pushing this gets a little complex */
2475 /*-----------------------------------------------------------------*/
2476 static void genIpush (iCode *ic)
2477 {
2478 //  int size, offset=0;
2479
2480   FENTRY;
2481   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2482
2483   if(ic->parmPush) {
2484     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2485
2486     /* send to stack as normal */
2487     addSet(&_G.sendSet,ic);
2488 //    addSetHead(&_G.sendSet,ic);
2489     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2490   }
2491
2492
2493 #if 0
2494     int size, offset = 0 ;
2495     char *l;
2496
2497
2498     /* if this is not a parm push : ie. it is spill push
2499     and spill push is always done on the local stack */
2500     if (!ic->parmPush) {
2501
2502         /* and the item is spilt then do nothing */
2503         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2504             return ;
2505
2506         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2507         size = AOP_SIZE(IC_LEFT(ic));
2508         /* push it on the stack */
2509         while(size--) {
2510             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2511             if (*l == '#') {
2512                 MOVA(l);
2513                 l = "acc";
2514             }
2515             pic16_emitcode("push","%s",l);
2516         }
2517         return ;
2518     }
2519
2520     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2521 #endif
2522 }
2523
2524 /*-----------------------------------------------------------------*/
2525 /* genIpop - recover the registers: can happen only for spilling   */
2526 /*-----------------------------------------------------------------*/
2527 static void genIpop (iCode *ic)
2528 {
2529   FENTRY;
2530   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2531 #if 0
2532     int size,offset ;
2533
2534
2535     /* if the temp was not pushed then */
2536     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2537         return ;
2538
2539     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2540     size = AOP_SIZE(IC_LEFT(ic));
2541     offset = (size-1);
2542     while (size--)
2543         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2544                                    FALSE,TRUE));
2545
2546     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2547 #endif
2548 }
2549
2550 static int wparamCmp(void *p1, void *p2)
2551 {
2552   return (!strcmp((char *)p1, (char *)p2));
2553 }
2554
2555 int inWparamList(char *s)
2556 {
2557   return isinSetWith(wparamList, s, wparamCmp);
2558 }
2559
2560
2561 /*-----------------------------------------------------------------*/
2562 /* genCall - generates a call statement                            */
2563 /*-----------------------------------------------------------------*/
2564 static void genCall (iCode *ic)
2565 {
2566   sym_link *ftype;
2567   int stackParms=0;
2568   int use_wreg=0;
2569   int inwparam=0;
2570   char *fname;
2571
2572     FENTRY;
2573
2574     ftype = OP_SYM_TYPE(IC_LEFT(ic));
2575     /* if caller saves & we have not saved then */
2576 //    if (!ic->regsSaved)
2577 //      saveRegisters(ic);
2578
2579         /* initialise stackParms for IPUSH pushes */
2580 //      stackParms = psuedoStkPtr;
2581 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2582     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
2583     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
2584
2585 #if 0
2586     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
2587 #endif
2588
2589     /* if send set is not empty the assign */
2590     if (_G.sendSet) {
2591       iCode *sic;
2592       int psuedoStkPtr=-1;
2593       int firstTimeThruLoop = 1;
2594
2595
2596         /* reverse sendSet if function is not reentrant */
2597         if(!IFFUNC_ISREENT(ftype))
2598           _G.sendSet = reverseSet(_G.sendSet);
2599
2600         /* First figure how many parameters are getting passed */
2601         stackParms = 0;
2602         use_wreg = 0;
2603
2604         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2605           int size;
2606 //          int offset = 0;
2607
2608             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2609             size = AOP_SIZE(IC_LEFT(sic));
2610
2611             stackParms += size;
2612
2613             /* pass the last byte through WREG */
2614             if(inwparam) {
2615
2616               while (size--) {
2617                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2618                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2619                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2620
2621                 if(!firstTimeThruLoop) {
2622                   /* If this is not the first time we've been through the loop
2623                    * then we need to save the parameter in a temporary
2624                    * register. The last byte of the last parameter is
2625                    * passed in W. */
2626
2627                   pushw();
2628 //                  --psuedoStkPtr;             // sanity check
2629                   use_wreg = 1;
2630                 }
2631
2632                 firstTimeThruLoop=0;
2633
2634                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2635
2636 //                offset++;
2637               }
2638             } else {
2639               /* all arguments are passed via stack */
2640               use_wreg = 0;
2641
2642               while (size--) {
2643                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2644                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2645                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2646
2647 //                pushaop(AOP(IC_LEFT(sic)), size);
2648                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
2649
2650                 if(!_G.resDirect)
2651                   pushw();
2652               }
2653             }
2654
2655             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2656           }
2657
2658           if(inwparam) {
2659             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
2660               pushw();  /* save last parameter to stack if functions has varargs */
2661               use_wreg = 0;
2662             } else
2663               use_wreg = 1;
2664           } else use_wreg = 0;
2665
2666           _G.stackRegSet = _G.sendSet;
2667           _G.sendSet = NULL;
2668     }
2669
2670     /* make the call */
2671     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
2672
2673     GpsuedoStkPtr=0;
2674
2675     /* if we need to assign a result value */
2676     if ((IS_ITEMP(IC_RESULT(ic))
2677           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2678               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2679         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2680
2681       _G.accInUse++;
2682       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2683       _G.accInUse--;
2684
2685       /* Must not assign an 8-bit result to a 16-bit variable;
2686        * this would use (used...) the uninitialized PRODL! */
2687       /* FIXME: Need a proper way to obtain size of function result type,
2688        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
2689       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
2690
2691       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2692                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2693
2694       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2695     }
2696
2697     if(!stackParms && ic->parmBytes) {
2698       stackParms = ic->parmBytes;
2699     }
2700
2701     stackParms -= use_wreg;
2702
2703     if(stackParms>0) {
2704       if(stackParms == 1) {
2705         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
2706       } else {
2707         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2708         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2709       }
2710       if(STACK_MODEL_LARGE) {
2711         emitSKPNC;
2712         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
2713       }
2714     }
2715
2716 #if 0
2717     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
2718 #endif
2719
2720     /* adjust the stack for parameters if required */
2721 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2722
2723 #if 0
2724       /* if register bank was saved then pop them */
2725       if (ic->bankSaved)
2726         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2727
2728       /* if we hade saved some registers then unsave them */
2729       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2730         unsaveRegisters (ic);
2731 #endif
2732 }
2733
2734
2735
2736 /*-----------------------------------------------------------------*/
2737 /* genPcall - generates a call by pointer statement                */
2738 /*            new version, created from genCall - HJD              */
2739 /*-----------------------------------------------------------------*/
2740 static void genPcall (iCode *ic)
2741 {
2742   sym_link *fntype;
2743   int stackParms=0;
2744   symbol *retlbl = newiTempLabel(NULL);
2745   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2746
2747     FENTRY;
2748
2749     fntype = operandType( IC_LEFT(ic) )->next;
2750
2751     /* if send set is not empty the assign */
2752     if (_G.sendSet) {
2753       iCode *sic;
2754       int psuedoStkPtr=-1;
2755
2756       /* reverse sendSet if function is not reentrant */
2757       if(!IFFUNC_ISREENT(fntype))
2758         _G.sendSet = reverseSet(_G.sendSet);
2759
2760       stackParms = 0;
2761
2762       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2763         int size;
2764
2765           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2766           size = AOP_SIZE(IC_LEFT(sic));
2767           stackParms += size;
2768
2769           /* all parameters are passed via stack, since WREG is clobbered
2770            * by the calling sequence */
2771           while (size--) {
2772             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2773             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2774             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2775
2776             pic16_mov2w (AOP(IC_LEFT(sic)), size);
2777             pushw();
2778           }
2779
2780           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2781       }
2782
2783       _G.stackRegSet = _G.sendSet;
2784       _G.sendSet = NULL;
2785     }
2786
2787     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2788
2789     // push return address
2790     // push $ on return stack, then replace with retlbl
2791
2792     /* Thanks to Thorsten Klose for pointing out that the following
2793      * snippet should be interrupt safe */
2794     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
2795     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
2796
2797     pic16_emitpcodeNULLop(POC_PUSH);
2798
2799     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2800     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2801     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2802     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2803     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2804     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2805
2806
2807     /* restore interrupt control register */
2808     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
2809     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
2810
2811     /* make the call by writing the pointer into pc */
2812     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
2813     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
2814
2815     // note: MOVFF to PCL not allowed
2816     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
2817     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2818
2819
2820     /* return address is here: (X) */
2821     pic16_emitpLabelFORCE(retlbl->key);
2822
2823     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2824
2825     GpsuedoStkPtr=0;
2826     /* if we need assign a result value */
2827     if ((IS_ITEMP(IC_RESULT(ic))
2828           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2829               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2830         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2831
2832       _G.accInUse++;
2833       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2834       _G.accInUse--;
2835
2836       /* FIXME: Need proper way to obtain the function result's type.
2837        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
2838       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
2839
2840       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2841               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2842
2843       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2844     }
2845
2846 //    stackParms -= use_wreg;
2847
2848     if(stackParms>0) {
2849       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2850       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
2851       if(STACK_MODEL_LARGE) {
2852         emitSKPNC;
2853         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
2854       }
2855     }
2856 }
2857
2858 /*-----------------------------------------------------------------*/
2859 /* resultRemat - result  is rematerializable                       */
2860 /*-----------------------------------------------------------------*/
2861 static int resultRemat (iCode *ic)
2862 {
2863   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2864   if (SKIP_IC(ic) || ic->op == IFX)
2865     return 0;
2866
2867   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2868     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2869     if (sym->remat && !POINTER_SET(ic))
2870       return 1;
2871   }
2872
2873   return 0;
2874 }
2875
2876 #if 0
2877 /*-----------------------------------------------------------------*/
2878 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2879 /*-----------------------------------------------------------------*/
2880 static bool inExcludeList(char *s)
2881 {
2882   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2883     int i =0;
2884
2885     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2886     if (options.excludeRegs[i] &&
2887     STRCASECMP(options.excludeRegs[i],"none") == 0)
2888         return FALSE ;
2889
2890     for ( i = 0 ; options.excludeRegs[i]; i++) {
2891         if (options.excludeRegs[i] &&
2892         STRCASECMP(s,options.excludeRegs[i]) == 0)
2893             return TRUE;
2894     }
2895     return FALSE ;
2896 }
2897 #endif
2898
2899 /*-----------------------------------------------------------------*/
2900 /* genFunction - generated code for function entry                 */
2901 /*-----------------------------------------------------------------*/
2902 static void genFunction (iCode *ic)
2903 {
2904   symbol *sym;
2905   sym_link *ftype;
2906
2907     FENTRY;
2908     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
2909
2910     pic16_labelOffset += (max_key+4);
2911     max_key=0;
2912     GpsuedoStkPtr=0;
2913     _G.nRegsSaved = 0;
2914
2915     ftype = operandType(IC_LEFT(ic));
2916     sym = OP_SYMBOL(IC_LEFT(ic));
2917
2918     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
2919       /* create an absolute section at the interrupt vector:
2920        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
2921       symbol *asym;
2922       char asymname[128];
2923       pBlock *apb;
2924
2925 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
2926
2927         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
2928           sprintf(asymname, "ivec_%s", sym->name);
2929         else
2930           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
2931
2932         /* when an interrupt is declared as naked, do not emit the special
2933          * wrapper segment at vector address. The user should take care for
2934          * this instead. -- VR */
2935
2936         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
2937           asym = newSymbol(asymname, 0);
2938           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
2939           pic16_addpBlock( apb );
2940
2941           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
2942           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
2943           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
2944           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
2945           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
2946
2947           /* mark the end of this tiny function */
2948           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
2949         } else {
2950           sprintf(asymname, "%s", sym->rname);
2951         }
2952
2953         {
2954           absSym *abSym;
2955
2956             abSym = Safe_calloc(1, sizeof(absSym));
2957             strcpy(abSym->name, asymname);
2958
2959             switch( FUNC_INTNO(sym->type) ) {
2960               case 0: abSym->address = 0x000000; break;
2961               case 1: abSym->address = 0x000008; break;
2962               case 2: abSym->address = 0x000018; break;
2963
2964               default:
2965 //                fprintf(stderr, "no interrupt number is given\n");
2966                 abSym->address = -1; break;
2967             }
2968
2969             /* relocate interrupt vectors if needed */
2970             if(abSym->address != -1)
2971               abSym->address += pic16_options.ivt_loc;
2972
2973             addSet(&absSymSet, abSym);
2974         }
2975     }
2976
2977     /* create the function header */
2978     pic16_emitcode(";","-----------------------------------------");
2979     pic16_emitcode(";"," function %s",sym->name);
2980     pic16_emitcode(";","-----------------------------------------");
2981
2982     /* prevent this symbol from being emitted as 'extern' */
2983     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
2984
2985     pic16_emitcode("","%s:",sym->rname);
2986     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2987
2988     {
2989       absSym *ab;
2990
2991         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
2992           if(!strcmp(ab->name, sym->rname)) {
2993             pic16_pBlockConvert2Absolute(pb);
2994             break;
2995           }
2996         }
2997     }
2998
2999     if(IFFUNC_ISNAKED(ftype)) {
3000       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3001       return;
3002     }
3003
3004     /* if critical function then turn interrupts off */
3005     if (IFFUNC_ISCRITICAL(ftype)) {
3006       //pic16_emitcode("clr","ea");
3007     }
3008
3009     currFunc = sym;             /* update the currFunc symbol */
3010     _G.fregsUsed = sym->regsUsed;
3011     _G.sregsAlloc = newBitVect(128);
3012
3013
3014     /* if this is an interrupt service routine then
3015      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3016     if (IFFUNC_ISISR(sym->type)) {
3017         _G.usefastretfie = 1;   /* use shadow registers by default */
3018
3019         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3020         if(!FUNC_ISSHADOWREGS(sym->type)) {
3021           /* do not save WREG,STATUS,BSR for high priority interrupts
3022            * because they are stored in the hardware shadow registers already */
3023           _G.usefastretfie = 0;
3024           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3025           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3026           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3027         }
3028
3029         /* these should really be optimized somehow, because not all
3030          * interrupt handlers modify them */
3031         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3032         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3033         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3034         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3035         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3036         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3037
3038 //        pic16_pBlockConvert2ISR(pb);
3039     }
3040
3041     /* emit code to setup stack frame if user enabled,
3042      * and function is not main() */
3043
3044 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3045     if(strcmp(sym->name, "main")) {
3046       if(0
3047         || !options.ommitFramePtr
3048 //        || sym->regsUsed
3049         || IFFUNC_ARGS(sym->type)
3050         || FUNC_HASSTACKPARM(sym->etype)
3051         ) {
3052         /* setup the stack frame */
3053         if(STACK_MODEL_LARGE)
3054           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3055         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3056
3057         if(STACK_MODEL_LARGE)
3058           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3059         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3060       }
3061     }
3062
3063     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3064           && sym->stack) {
3065
3066       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3067
3068       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3069       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3070       emitSKPC;
3071       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3072     }
3073
3074     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3075       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3076         _G.useWreg = 0;
3077       else
3078         _G.useWreg = 1;
3079     } else
3080       _G.useWreg = 0;
3081
3082     /* if callee-save to be used for this function
3083      * then save the registers being used in this function */
3084 //    if (IFFUNC_CALLEESAVES(sym->type))
3085     if(strcmp(sym->name, "main")) {
3086       int i;
3087
3088         /* if any registers used */
3089         if (sym->regsUsed) {
3090                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3091
3092           if(!pic16_options.xinst) {
3093             /* save the registers used */
3094             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3095             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3096               if (bitVectBitValue(sym->regsUsed,i)) {
3097 #if 0
3098                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3099 #endif
3100                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3101                 _G.nRegsSaved++;
3102
3103                 if(!pic16_regWithIdx(i)->wasUsed) {
3104                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3105                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3106                   pic16_regWithIdx(i)->wasUsed = 1;
3107                 }
3108               }
3109             }
3110           } else {
3111
3112             /* xinst */
3113             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3114             for(i=0;i<sym->regsUsed->size;i++) {
3115               if(bitVectBitValue(sym->regsUsed, i)) {
3116                 _G.nRegsSaved++;
3117               }
3118             }
3119
3120 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3121           }
3122
3123           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3124
3125         }
3126     }
3127
3128     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3129 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3130 }
3131
3132 /*-----------------------------------------------------------------*/
3133 /* genEndFunction - generates epilogue for functions               */
3134 /*-----------------------------------------------------------------*/
3135 static void genEndFunction (iCode *ic)
3136 {
3137   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3138
3139     FENTRY;
3140
3141     if(IFFUNC_ISNAKED(sym->type)) {
3142       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3143       return;
3144     }
3145
3146     _G.stack_lat = 0;
3147
3148     /* add code for ISCRITICAL */
3149     if(IFFUNC_ISCRITICAL(sym->type)) {
3150       /* if critical function, turn on interrupts */
3151
3152       /* TODO: add code here -- VR */
3153     }
3154
3155 //    sym->regsUsed = _G.fregsUsed;
3156
3157     /* now we need to restore the registers */
3158     /* if any registers used */
3159
3160     /* first restore registers that might be used for stack access */
3161     if(_G.sregsAllocSet) {
3162     regs *sr;
3163
3164       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3165       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3166         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3167       }
3168     }
3169
3170     if (strcmp(sym->name, "main") && sym->regsUsed) {
3171       int i;
3172
3173         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3174         /* restore registers used */
3175         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3176         for ( i = sym->regsUsed->size; i >= 0; i--) {
3177           if (bitVectBitValue(sym->regsUsed,i)) {
3178             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3179             _G.nRegsSaved--;
3180           }
3181         }
3182         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3183     }
3184
3185
3186
3187     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3188           && sym->stack) {
3189       if (sym->stack == 1) {
3190         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3191         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3192       } else {
3193         // we have to add more than one...
3194         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3195         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3196         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3197         emitSKPNC;
3198         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3199         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3200         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3201       }
3202     }
3203
3204     if(strcmp(sym->name, "main")) {
3205       if(0
3206         || !options.ommitFramePtr
3207 //        || sym->regsUsed
3208         || IFFUNC_ARGS(sym->type)
3209         || FUNC_HASSTACKPARM(sym->etype)
3210         ) {
3211         /* restore stack frame */
3212         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3213         if(STACK_MODEL_LARGE)
3214           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3215       }
3216     }
3217
3218     _G.useWreg = 0;
3219
3220     if (IFFUNC_ISISR(sym->type)) {
3221       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3222       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3223       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3224       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3225       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3226       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3227
3228       if(!FUNC_ISSHADOWREGS(sym->type)) {
3229         /* do not restore interrupt vector for WREG,STATUS,BSR
3230          * for high priority interrupt, see genFunction */
3231         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3232         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3233         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3234       }
3235 //      _G.interruptvector = 0;         /* sanity check */
3236
3237
3238       /* if debug then send end of function */
3239 /*      if (options.debug && currFunc)  */
3240       if (currFunc) {
3241         debugFile->writeEndFunction (currFunc, ic, 1);
3242       }
3243
3244       if(_G.usefastretfie)
3245         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3246       else
3247         pic16_emitpcodeNULLop(POC_RETFIE);
3248
3249       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3250
3251       _G.usefastretfie = 0;
3252       return;
3253     }
3254
3255     if (IFFUNC_ISCRITICAL(sym->type)) {
3256       pic16_emitcode("setb","ea");
3257     }
3258
3259     /* if debug then send end of function */
3260     if (currFunc) {
3261       debugFile->writeEndFunction (currFunc, ic, 1);
3262     }
3263
3264     /* insert code to restore stack frame, if user enabled it
3265      * and function is not main() */
3266
3267
3268     pic16_emitpcodeNULLop(POC_RETURN);
3269
3270     /* Mark the end of a function */
3271     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3272 }
3273
3274
3275 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3276 {
3277   unsigned long lit=1;
3278   operand *op;
3279
3280     op = IC_LEFT(ic);
3281
3282     // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE)
3283     if(AOP_TYPE(op) == AOP_LIT) {
3284       if(!IS_FLOAT(operandType( op ))) {
3285         lit = ulFromVal (AOP(op)->aopu.aop_lit);
3286       } else {
3287         union {
3288           unsigned long lit_int;
3289           float lit_float;
3290         } info;
3291
3292         /* take care if literal is a float */
3293         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3294         lit = info.lit_int;
3295       }
3296     }
3297
3298     if (AOP_TYPE(op) == AOP_LIT) {
3299       /* FIXME: broken for
3300        *   char __at(0x456) foo;
3301        *   return &foo;
3302        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3303       pic16_movLit2f(dest, (lit >> (8ul*offset)));
3304     } else if (AOP_TYPE(op) == AOP_PCODE
3305                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3306       /* char *s= "aaa"; return s; */
3307       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
3308        *      that the generic pointer is interpreted correctly
3309        *      as referring to __code space, but this is fragile! */
3310       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
3311       /* XXX: should check that dest != WREG */
3312       pic16_emitpcode(POC_MOVWF, dest);
3313     } else {
3314       if(dest->type == PO_WREG && (offset == 0)) {
3315         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3316         return;
3317       }
3318       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3319     }
3320 }
3321
3322 /*-----------------------------------------------------------------*/
3323 /* genRet - generate code for return statement                     */
3324 /*-----------------------------------------------------------------*/
3325 static void genRet (iCode *ic)
3326 {
3327   int size;
3328   operand *left;
3329
3330     FENTRY;
3331         /* if we have no return value then
3332          * just generate the "ret" */
3333
3334         if (!IC_LEFT(ic))
3335                 goto jumpret;
3336
3337         /* we have something to return then
3338          * move the return value into place */
3339         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3340         size = AOP_SIZE(IC_LEFT(ic));
3341
3342         if(size <= 4) {
3343           if(size>3)
3344             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3345
3346           if(size>2)
3347             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3348
3349           if(size>1)
3350             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3351
3352           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3353
3354         } else {
3355                 /* >32-bits, setup stack and FSR0 */
3356                 while (size--) {
3357 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3358 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3359
3360                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3361
3362 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3363                         GpsuedoStkPtr++;
3364                 }
3365
3366                 /* setup FSR0 */
3367                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3368                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3369
3370                 if(STACK_MODEL_LARGE) {
3371                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3372                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3373                 } else {
3374                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3375                 }
3376         }
3377
3378         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3379
3380 jumpret:
3381         /* generate a jump to the return label
3382          * if the next is not the return statement */
3383         if (!(ic->next && ic->next->op == LABEL
3384                 && IC_LABEL(ic->next) == returnLabel)) {
3385
3386                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3387                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3388         }
3389 }
3390
3391 /*-----------------------------------------------------------------*/
3392 /* genLabel - generates a label                                    */
3393 /*-----------------------------------------------------------------*/
3394 static void genLabel (iCode *ic)
3395 {
3396   FENTRY;
3397
3398   /* special case never generate */
3399   if (IC_LABEL(ic) == entryLabel)
3400     return ;
3401
3402   pic16_emitpLabel(IC_LABEL(ic)->key);
3403 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3404 }
3405
3406 /*-----------------------------------------------------------------*/
3407 /* genGoto - generates a goto                                      */
3408 /*-----------------------------------------------------------------*/
3409 //tsd
3410 static void genGoto (iCode *ic)
3411 {
3412   FENTRY;
3413   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3414 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3415 }
3416
3417
3418 /*-----------------------------------------------------------------*/
3419 /* genMultbits :- multiplication of bits                           */
3420 /*-----------------------------------------------------------------*/
3421 static void genMultbits (operand *left,
3422                          operand *right,
3423                          operand *result)
3424 {
3425   FENTRY;
3426
3427   if(!pic16_sameRegs(AOP(result),AOP(right)))
3428     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3429
3430   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3431   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3432   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3433
3434 }
3435
3436
3437 /*-----------------------------------------------------------------*/
3438 /* genMultOneByte : 8 bit multiplication & division                */
3439 /*-----------------------------------------------------------------*/
3440 static void genMultOneByte (operand *left,
3441                             operand *right,
3442                             operand *result)
3443 {
3444
3445   FENTRY;
3446   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3447   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3448
3449   /* (if two literals, the value is computed before) */
3450   /* if one literal, literal on the right */
3451   if (AOP_TYPE(left) == AOP_LIT){
3452     operand *t = right;
3453     right = left;
3454     left = t;
3455   }
3456
3457         /* size is already checked in genMult == 1 */
3458 //      size = AOP_SIZE(result);
3459
3460         if (AOP_TYPE(right) == AOP_LIT){
3461                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3462                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3463                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3464                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3465         } else {
3466                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3467                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3468                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3469                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3470         }
3471
3472         pic16_genMult8X8_n (left, right,result);
3473 }
3474
3475 #if 0
3476 /*-----------------------------------------------------------------*/
3477 /* genMultOneWord : 16 bit multiplication                          */
3478 /*-----------------------------------------------------------------*/
3479 static void genMultOneWord (operand *left,
3480                             operand *right,
3481                             operand *result)
3482 {
3483   FENTRY;
3484   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3485   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3486
3487   /* (if two literals, the value is computed before)
3488    * if one literal, literal on the right */
3489   if (AOP_TYPE(left) == AOP_LIT){
3490     operand *t = right;
3491     right = left;
3492     left = t;
3493   }
3494
3495   /* size is checked already == 2 */
3496 //  size = AOP_SIZE(result);
3497
3498   if (AOP_TYPE(right) == AOP_LIT) {
3499     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3500       pic16_aopGet(AOP(right),0,FALSE,FALSE),
3501       pic16_aopGet(AOP(left),0,FALSE,FALSE),
3502       pic16_aopGet(AOP(result),0,FALSE,FALSE));
3503   } else {
3504     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3505       pic16_aopGet(AOP(right),0,FALSE,FALSE),
3506       pic16_aopGet(AOP(left),0,FALSE,FALSE),
3507       pic16_aopGet(AOP(result),0,FALSE,FALSE));
3508   }
3509
3510   pic16_genMult16X16_16(left, right,result);
3511 }
3512 #endif
3513
3514 #if 0
3515 /*-----------------------------------------------------------------*/
3516 /* genMultOneLong : 32 bit multiplication                          */
3517 /*-----------------------------------------------------------------*/
3518 static void genMultOneLong (operand *left,
3519                             operand *right,
3520                             operand *result)
3521 {
3522   FENTRY;
3523   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3524   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3525
3526   /* (if two literals, the value is computed before)
3527    * if one literal, literal on the right */
3528   if (AOP_TYPE(left) == AOP_LIT){
3529     operand *t = right;
3530     right = left;
3531     left = t;
3532   }
3533
3534   /* size is checked already == 4 */
3535 //  size = AOP_SIZE(result);
3536
3537   if (AOP_TYPE(right) == AOP_LIT) {
3538     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3539         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3540         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3541         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3542   } else {
3543     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3544         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3545         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3546         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3547   }
3548
3549   pic16_genMult32X32_32(left, right,result);
3550 }
3551 #endif
3552
3553
3554
3555 /*-----------------------------------------------------------------*/
3556 /* genMult - generates code for multiplication                     */
3557 /*-----------------------------------------------------------------*/
3558 static void genMult (iCode *ic)
3559 {
3560   operand *left = IC_LEFT(ic);
3561   operand *right = IC_RIGHT(ic);
3562   operand *result= IC_RESULT(ic);
3563
3564     FENTRY;
3565         /* assign the amsops */
3566         pic16_aopOp (left,ic,FALSE);
3567         pic16_aopOp (right,ic,FALSE);
3568         pic16_aopOp (result,ic,TRUE);
3569
3570         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3571
3572         /* special cases first *
3573         * both are bits */
3574         if (AOP_TYPE(left) == AOP_CRY
3575                 && AOP_TYPE(right)== AOP_CRY) {
3576                 genMultbits(left,right,result);
3577           goto release ;
3578         }
3579
3580         /* if both are of size == 1 */
3581         if(AOP_SIZE(left) == 1
3582                 && AOP_SIZE(right) == 1) {
3583                 genMultOneByte(left,right,result);
3584           goto release ;
3585         }
3586
3587 #if 0
3588         /* if both are of size == 2 */
3589         if(AOP_SIZE(left) == 2
3590                 && AOP_SIZE(right) == 2) {
3591                 genMultOneWord(left, right, result);
3592           goto release;
3593         }
3594
3595         /* if both are of size == 4 */
3596         if(AOP_SIZE(left) == 4
3597                 && AOP_SIZE(right) == 4) {
3598                 genMultOneLong(left, right, result);
3599           goto release;
3600         }
3601 #endif
3602
3603         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
3604         assert( !"Multiplication should have been transformed into function call!" );
3605
3606         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3607
3608
3609         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3610         /* should have been converted to function call */
3611         assert(0) ;
3612
3613 release :
3614         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3615         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3616         pic16_freeAsmop(result,NULL,ic,TRUE);
3617 }
3618
3619 #if 0
3620 /*-----------------------------------------------------------------*/
3621 /* genDivbits :- division of bits                                  */
3622 /*-----------------------------------------------------------------*/
3623 static void genDivbits (operand *left,
3624                         operand *right,
3625                         operand *result)
3626 {
3627   char *l;
3628
3629     FENTRY;
3630     /* the result must be bit */
3631     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3632     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3633
3634     MOVA(l);
3635
3636     pic16_emitcode("div","ab");
3637     pic16_emitcode("rrc","a");
3638     pic16_aopPut(AOP(result),"c",0);
3639 }
3640
3641 /*-----------------------------------------------------------------*/
3642 /* genDivOneByte : 8 bit division                                  */
3643 /*-----------------------------------------------------------------*/
3644 static void genDivOneByte (operand *left,
3645                            operand *right,
3646                            operand *result)
3647 {
3648   sym_link *opetype = operandType(result);
3649   char *l ;
3650   symbol *lbl ;
3651   int size,offset;
3652
3653         /* result = divident / divisor
3654          * - divident may be a register or a literal,
3655          * - divisor may be a register or a literal,
3656          * so there are 3 cases (literal / literal is optimized
3657          * by the front-end) to handle.
3658          * In addition we must handle signed and unsigned, which
3659          * result in 6 final different cases -- VR */
3660
3661     FENTRY;
3662
3663     size = AOP_SIZE(result) - 1;
3664     offset = 1;
3665     /* signed or unsigned */
3666     if (SPEC_USIGN(opetype)) {
3667       pCodeOp *pct1,    /* count */
3668                 *pct2,  /* reste */
3669                 *pct3;  /* temp */
3670       symbol *label1, *label2, *label3;;
3671
3672
3673         /* unsigned is easy */
3674
3675         pct1 = pic16_popGetTempReg(1);
3676         pct2 = pic16_popGetTempReg(1);
3677         pct3 = pic16_popGetTempReg(1);
3678
3679         label1 = newiTempLabel(NULL);
3680         label2 = newiTempLabel(NULL);
3681         label3 = newiTempLabel(NULL);
3682
3683         /* the following algorithm is extracted from divuint.c */
3684
3685         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3686         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3687
3688         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3689
3690         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3691
3692         pic16_emitpLabel(label1->key);
3693
3694         emitCLRC;
3695         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
3696
3697
3698         emitCLRC;
3699         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
3700
3701
3702         emitSKPNC;
3703         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
3704
3705         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
3706         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
3707
3708         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
3709         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
3710         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
3711
3712         pic16_emitpLabel( label3->key );
3713         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
3714         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
3715
3716
3717
3718         pic16_emitpLabel(label2->key);
3719         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
3720         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
3721         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
3722
3723         /* result is in wreg */
3724         if(AOP_TYPE(result) != AOP_ACC)
3725                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3726
3727         pic16_popReleaseTempReg( pct3, 1);
3728         pic16_popReleaseTempReg( pct2, 1);
3729         pic16_popReleaseTempReg( pct1, 1);
3730
3731         return ;
3732     }
3733
3734     /* signed is a little bit more difficult */
3735
3736     /* save the signs of the operands */
3737     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3738     MOVA(l);
3739     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3740     pic16_emitcode("push","acc"); /* save it on the stack */
3741
3742     /* now sign adjust for both left & right */
3743     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
3744     MOVA(l);
3745     lbl = newiTempLabel(NULL);
3746     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3747     pic16_emitcode("cpl","a");
3748     pic16_emitcode("inc","a");
3749     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3750     pic16_emitcode("mov","b,a");
3751
3752     /* sign adjust left side */
3753     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
3754     MOVA(l);
3755
3756     lbl = newiTempLabel(NULL);
3757     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3758     pic16_emitcode("cpl","a");
3759     pic16_emitcode("inc","a");
3760     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3761
3762     /* now the division */
3763     pic16_emitcode("div","ab");
3764     /* we are interested in the lower order
3765     only */
3766     pic16_emitcode("mov","b,a");
3767     lbl = newiTempLabel(NULL);
3768     pic16_emitcode("pop","acc");
3769     /* if there was an over flow we don't
3770     adjust the sign of the result */
3771     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3772     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3773     CLRC;
3774     pic16_emitcode("clr","a");
3775     pic16_emitcode("subb","a,b");
3776     pic16_emitcode("mov","b,a");
3777     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3778
3779     /* now we are done */
3780     pic16_aopPut(AOP(result),"b",0);
3781     if(size > 0){
3782         pic16_emitcode("mov","c,b.7");
3783         pic16_emitcode("subb","a,acc");
3784     }
3785     while (size--)
3786         pic16_aopPut(AOP(result),"a",offset++);
3787
3788 }
3789 #endif
3790
3791 /*-----------------------------------------------------------------*/
3792 /* genDiv - generates code for division                            */
3793 /*-----------------------------------------------------------------*/
3794 static void genDiv (iCode *ic)
3795 {
3796     operand *left = IC_LEFT(ic);
3797     operand *right = IC_RIGHT(ic);
3798     operand *result= IC_RESULT(ic);
3799     int negated = 0;
3800     int leftVal = 0, rightVal = 0;
3801     int signedLits = 0;
3802     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
3803     int op = 0;
3804
3805         /* Division is a very lengthy algorithm, so it is better
3806          * to call support routines than inlining algorithm.
3807          * Division functions written here just in case someone
3808          * wants to inline and not use the support libraries -- VR */
3809
3810     FENTRY;
3811
3812     /* assign the amsops */
3813     pic16_aopOp (left,ic,FALSE);
3814     pic16_aopOp (right,ic,FALSE);
3815     pic16_aopOp (result,ic,TRUE);
3816
3817     if (ic->op == '/')
3818       op = 0;
3819     else if (ic->op == '%')
3820       op = 1;
3821     else
3822       assert( !"invalid operation requested in genDivMod" );
3823
3824     /* get literal values */
3825     if (IS_VALOP(left)) {
3826       leftVal = (int) ulFromVal ( OP_VALUE(left) );
3827       assert( leftVal >= -128 && leftVal < 256 );
3828       if (leftVal < 0) { signedLits++; }
3829     }
3830     if (IS_VALOP(right)) {
3831       rightVal = (int) ulFromVal ( OP_VALUE(right) );
3832       assert( rightVal >= -128 && rightVal < 256 );
3833       if (rightVal < 0) { signedLits++; }
3834     }
3835
3836     /* We should only come here to convert all
3837      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
3838      * with exactly one operand being s8_t into
3839      * u8_t x u8_t -> u8_t. All other cases should have been
3840      * turned into calls to support routines beforehand... */
3841     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
3842         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
3843     {
3844       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
3845           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
3846       {
3847         /* Both operands are signed or negative, use _divschar
3848          * instead of _divuchar */
3849         pushaop(AOP(right), 0);
3850         pushaop(AOP(left), 0);
3851
3852         /* call _divschar */
3853         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
3854
3855         {
3856           symbol *sym;
3857           sym = newSymbol( functions[op][0], 0 );
3858           sym->used++;
3859           strcpy(sym->rname, functions[op][0]);
3860           checkAddSym(&externs, sym);
3861         }
3862
3863         /* assign result */
3864         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3865         if (AOP_SIZE(result) > 1)
3866         {
3867           pic16_emitpcode(POC_MOVFF,
3868               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
3869                 pic16_popGet(AOP(result), 1)));
3870           /* sign extend */
3871           pic16_addSign(result, 2, 1);
3872         }
3873
3874         /* clean up stack */
3875         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3876         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3877
3878         goto release;
3879       }
3880
3881       /* push right operand */
3882       if (IS_VALOP(right)) {
3883         if (rightVal < 0) {
3884           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
3885           negated++;
3886         } else {
3887           pushaop(AOP(right), 0);
3888         }
3889       } else if (!IS_UNSIGNED(operandType(right))) {
3890         pic16_mov2w(AOP(right), 0);
3891         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3892         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3893         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3894         negated++;
3895       } else {
3896         pushaop(AOP(right), 0);
3897       }
3898
3899       /* push left operand */
3900       if (IS_VALOP(left)) {
3901         if (leftVal < 0) {
3902           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
3903           negated++;
3904         } else {
3905           pushaop(AOP(left), 0);
3906         }
3907       } else if (!IS_UNSIGNED(operandType(left))) {
3908         pic16_mov2w(AOP(left),0);
3909         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3910         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3911         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3912         negated++;
3913       } else {
3914         pushaop(AOP(left), 0);
3915       }
3916
3917       /* call _divuchar */
3918       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
3919
3920       {
3921         symbol *sym;
3922         sym = newSymbol( functions[op][1], 0 );
3923         sym->used++;
3924         strcpy(sym->rname, functions[op][1]);
3925         checkAddSym(&externs, sym);
3926       }
3927
3928       /* Revert negation(s) from above.
3929        * This is inefficient: if both operands are negative, this
3930        * should not touch WREG. However, determining that exactly
3931        * one operand was negated costs at least 3 instructions,
3932        * so there is nothing to be gained here, is there?
3933        *
3934        * I negate WREG because either operand might share registers with
3935        * result, so assigning first might destroy an operand. */
3936
3937       /* For the modulus operator, (a/b)*b == a shall hold.
3938        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
3939        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
3940        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
3941        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
3942        * Only invert the result if the left operand is negative (sigh).
3943        */
3944       if (AOP_SIZE(result) <= 1 || !negated)
3945       {
3946         if (ic->op == '/')
3947         {
3948           if (IS_VALOP(right)) {
3949             if (rightVal < 0) {
3950               /* we negated this operand above */
3951               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3952             }
3953           } else if (!IS_UNSIGNED(operandType(right))) {
3954             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3955             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3956           }
3957         }
3958
3959         if (IS_VALOP(left)) {
3960           if (leftVal < 0) {
3961             /* we negated this operand above */
3962             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3963           }
3964         } else if (!IS_UNSIGNED(operandType(left))) {
3965           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3966           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3967         }
3968
3969         /* Move result to destination. */
3970         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3971
3972         /* Zero-extend:  no operand was signed (or result is just a byte). */
3973         pic16_addSign(result, 1, 0);
3974       } else {
3975         assert( AOP_SIZE(result) > 1 );
3976         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
3977         if (ic->op == '/')
3978         {
3979           if (IS_VALOP(right)) {
3980             if (rightVal < 0) {
3981               /* we negated this operand above */
3982               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3983             }
3984           } else if (!IS_UNSIGNED(operandType(right))) {
3985             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3986             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3987           }
3988         }
3989
3990         if (IS_VALOP(left)) {
3991           if (leftVal < 0) {
3992             /* we negated this operand above */
3993             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3994           }
3995         } else if (!IS_UNSIGNED(operandType(left))) {
3996           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3997           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
3998         }
3999
4000         /* Move result to destination. */
4001         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4002
4003         /* Negate result if required. */
4004         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4005         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4006
4007         /* Sign-extend. */
4008         pic16_addSign(result, 2, 1);
4009       }
4010
4011       /* clean up stack */
4012       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4013       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4014       goto release;
4015     }
4016
4017 #if 0
4018     /* special cases first */
4019     /* both are bits */
4020     if (AOP_TYPE(left) == AOP_CRY &&
4021         AOP_TYPE(right)== AOP_CRY) {
4022         genDivbits(left,right,result);
4023         goto release ;
4024     }
4025
4026     /* if both are of size == 1 */
4027     if (AOP_SIZE(left) == 1 &&
4028         AOP_SIZE(right) == 1 ) {
4029         genDivOneByte(left,right,result);
4030         goto release ;
4031     }
4032 #endif
4033
4034     /* should have been converted to function call */
4035     assert(0);
4036 release :
4037     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4038     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4039     pic16_freeAsmop(result,NULL,ic,TRUE);
4040 }
4041
4042 #if 0
4043 /*-----------------------------------------------------------------*/
4044 /* genModbits :- modulus of bits                                   */
4045 /*-----------------------------------------------------------------*/
4046 static void genModbits (operand *left,
4047                         operand *right,
4048                         operand *result)
4049 {
4050   char *l;
4051
4052     FENTRY;
4053
4054     werror(W_POSSBUG2, __FILE__, __LINE__);
4055     /* the result must be bit */
4056     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4057     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4058
4059     MOVA(l);
4060
4061     pic16_emitcode("div","ab");
4062     pic16_emitcode("mov","a,b");
4063     pic16_emitcode("rrc","a");
4064     pic16_aopPut(AOP(result),"c",0);
4065 }
4066
4067 /*-----------------------------------------------------------------*/
4068 /* genModOneByte : 8 bit modulus                                   */
4069 /*-----------------------------------------------------------------*/
4070 static void genModOneByte (operand *left,
4071                            operand *right,
4072                            operand *result)
4073 {
4074   sym_link *opetype = operandType(result);
4075   char *l ;
4076   symbol *lbl ;
4077
4078     FENTRY;
4079     werror(W_POSSBUG2, __FILE__, __LINE__);
4080
4081     /* signed or unsigned */
4082     if (SPEC_USIGN(opetype)) {
4083         /* unsigned is easy */
4084         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4085         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4086         MOVA(l);
4087         pic16_emitcode("div","ab");
4088         pic16_aopPut(AOP(result),"b",0);
4089         return ;
4090     }
4091
4092     /* signed is a little bit more difficult */
4093
4094     /* save the signs of the operands */
4095     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4096     MOVA(l);
4097
4098     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4099     pic16_emitcode("push","acc"); /* save it on the stack */
4100
4101     /* now sign adjust for both left & right */
4102     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
4103     MOVA(l);
4104
4105     lbl = newiTempLabel(NULL);
4106     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4107     pic16_emitcode("cpl","a");
4108     pic16_emitcode("inc","a");
4109     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4110     pic16_emitcode("mov","b,a");
4111
4112     /* sign adjust left side */
4113     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
4114     MOVA(l);
4115
4116     lbl = newiTempLabel(NULL);
4117     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4118     pic16_emitcode("cpl","a");
4119     pic16_emitcode("inc","a");
4120     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4121
4122     /* now the multiplication */
4123     pic16_emitcode("div","ab");
4124     /* we are interested in the lower order
4125     only */
4126     lbl = newiTempLabel(NULL);
4127     pic16_emitcode("pop","acc");
4128     /* if there was an over flow we don't
4129     adjust the sign of the result */
4130     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4131     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4132     CLRC ;
4133     pic16_emitcode("clr","a");
4134     pic16_emitcode("subb","a,b");
4135     pic16_emitcode("mov","b,a");
4136     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4137
4138     /* now we are done */
4139     pic16_aopPut(AOP(result),"b",0);
4140
4141 }
4142 #endif
4143
4144 /*-----------------------------------------------------------------*/
4145 /* genMod - generates code for division                            */
4146 /*-----------------------------------------------------------------*/
4147 static void genMod (iCode *ic)
4148 {
4149   /* Task deferred to genDiv */
4150   genDiv(ic);
4151 #if 0
4152   operand *left = IC_LEFT(ic);
4153   operand *right = IC_RIGHT(ic);
4154   operand *result= IC_RESULT(ic);
4155
4156     FENTRY;
4157
4158     /* assign the amsops */
4159     pic16_aopOp (left,ic,FALSE);
4160     pic16_aopOp (right,ic,FALSE);
4161     pic16_aopOp (result,ic,TRUE);
4162
4163     /* special cases first */
4164     /* both are bits */
4165     if (AOP_TYPE(left) == AOP_CRY &&
4166         AOP_TYPE(right)== AOP_CRY) {
4167         genModbits(left,right,result);
4168         goto release ;
4169     }
4170
4171     /* if both are of size == 1 */
4172     if (AOP_SIZE(left) == 1 &&
4173         AOP_SIZE(right) == 1 ) {
4174         genModOneByte(left,right,result);
4175         goto release ;
4176     }
4177
4178     /* should have been converted to function call */
4179     assert(0);
4180
4181 release :
4182     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4183     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4184     pic16_freeAsmop(result,NULL,ic,TRUE);
4185 #endif
4186 }
4187
4188 /*-----------------------------------------------------------------*/
4189 /* genIfxJump :- will create a jump depending on the ifx           */
4190 /*-----------------------------------------------------------------*/
4191 /*
4192   note: May need to add parameter to indicate when a variable is in bit space.
4193 */
4194 static void genIfxJump (iCode *ic, char *jval)
4195 {
4196   FENTRY;
4197
4198     /* if true label then we jump if condition
4199     supplied is true */
4200     if ( IC_TRUE(ic) ) {
4201
4202         if(strcmp(jval,"a") == 0)
4203           emitSKPZ;
4204         else if (strcmp(jval,"c") == 0)
4205           emitSKPNC;
4206         else {
4207           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4208           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4209         }
4210
4211         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4212         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4213
4214     }
4215     else {
4216         /* false label is present */
4217         if(strcmp(jval,"a") == 0)
4218           emitSKPNZ;
4219         else if (strcmp(jval,"c") == 0)
4220           emitSKPC;
4221         else {
4222           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4223           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4224         }
4225
4226         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4227         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4228
4229     }
4230
4231
4232     /* mark the icode as generated */
4233     ic->generated = 1;
4234 }
4235
4236 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4237 {
4238   FENTRY;
4239
4240     /* if true label then we jump if condition
4241     supplied is true */
4242     if ( IC_TRUE(ic) ) {
4243       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4244       pic16_emitpcode(POC_BTFSC, jop);
4245
4246       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4247       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4248
4249     } else {
4250       /* false label is present */
4251       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4252       pic16_emitpcode(POC_BTFSS, jop);
4253
4254       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4255       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4256     }
4257
4258
4259     /* mark the icode as generated */
4260     ic->generated = 1;
4261 }
4262
4263 #if 0
4264 // not needed ATM
4265
4266 /*-----------------------------------------------------------------*/
4267 /* genSkip                                                         */
4268 /*-----------------------------------------------------------------*/
4269 static void genSkip(iCode *ifx,int status_bit)
4270 {
4271   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4272   if(!ifx)
4273     return;
4274
4275   if ( IC_TRUE(ifx) ) {
4276     switch(status_bit) {
4277     case 'z':
4278       emitSKPNZ;
4279       break;
4280
4281     case 'c':
4282       emitSKPNC;
4283       break;
4284
4285     case 'd':
4286       emitSKPDC;
4287       break;
4288
4289     }
4290
4291     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4292     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4293
4294   } else {
4295
4296     switch(status_bit) {
4297
4298     case 'z':
4299       emitSKPZ;
4300       break;
4301
4302     case 'c':
4303       emitSKPC;
4304       break;
4305
4306     case 'd':
4307       emitSKPDC;
4308       break;
4309     }
4310     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4311     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4312
4313   }
4314
4315 }
4316 #endif
4317
4318 /*-----------------------------------------------------------------*/
4319 /* genSkipc                                                        */
4320 /*-----------------------------------------------------------------*/
4321 static void genSkipc(resolvedIfx *rifx)
4322 {
4323   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4324
4325   if(!rifx)
4326     return;
4327
4328   if(rifx->condition)
4329     emitSKPNC;
4330   else
4331     emitSKPC;
4332
4333   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4334   rifx->generated = 1;
4335 }
4336
4337 /*-----------------------------------------------------------------*/
4338 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4339 /*                  aop (if it's NOT a literal) or from lit (if    */
4340 /*                  aop is a literal)                              */
4341 /*-----------------------------------------------------------------*/
4342 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4343   if (aop->type == AOP_LIT) {
4344     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4345   } else {
4346     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4347   }
4348 }
4349
4350 /*-----------------------------------------------------------------*/
4351 /* genCmp :- greater or less than comparison                       */
4352 /*-----------------------------------------------------------------*/
4353
4354 /* genCmp performs a left < right comparison, stores
4355  * the outcome in result (if != NULL) and generates
4356  * control flow code for the ifx (if != NULL).
4357  *
4358  * This version leaves in sequences like
4359  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4360  * which should be optmized by the peephole
4361  * optimizer - RN 2005-01-01 */
4362 static void genCmp (operand *left,operand *right,
4363                     operand *result, iCode *ifx, int sign)
4364 {
4365   resolvedIfx rIfx;
4366   int size;
4367   int offs;
4368   symbol *templbl;
4369   operand *dummy;
4370   unsigned long lit;
4371   unsigned long mask;
4372   int performedLt;
4373
4374   FENTRY;
4375
4376   assert (left && right);
4377   assert (AOP_SIZE(left) == AOP_SIZE(right));
4378
4379   size = AOP_SIZE(right) - 1;
4380   mask = (0x100UL << (size*8)) - 1;
4381   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4382   performedLt = 1;
4383   templbl = NULL;
4384   lit = 0;
4385
4386   resolveIfx (&rIfx, ifx);
4387
4388   /* handle for special cases */
4389   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4390       return;
4391
4392   /**********************************************************************
4393    * handle bits - bit compares are promoted to int compares seemingly! *
4394    **********************************************************************/
4395 #if 0
4396   // THIS IS COMPLETELY UNTESTED!
4397   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4398     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4399     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4400     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4401
4402     emitSETC;
4403     // 1 < {0,1} is false --> clear C by skipping the next instruction
4404     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4405     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4406     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4407     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4408     emitCLRC; // only skipped for left=0 && right=1
4409
4410     goto correct_result_in_carry;
4411   } // if
4412 #endif
4413
4414   /*************************************************
4415    * make sure that left is register (or the like) *
4416    *************************************************/
4417   if (!isAOP_REGlike(left)) {
4418     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4419     assert (isAOP_LIT(left));
4420     assert (isAOP_REGlike(right));
4421     // swap left and right
4422     // left < right <==> right > left <==> (right >= left + 1)
4423     lit = ulFromVal (AOP(left)->aopu.aop_lit);
4424
4425     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4426       // MAXVALUE < right? always false
4427       if (performedLt) emitCLRC; else emitSETC;
4428       goto correct_result_in_carry;
4429     } // if
4430
4431     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4432     // that's why we handled it above.
4433     lit++;
4434
4435     dummy = left;
4436     left = right;
4437     right = dummy;
4438
4439     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4440   } else if (isAOP_LIT(right)) {
4441     lit = ulFromVal (AOP(right)->aopu.aop_lit);
4442   } // if
4443
4444   assert (isAOP_REGlike(left)); // left must be register or the like
4445   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4446
4447   /*************************************************
4448    * special cases go here                         *
4449    *************************************************/
4450
4451   if (isAOP_LIT(right)) {
4452     if (!sign) {
4453       // unsigned comparison to a literal
4454       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4455       if (lit == 0) {
4456         // unsigned left < 0? always false
4457         if (performedLt) emitCLRC; else emitSETC;
4458         goto correct_result_in_carry;
4459       }
4460     } else {
4461       // signed comparison to a literal
4462       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4463       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4464         // signed left < 0x80000000? always false
4465         if (performedLt) emitCLRC; else emitSETC;
4466         goto correct_result_in_carry;
4467       } else if (lit == 0) {
4468         // compare left < 0; set CARRY if SIGNBIT(left) is set
4469         if (performedLt) emitSETC; else emitCLRC;
4470         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4471         if (performedLt) emitCLRC; else emitSETC;
4472         goto correct_result_in_carry;
4473       }
4474     } // if (!sign)
4475   } // right is literal
4476
4477   /*************************************************
4478    * perform a general case comparison             *
4479    * make sure we get CARRY==1 <==> left >= right  *
4480    *************************************************/
4481   // compare most significant bytes
4482   //DEBUGpc ("comparing bytes at offset %d", size);
4483   if (!sign) {
4484     // unsigned comparison
4485     mov2w_regOrLit (AOP(right), lit, size);
4486     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4487   } else {
4488     // signed comparison
4489     // (add 2^n to both operands then perform an unsigned comparison)
4490     if (isAOP_LIT(right)) {
4491       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4492       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4493
4494       if (litbyte == 0x80) {
4495         // left >= 0x80 -- always true, but more bytes to come
4496         pic16_mov2w (AOP(left), size);
4497         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4498         emitSETC;
4499       } else {
4500         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4501         pic16_mov2w (AOP(left), size);
4502         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4503         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4504       } // if
4505     } else {
4506       /* using PRODL as a temporary register here */
4507       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4508       //pCodeOp *pctemp = pic16_popGetTempReg(1);
4509       pic16_mov2w (AOP(left), size);
4510       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4511       pic16_emitpcode (POC_MOVWF, pctemp);
4512       pic16_mov2w (AOP(right), size);
4513       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4514       pic16_emitpcode (POC_SUBFW, pctemp);
4515       //pic16_popReleaseTempReg(pctemp, 1);
4516     }
4517   } // if (!sign)
4518
4519   // compare remaining bytes (treat as unsigned case from above)
4520   templbl = newiTempLabel ( NULL );
4521   offs = size;
4522   while (offs--) {
4523     //DEBUGpc ("comparing bytes at offset %d", offs);
4524     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4525     mov2w_regOrLit (AOP(right), lit, offs);
4526     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4527   } // while (offs)
4528   pic16_emitpLabel (templbl->key);
4529   goto result_in_carry;
4530
4531 result_in_carry:
4532
4533   /****************************************************
4534    * now CARRY contains the result of the comparison: *
4535    * SUBWF sets CARRY iff                             *
4536    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4537    * (F=left, W=right)                                *
4538    ****************************************************/
4539
4540   if (performedLt) {
4541     if (result && AOP_TYPE(result) != AOP_CRY) {
4542       // value will be stored
4543       emitTOGC;
4544     } else {
4545       // value wil only be used in the following genSkipc()
4546       rIfx.condition ^= 1;
4547     }
4548   } // if
4549
4550 correct_result_in_carry:
4551
4552   // assign result to variable (if neccessary)
4553   if (result && AOP_TYPE(result) != AOP_CRY) {
4554     //DEBUGpc ("assign result");
4555     size = AOP_SIZE(result);
4556     while (size--) {
4557       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4558     } // while
4559     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4560   } // if (result)
4561
4562   // perform conditional jump
4563   if (ifx) {
4564     //DEBUGpc ("generate control flow");
4565     genSkipc (&rIfx);
4566     ifx->generated = 1;
4567   } // if
4568 }
4569
4570 /*-----------------------------------------------------------------*/
4571 /* genCmpGt :- greater than comparison                             */
4572 /*-----------------------------------------------------------------*/
4573 static void genCmpGt (iCode *ic, iCode *ifx)
4574 {
4575   operand *left, *right, *result;
4576   sym_link *letype , *retype;
4577   int sign ;
4578
4579     FENTRY;
4580
4581     left = IC_LEFT(ic);
4582     right= IC_RIGHT(ic);
4583     result = IC_RESULT(ic);
4584
4585     letype = getSpec(operandType(left));
4586     retype =getSpec(operandType(right));
4587     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4588     /* assign the amsops */
4589     pic16_aopOp (left,ic,FALSE);
4590     pic16_aopOp (right,ic,FALSE);
4591     pic16_aopOp (result,ic,TRUE);
4592
4593     genCmp(right, left, result, ifx, sign);
4594
4595     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4596     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4597     pic16_freeAsmop(result,NULL,ic,TRUE);
4598 }
4599
4600 /*-----------------------------------------------------------------*/
4601 /* genCmpLt - less than comparisons                                */
4602 /*-----------------------------------------------------------------*/
4603 static void genCmpLt (iCode *ic, iCode *ifx)
4604 {
4605   operand *left, *right, *result;
4606   sym_link *letype , *retype;
4607   int sign ;
4608
4609     FENTRY;
4610
4611     left = IC_LEFT(ic);
4612     right= IC_RIGHT(ic);
4613     result = IC_RESULT(ic);
4614
4615     letype = getSpec(operandType(left));
4616     retype =getSpec(operandType(right));
4617     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4618
4619     /* assign the amsops */
4620     pic16_aopOp (left,ic,FALSE);
4621     pic16_aopOp (right,ic,FALSE);
4622     pic16_aopOp (result,ic,TRUE);
4623
4624     genCmp(left, right, result, ifx, sign);
4625
4626     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4627     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628     pic16_freeAsmop(result,NULL,ic,TRUE);
4629 }
4630
4631 /*-----------------------------------------------------------------*/
4632 /* pic16_isLitOp - check if operand has to be treated as literal   */
4633 /*-----------------------------------------------------------------*/
4634 bool pic16_isLitOp(operand *op)
4635 {
4636   return ((AOP_TYPE(op) == AOP_LIT)
4637       || ( (AOP_TYPE(op) == AOP_PCODE)
4638           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
4639               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
4640 }
4641
4642 /*-----------------------------------------------------------------*/
4643 /* pic16_isLitAop - check if operand has to be treated as literal  */
4644 /*-----------------------------------------------------------------*/
4645 bool pic16_isLitAop(asmop *aop)
4646 {
4647   return ((aop->type == AOP_LIT)
4648       || ( (aop->type == AOP_PCODE)
4649           && ( (aop->aopu.pcop->type == PO_LITERAL)
4650               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
4651 }
4652
4653
4654
4655 /*-----------------------------------------------------------------*/
4656 /* genCmpEq - generates code for equal to                          */
4657 /*-----------------------------------------------------------------*/
4658 static void genCmpEq (iCode *ic, iCode *ifx)
4659 {
4660   operand *left, *right, *result;
4661   symbol *falselbl = newiTempLabel(NULL);
4662   symbol *donelbl = newiTempLabel(NULL);
4663
4664   int preserve_result = 0;
4665   int generate_result = 0;
4666   int i=0;
4667   unsigned long lit = -1;
4668
4669   FENTRY;
4670
4671   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4672   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4673   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4674
4675   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4676
4677   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
4678     {
4679       werror(W_POSSBUG2, __FILE__, __LINE__);
4680       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4681       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
4682       goto release;
4683     }
4684
4685   if (pic16_isLitOp(left) || (AOP_TYPE(right) == AOP_ACC))
4686     {
4687       operand *tmp = right ;
4688       right = left;
4689       left = tmp;
4690     }
4691
4692   if (AOP_TYPE(right) == AOP_LIT) {
4693     lit = ulFromVal (AOP(right)->aopu.aop_lit);
4694   }
4695
4696   if ( regsInCommon(left, result) || regsInCommon(right, result) )
4697     preserve_result = 1;
4698
4699   if(result && AOP_SIZE(result))
4700     generate_result = 1;
4701
4702   if(generate_result && !preserve_result)
4703     {
4704       for(i = 0; i < AOP_SIZE(result); i++)
4705         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4706     }
4707
4708   assert( AOP_SIZE(left) == AOP_SIZE(right) );
4709   for(i=0; i < AOP_SIZE(left); i++)
4710     {
4711       if(AOP_TYPE(left) != AOP_ACC)
4712         {
4713           if(pic16_isLitOp(left))
4714             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
4715           else
4716             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
4717         }
4718       if(pic16_isLitOp(right)) {
4719         if (pic16_isLitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
4720           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
4721         }
4722       } else
4723         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
4724
4725       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
4726     }
4727
4728   // result == true
4729
4730   if(generate_result && preserve_result)
4731     {
4732       for(i = 0; i < AOP_SIZE(result); i++)
4733         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4734     }
4735
4736   if(generate_result)
4737     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
4738
4739   if(generate_result && preserve_result)
4740     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4741
4742   if(ifx && IC_TRUE(ifx))
4743     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4744
4745   if(ifx && IC_FALSE(ifx))
4746     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4747
4748   pic16_emitpLabel(falselbl->key);
4749
4750   // result == false
4751
4752   if(ifx && IC_FALSE(ifx))
4753     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4754
4755   if(generate_result && preserve_result)
4756     {
4757       for(i = 0; i < AOP_SIZE(result); i++)
4758         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4759     }
4760
4761   pic16_emitpLabel(donelbl->key);
4762
4763   if(ifx)
4764     ifx->generated = 1;
4765
4766 release:
4767   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4768   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4769   pic16_freeAsmop(result,NULL,ic,TRUE);
4770
4771 }
4772
4773
4774 #if 0
4775 // old version kept for reference
4776
4777 /*-----------------------------------------------------------------*/
4778 /* genCmpEq - generates code for equal to                          */
4779 /*-----------------------------------------------------------------*/
4780 static void genCmpEq (iCode *ic, iCode *ifx)
4781 {
4782     operand *left, *right, *result;
4783     unsigned long lit = 0L;
4784     int size,offset=0;
4785     symbol *falselbl  = newiTempLabel(NULL);
4786
4787
4788     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4789
4790     if(ifx)
4791       DEBUGpic16_emitcode ("; ifx is non-null","");
4792     else
4793       DEBUGpic16_emitcode ("; ifx is null","");
4794
4795     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4796     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4797     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4798
4799     size = max(AOP_SIZE(left),AOP_SIZE(right));
4800
4801     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4802
4803     /* if literal, literal on the right or
4804     if the right is in a pointer register and left
4805     is not */
4806     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)) {
4807       operand *tmp = right ;
4808       right = left;
4809       left = tmp;
4810     }
4811
4812
4813     if(ifx && !AOP_SIZE(result)){
4814         symbol *tlbl;
4815         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
4816         /* if they are both bit variables */
4817         if (AOP_TYPE(left) == AOP_CRY &&
4818             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4819                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
4820             if(AOP_TYPE(right) == AOP_LIT){
4821                 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4822                 if(lit == 0L){
4823                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4824                     pic16_emitcode("cpl","c");
4825                 } else if(lit == 1L) {
4826                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4827                 } else {
4828                     pic16_emitcode("clr","c");
4829                 }
4830                 /* AOP_TYPE(right) == AOP_CRY */
4831             } else {
4832                 symbol *lbl = newiTempLabel(NULL);
4833                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4834                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4835                 pic16_emitcode("cpl","c");
4836                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4837             }
4838             /* if true label then we jump if condition
4839             supplied is true */
4840             tlbl = newiTempLabel(NULL);
4841             if ( IC_TRUE(ifx) ) {
4842                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4843                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4844             } else {
4845                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4846                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4847             }
4848             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
4849
4850                 {
4851                 /* left and right are both bit variables, result is carry */
4852                         resolvedIfx rIfx;
4853
4854                         resolveIfx(&rIfx,ifx);
4855
4856                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4857                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4858                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4859                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4860                         genSkipz2(&rIfx,0);
4861                 }
4862         } else {
4863
4864                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
4865
4866                         /* They're not both bit variables. Is the right a literal? */
4867                         if(AOP_TYPE(right) == AOP_LIT) {
4868                         lit = ulFromVal (AOP(right)->aopu.aop_lit);
4869
4870                         switch(size) {
4871
4872                                 case 1:
4873                                         switch(lit & 0xff) {
4874                                                 case 1:
4875                                                                 if ( IC_TRUE(ifx) ) {
4876                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4877                                                                         emitSKPNZ;
4878                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4879                                                                 } else {
4880                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4881                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4882                                                                 }
4883                                                                 break;
4884                                                 case 0xff:
4885                                                                 if ( IC_TRUE(ifx) ) {
4886                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4887                                                                         emitSKPNZ;
4888                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4889                                                                 } else {
4890                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4891                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4892                                                                 }
4893                                                                 break;
4894                                                 default:
4895                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4896                                                                 if(lit)
4897                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4898                                                                 genSkip(ifx,'z');
4899                                         } // switch lit
4900
4901
4902                                         /* end of size == 1 */
4903                                         break;
4904
4905                                 case 2:
4906                                         genc16bit2lit(left,lit,offset);
4907                                         genSkip(ifx,'z');
4908                                         break;
4909                                         /* end of size == 2 */
4910
4911                                 default:
4912                                         /* size is 4 */
4913                                         if(lit==0) {
4914                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4915                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4916                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4917                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4918                                                 genSkip(ifx,'z');
4919                                         } else {
4920                                                 /* search for patterns that can be optimized */
4921
4922                                                 genc16bit2lit(left,lit,0);
4923                                                 lit >>= 16;
4924                                                 if(lit) {
4925                                                                 if(IC_TRUE(ifx))
4926                                                                 emitSKPZ; // if hi word unequal
4927                                                                 else
4928                                                                 emitSKPNZ; // if hi word equal
4929                                                                 // fail early
4930                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
4931                                                         genc16bit2lit(left,lit,2);
4932                                                         genSkip(ifx,'z');
4933                                                 } else {
4934                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4935                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4936                                                         genSkip(ifx,'z');
4937                                                 }
4938                                         }
4939                                                 pic16_emitpLabel(falselbl->key);
4940                                                 break;
4941
4942                         } // switch size
4943
4944                         ifx->generated = 1;
4945                         goto release ;
4946
4947
4948           } else if(AOP_TYPE(right) == AOP_CRY ) {
4949             /* we know the left is not a bit, but that the right is */
4950             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4951             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4952                       pic16_popGet(AOP(right),offset));
4953             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4954
4955             /* if the two are equal, then W will be 0 and the Z bit is set
4956              * we could test Z now, or go ahead and check the high order bytes if
4957              * the variable we're comparing is larger than a byte. */
4958
4959             while(--size)
4960               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4961
4962             if ( IC_TRUE(ifx) ) {
4963               emitSKPNZ;
4964               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4965               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4966             } else {
4967               emitSKPZ;
4968               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4969               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4970             }
4971
4972           } else {
4973             /* They're both variables that are larger than bits */
4974             int s = size;
4975
4976             tlbl = newiTempLabel(NULL);
4977
4978             while(size--) {
4979               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4980               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4981
4982               if ( IC_TRUE(ifx) ) {
4983                 if(size) {
4984                   emitSKPZ;
4985
4986                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
4987
4988                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
4989                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
4990                 } else {
4991                   emitSKPNZ;
4992
4993                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
4994
4995
4996                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4997                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4998                 }
4999               } else {
5000                 emitSKPZ;
5001
5002                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5003
5004                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5005                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5006               }
5007               offset++;
5008             }
5009             if(s>1 && IC_TRUE(ifx)) {
5010               pic16_emitpLabel(tlbl->key);
5011               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5012             }
5013           }
5014         }
5015         /* mark the icode as generated */
5016         ifx->generated = 1;
5017         goto release ;
5018     }
5019
5020     /* if they are both bit variables */
5021     if (AOP_TYPE(left) == AOP_CRY &&
5022         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5023         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5024         if(AOP_TYPE(right) == AOP_LIT){
5025             unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
5026             if(lit == 0L){
5027                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5028                 pic16_emitcode("cpl","c");
5029             } else if(lit == 1L) {
5030                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5031             } else {
5032                 pic16_emitcode("clr","c");
5033             }
5034             /* AOP_TYPE(right) == AOP_CRY */
5035         } else {
5036             symbol *lbl = newiTempLabel(NULL);
5037             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5038             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5039             pic16_emitcode("cpl","c");
5040             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5041         }
5042         /* c = 1 if egal */
5043         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5044             pic16_outBitC(result);
5045             goto release ;
5046         }
5047         if (ifx) {
5048             genIfxJump (ifx,"c");
5049             goto release ;
5050         }
5051         /* if the result is used in an arithmetic operation
5052         then put the result in place */
5053         pic16_outBitC(result);
5054     } else {
5055
5056       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5057       gencjne(left,right,result,ifx);
5058 /*
5059       if(ifx)
5060         gencjne(left,right,newiTempLabel(NULL));
5061       else {
5062         if(IC_TRUE(ifx)->key)
5063           gencjne(left,right,IC_TRUE(ifx)->key);
5064         else
5065           gencjne(left,right,IC_FALSE(ifx)->key);
5066         ifx->generated = 1;
5067         goto release ;
5068       }
5069       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5070         pic16_aopPut(AOP(result),"a",0);
5071         goto release ;
5072       }
5073
5074       if (ifx) {
5075         genIfxJump (ifx,"a");
5076         goto release ;
5077       }
5078 */
5079       /* if the result is used in an arithmetic operation
5080          then put the result in place */
5081 /*
5082       if (AOP_TYPE(result) != AOP_CRY)
5083         pic16_outAcc(result);
5084 */
5085       /* leave the result in acc */
5086     }
5087
5088 release:
5089     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5090     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5091     pic16_freeAsmop(result,NULL,ic,TRUE);
5092 }
5093 #endif
5094
5095 /*-----------------------------------------------------------------*/
5096 /* ifxForOp - returns the icode containing the ifx for operand     */
5097 /*-----------------------------------------------------------------*/
5098 static iCode *ifxForOp ( operand *op, iCode *ic )
5099 {
5100   FENTRY2;
5101
5102     /* if true symbol then needs to be assigned */
5103     if (IS_TRUE_SYMOP(op))
5104         return NULL ;
5105
5106     /* if this has register type condition and
5107     the next instruction is ifx with the same operand
5108     and live to of the operand is upto the ifx only then */
5109     if (ic->next
5110         && ic->next->op == IFX
5111         && IC_COND(ic->next)->key == op->key
5112         && OP_SYMBOL(op)->liveTo <= ic->next->seq
5113         ) {
5114                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
5115           return ic->next;
5116     }
5117
5118     /*
5119     if (ic->next &&
5120         ic->next->op == IFX &&
5121         IC_COND(ic->next)->key == op->key) {
5122       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5123       return ic->next;
5124     }
5125     */
5126
5127     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5128     if (ic->next &&
5129         ic->next->op == IFX)
5130       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5131
5132     if (ic->next &&
5133         ic->next->op == IFX &&
5134         IC_COND(ic->next)->key == op->key) {
5135       DEBUGpic16_emitcode ("; "," key is okay");
5136       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5137                            OP_SYMBOL(op)->liveTo,
5138                            ic->next->seq);
5139     }
5140
5141 #if 0
5142     /* the code below is completely untested
5143      * it just allows ulong2fs.c compile -- VR */
5144
5145     ic = ic->next;
5146     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5147                                         __FILE__, __FUNCTION__, __LINE__);
5148
5149     /* if this has register type condition and
5150     the next instruction is ifx with the same operand
5151     and live to of the operand is upto the ifx only then */
5152     if (ic->next &&
5153         ic->next->op == IFX &&
5154         IC_COND(ic->next)->key == op->key &&
5155         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5156         return ic->next;
5157
5158     if (ic->next &&
5159         ic->next->op == IFX &&
5160         IC_COND(ic->next)->key == op->key) {
5161       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5162       return ic->next;
5163     }
5164
5165     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5166                                         __FILE__, __FUNCTION__, __LINE__);
5167
5168 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
5169 #endif
5170
5171     return NULL;
5172 }
5173 /*-----------------------------------------------------------------*/
5174 /* genAndOp - for && operation                                     */
5175 /*-----------------------------------------------------------------*/
5176 static void genAndOp (iCode *ic)
5177 {
5178   operand *left,*right, *result;
5179 /*     symbol *tlbl; */
5180
5181     FENTRY;
5182
5183     /* note here that && operations that are in an
5184     if statement are taken away by backPatchLabels
5185     only those used in arthmetic operations remain */
5186     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5187     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5188     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5189
5190     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5191
5192     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5193     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5194     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5195
5196     /* if both are bit variables */
5197 /*     if (AOP_TYPE(left) == AOP_CRY && */
5198 /*         AOP_TYPE(right) == AOP_CRY ) { */
5199 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5200 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5201 /*         pic16_outBitC(result); */
5202 /*     } else { */
5203 /*         tlbl = newiTempLabel(NULL); */
5204 /*         pic16_toBoolean(left);     */
5205 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5206 /*         pic16_toBoolean(right); */
5207 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5208 /*         pic16_outBitAcc(result); */
5209 /*     } */
5210
5211     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5212     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5213     pic16_freeAsmop(result,NULL,ic,TRUE);
5214 }
5215
5216
5217 /*-----------------------------------------------------------------*/
5218 /* genOrOp - for || operation                                      */
5219 /*-----------------------------------------------------------------*/
5220 /*
5221   tsd pic port -
5222   modified this code, but it doesn't appear to ever get called
5223 */
5224
5225 static void genOrOp (iCode *ic)
5226 {
5227   operand *left,*right, *result;
5228   symbol *tlbl;
5229
5230     FENTRY;
5231
5232   /* note here that || operations that are in an
5233     if statement are taken away by backPatchLabels
5234     only those used in arthmetic operations remain */
5235     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5236     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5237     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5238
5239     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5240
5241     /* if both are bit variables */
5242     if (AOP_TYPE(left) == AOP_CRY &&
5243         AOP_TYPE(right) == AOP_CRY ) {
5244       pic16_emitcode("clrc","");
5245       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5246                AOP(left)->aopu.aop_dir,
5247                AOP(left)->aopu.aop_dir);
5248       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5249                AOP(right)->aopu.aop_dir,
5250                AOP(right)->aopu.aop_dir);
5251       pic16_emitcode("setc","");
5252
5253     } else {
5254         tlbl = newiTempLabel(NULL);
5255         pic16_toBoolean(left);
5256         emitSKPZ;
5257         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
5258         pic16_toBoolean(right);
5259         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5260
5261         pic16_outBitAcc(result);
5262     }
5263
5264     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5265     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5266     pic16_freeAsmop(result,NULL,ic,TRUE);
5267 }
5268
5269 /*-----------------------------------------------------------------*/
5270 /* isLiteralBit - test if lit == 2^n                               */
5271 /*-----------------------------------------------------------------*/
5272 static int isLiteralBit(unsigned long lit)
5273 {
5274     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5275     0x100L,0x200L,0x400L,0x800L,
5276     0x1000L,0x2000L,0x4000L,0x8000L,
5277     0x10000L,0x20000L,0x40000L,0x80000L,
5278     0x100000L,0x200000L,0x400000L,0x800000L,
5279     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5280     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5281     int idx;
5282
5283     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5284     for(idx = 0; idx < 32; idx++)
5285         if(lit == pw[idx])
5286             return idx+1;
5287     return 0;
5288 }
5289
5290 /*-----------------------------------------------------------------*/
5291 /* continueIfTrue -                                                */
5292 /*-----------------------------------------------------------------*/
5293 static void continueIfTrue (iCode *ic)
5294 {
5295   FENTRY;
5296   if(IC_TRUE(ic))
5297     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5298   ic->generated = 1;
5299 }
5300
5301 /*-----------------------------------------------------------------*/
5302 /* jmpIfTrue -                                                     */
5303 /*-----------------------------------------------------------------*/
5304 static void jumpIfTrue (iCode *ic)
5305 {
5306   FENTRY;
5307   if(!IC_TRUE(ic))
5308     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5309   ic->generated = 1;
5310 }
5311
5312 /*-----------------------------------------------------------------*/
5313 /* jmpTrueOrFalse -                                                */
5314 /*-----------------------------------------------------------------*/
5315 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5316 {
5317   // ugly but optimized by peephole
5318   FENTRY;
5319   if(IC_TRUE(ic)){
5320     symbol *nlbl = newiTempLabel(NULL);
5321       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5322       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5323       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5324       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5325   } else {
5326     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5327     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5328   }
5329   ic->generated = 1;
5330 }
5331
5332 /*-----------------------------------------------------------------*/
5333 /* genAnd  - code for and                                          */
5334 /*-----------------------------------------------------------------*/
5335 static void genAnd (iCode *ic, iCode *ifx)
5336 {
5337   operand *left, *right, *result;
5338   int size, offset = 0;
5339   unsigned long lit = 0L;
5340   resolvedIfx rIfx;
5341
5342   FENTRY;
5343
5344   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5345   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5346   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5347
5348   resolveIfx (&rIfx, ifx);
5349
5350   /* if left is a literal & right is not then exchange them */
5351   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5352       AOP_NEEDSACC (left))
5353     {
5354       operand *tmp = right;
5355       right = left;
5356       left = tmp;
5357     }
5358
5359   /* if result = right then exchange them */
5360   if (pic16_sameRegs (AOP (result), AOP (right)))
5361     {
5362       operand *tmp = right;
5363       right = left;
5364       left = tmp;
5365     }
5366
5367   /* if right is bit then exchange them */
5368   if (AOP_TYPE (right) == AOP_CRY &&
5369       AOP_TYPE (left) != AOP_CRY)
5370     {
5371       operand *tmp = right;
5372       right = left;
5373       left = tmp;
5374     }
5375
5376   if (AOP_TYPE (right) == AOP_LIT)
5377     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5378
5379   size = AOP_SIZE (result);
5380
5381   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5382
5383   // if(bit & yy)
5384   // result = bit & yy;
5385   if (AOP_TYPE(left) == AOP_CRY){
5386     // c = bit & literal;
5387     if(AOP_TYPE(right) == AOP_LIT){
5388       if(lit & 1) {
5389         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5390           // no change
5391           goto release;
5392         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5393       } else {
5394         // bit(result) = 0;
5395         if(size && (AOP_TYPE(result) == AOP_CRY)){
5396           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5397           goto release;
5398         }
5399         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5400           jumpIfTrue(ifx);
5401           goto release;
5402         }
5403         pic16_emitcode("clr","c");
5404       }
5405     } else {
5406       if (AOP_TYPE(right) == AOP_CRY){
5407         // c = bit & bit;
5408         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5409         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5410       } else {
5411         // c = bit & val;
5412         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5413         // c = lsb
5414         pic16_emitcode("rrc","a");
5415         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5416       }
5417     }
5418     // bit = c
5419     // val = c
5420     if(size)
5421       pic16_outBitC(result);
5422     // if(bit & ...)
5423     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5424       genIfxJump(ifx, "c");
5425     goto release ;
5426   }
5427
5428   // if (val & 0xZZ)      - size = 0, ifx != FALSE -
5429   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5430   if ((AOP_TYPE (right) == AOP_LIT) &&
5431      (AOP_TYPE (result) == AOP_CRY) &&
5432      (AOP_TYPE (left) != AOP_CRY))
5433     {
5434       symbol *tlbl = newiTempLabel (NULL);
5435       int sizel = AOP_SIZE (left);
5436       int nonnull = 0;
5437       char emitBra;
5438
5439       if (size)
5440         emitSETC;
5441
5442       /* get number of non null bytes in literal */
5443       while (sizel--)
5444         {
5445           if (lit & (0xff << (sizel * 8)))
5446             ++nonnull;
5447         }
5448
5449       emitBra = nonnull || rIfx.condition;
5450
5451       for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
5452         {
5453           unsigned char bytelit = lit;
5454
5455           if (bytelit != 0)
5456             {
5457               int posbit;
5458
5459               --nonnull;
5460
5461               /* patch provided by Aaron Colwell */
5462               if ((posbit = isLiteralBit (bytelit)) != 0)
5463                 {
5464                   if (nonnull)
5465                     {
5466                       pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5467                       pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
5468                     }
5469                   else
5470                     {
5471                       pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5472                     }
5473                 }
5474               else
5475                 {
5476                   if (bytelit == 0xff)
5477                     {
5478                       /* Aaron had a MOVF instruction here, changed to MOVFW cause
5479                        * a peephole could optimize it out -- VR */
5480                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5481                     }
5482                   else
5483                     {
5484                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5485                       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
5486                     }
5487                   if (nonnull)
5488                     {
5489                       if (rIfx.condition)
5490                         {
5491                           emitSKPZ;
5492                           pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5493                         }
5494                       else
5495                         {
5496                           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
5497                         }
5498                     }
5499                   else
5500                     {
5501                       /* last non null byte */
5502                       if (rIfx.condition)
5503                         emitSKPZ;
5504                       else
5505                         emitSKPNZ;
5506                     }
5507                 }
5508             }
5509         }
5510
5511       // bit = left & literal
5512       if (size)
5513         {
5514           emitCLRC;
5515           pic16_emitpLabel (tlbl->key);
5516         }
5517
5518       // if(left & literal)
5519       else
5520         {
5521           if (ifx)
5522             {
5523               if (emitBra)
5524                 pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
5525               ifx->generated = 1;
5526             }
5527           pic16_emitpLabel (tlbl->key);
5528           goto release;
5529         }
5530       pic16_outBitC (result);
5531       goto release;
5532     }
5533
5534   /* if left is same as result */
5535   if(pic16_sameRegs(AOP(result),AOP(left))){
5536     int know_W = -1;
5537     for(;size--; offset++,lit>>=8) {
5538       if(AOP_TYPE(right) == AOP_LIT){
5539         switch(lit & 0xff) {
5540         case 0x00:
5541           /*  and'ing with 0 has clears the result */
5542 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5543           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5544           break;
5545         case 0xff:
5546           /* and'ing with 0xff is a nop when the result and left are the same */
5547           break;
5548
5549         default:
5550           {
5551             int p = pic16_my_powof2( (~lit) & 0xff );
5552             if(p>=0) {
5553               /* only one bit is set in the literal, so use a bcf instruction */
5554 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5555               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5556
5557             } else {
5558               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5559               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5560               if(know_W != (lit&0xff))
5561                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5562               know_W = lit &0xff;
5563               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5564             }
5565           }
5566         }
5567       } else {
5568         if (AOP_TYPE(left) == AOP_ACC) {
5569           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5570         } else {
5571           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5572           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5573
5574         }
5575       }
5576     }
5577
5578   } else {
5579     // left & result in different registers
5580     if(AOP_TYPE(result) == AOP_CRY){
5581       // result = bit
5582       // if(size), result in bit
5583       // if(!size && ifx), conditional oper: if(left & right)
5584       symbol *tlbl = newiTempLabel(NULL);
5585       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5586       if(size)
5587         pic16_emitcode("setb","c");
5588       while(sizer--){
5589         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5590         pic16_emitcode("anl","a,%s",
5591                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5592         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5593         offset++;
5594       }
5595       if(size){
5596         CLRC;
5597         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5598         pic16_outBitC(result);
5599       } else if(ifx)
5600         jmpTrueOrFalse(ifx, tlbl);
5601     } else {
5602       for(;(size--);offset++) {
5603         // normal case
5604         // result = left & right
5605         if(AOP_TYPE(right) == AOP_LIT){
5606           int t = (lit >> (offset*8)) & 0x0FFL;
5607           switch(t) {
5608           case 0x00:
5609             pic16_emitcode("clrf","%s",
5610                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5611             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5612             break;
5613           case 0xff:
5614             pic16_emitcode("movf","%s,w",
5615                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5616             pic16_emitcode("movwf","%s",
5617                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5618             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5619             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5620             break;
5621           default:
5622             pic16_emitcode("movlw","0x%x",t);
5623             pic16_emitcode("andwf","%s,w",
5624                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5625             pic16_emitcode("movwf","%s",
5626                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5627
5628             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5629             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5630             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5631           }
5632           continue;
5633         }
5634
5635         if (AOP_TYPE(left) == AOP_ACC) {
5636           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5637           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5638         } else {
5639           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5640           pic16_emitcode("andwf","%s,w",
5641                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5642           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5643           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5644         }
5645         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5646         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5647       }
5648     }
5649   }
5650
5651 release :
5652   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5653   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5654   pic16_freeAsmop(result,NULL,ic,TRUE);
5655 }
5656
5657 /*-----------------------------------------------------------------*/
5658 /* genOr  - code for or                                            */
5659 /*-----------------------------------------------------------------*/
5660 static void genOr (iCode *ic, iCode *ifx)
5661 {
5662   operand *left, *right, *result;
5663   int size, offset = 0;
5664   unsigned long lit = 0L;
5665   resolvedIfx rIfx;
5666
5667   FENTRY;
5668
5669   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5670   pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
5671   pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
5672
5673   resolveIfx (&rIfx, ifx);
5674
5675   /* if left is a literal & right is not then exchange them */
5676   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5677       AOP_NEEDSACC (left))
5678     {
5679       operand *tmp = right;
5680       right = left;
5681       left = tmp;
5682     }
5683
5684   /* if result = right then exchange them */
5685   if (pic16_sameRegs (AOP (result), AOP (right)))
5686     {
5687       operand *tmp = right;
5688       right = left;
5689       left = tmp;
5690     }
5691
5692   /* if right is bit then exchange them */
5693   if (AOP_TYPE (right) == AOP_CRY &&
5694       AOP_TYPE (left) != AOP_CRY)
5695     {
5696       operand *tmp = right;
5697       right = left;
5698       left = tmp;
5699     }
5700
5701   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5702
5703   if (AOP_TYPE (right) == AOP_LIT)
5704       lit = ulFromVal (AOP (right)->aopu.aop_lit);
5705
5706   size = AOP_SIZE (result);
5707
5708   // if(bit | yy)
5709   // xx = bit | yy;
5710   if (AOP_TYPE(left) == AOP_CRY){
5711       if(AOP_TYPE(right) == AOP_LIT){
5712           // c = bit & literal;
5713           if(lit){
5714               // lit != 0 => result = 1
5715               if(AOP_TYPE(result) == AOP_CRY){
5716                 if(size)
5717                   pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5718                 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5719                 //     AOP(result)->aopu.aop_dir,
5720                 //     AOP(result)->aopu.aop_dir);
5721                   else if(ifx)
5722                       continueIfTrue(ifx);
5723                   goto release;
5724               }
5725           } else {
5726               // lit == 0 => result = left
5727               if(size && pic16_sameRegs(AOP(result),AOP(left)))
5728                   goto release;
5729               pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5730           }
5731       } else {
5732           if (AOP_TYPE(right) == AOP_CRY){
5733             if(pic16_sameRegs(AOP(result),AOP(left))){
5734               // c = bit | bit;
5735               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5736               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5737               pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5738
5739             } else {
5740               if( AOP_TYPE(result) == AOP_ACC) {
5741                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5742                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5743                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5744                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5745
5746               } else {
5747
5748                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5749                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5750                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5751                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5752
5753               }
5754             }
5755           } else {
5756               // c = bit | val;
5757               symbol *tlbl = newiTempLabel(NULL);
5758               pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5759
5760
5761               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5762               if( AOP_TYPE(right) == AOP_ACC) {
5763                 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5764                 emitSKPNZ;
5765                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5766                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5767               }
5768
5769
5770
5771               if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5772                   pic16_emitcode(";XXX setb","c");
5773               pic16_emitcode(";XXX jb","%s,%05d_DS_",
5774                        AOP(left)->aopu.aop_dir,tlbl->key+100);
5775               pic16_toBoolean(right);
5776               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5777               if((AOP_TYPE(result) == AOP_CRY) && ifx){
5778                   jmpTrueOrFalse(ifx, tlbl);
5779                   goto release;
5780               } else {
5781                   CLRC;
5782                   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5783               }
5784           }
5785       }
5786       // bit = c
5787       // val = c
5788       if(size)
5789           pic16_outBitC(result);
5790       // if(bit | ...)
5791       else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5792           genIfxJump(ifx, "c");
5793       goto release ;
5794   }
5795
5796   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5797   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5798   if ((AOP_TYPE (right) == AOP_LIT) &&
5799      (AOP_TYPE (result) == AOP_CRY) &&
5800      (AOP_TYPE (left) != AOP_CRY))
5801     {
5802       if (IS_OP_VOLATILE(left)) {
5803           pic16_mov2w_volatile(AOP(left));
5804       } // if
5805       if (lit)
5806         {
5807           if (rIfx.condition)
5808             pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5809           ifx->generated = 1;
5810         }
5811       else
5812         wassert (0);
5813
5814       goto release;
5815   }
5816
5817   /* if left is same as result */
5818   if(pic16_sameRegs(AOP(result),AOP(left))){
5819     int know_W = -1;
5820     for(;size--; offset++,lit>>=8) {
5821       if(AOP_TYPE(right) == AOP_LIT){
5822         if(((lit & 0xff) == 0) && !IS_OP_VOLATILE(left)) {
5823           /*  or'ing with 0 has no effect */
5824           continue;
5825         } else {
5826           int p = pic16_my_powof2(lit & 0xff);
5827           if(p>=0) {
5828             /* only one bit is set in the literal, so use a bsf instruction */
5829             pic16_emitpcode(POC_BSF,
5830                       pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5831           } else {
5832             if(know_W != (lit & 0xff))
5833               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5834             know_W = lit & 0xff;
5835             pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5836           }
5837
5838         }
5839       } else {
5840         if (AOP_TYPE(left) == AOP_ACC) {
5841           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5842         } else {
5843           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5844           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5845         }
5846       }
5847     }
5848   } else {
5849       // left & result in different registers
5850       if(AOP_TYPE(result) == AOP_CRY){
5851           // result = bit
5852           // if(size), result in bit
5853           // if(!size && ifx), conditional oper: if(left | right)
5854           symbol *tlbl = newiTempLabel(NULL);
5855           int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5856           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5857
5858
5859           if(size)
5860               pic16_emitcode(";XXX setb","c");
5861           while(sizer--){
5862               MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5863               pic16_emitcode(";XXX orl","a,%s",
5864                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5865               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5866               offset++;
5867           }
5868           if(size){
5869               CLRC;
5870               pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5871               pic16_outBitC(result);
5872           } else if(ifx)
5873               jmpTrueOrFalse(ifx, tlbl);
5874       } else for(;(size--);offset++){
5875         // normal case
5876         // result = left & right
5877         if(AOP_TYPE(right) == AOP_LIT){
5878           int t = (lit >> (offset*8)) & 0x0FFL;
5879           switch(t) {
5880           case 0x00:
5881             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
5882             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5883             break;
5884           default:
5885             pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
5886             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5887             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5888           }
5889           continue;
5890         }
5891
5892         // faster than result <- left, anl result,right
5893         // and better if result is SFR
5894         if (AOP_TYPE(left) == AOP_ACC) {
5895           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
5896         } else {
5897           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5898           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5899         }
5900         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5901       }
5902   }
5903
5904 release :
5905   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5906   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5907   pic16_freeAsmop(result,NULL,ic,TRUE);
5908 }
5909
5910 /*-----------------------------------------------------------------*/
5911 /* genXor - code for xclusive or                                   */
5912 /*-----------------------------------------------------------------*/
5913 static void genXor (iCode *ic, iCode *ifx)
5914 {
5915   operand *left, *right, *result;
5916   int size, offset = 0;
5917   unsigned long lit = 0L;
5918   resolvedIfx rIfx;
5919
5920   FENTRY;
5921
5922   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5923   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5924   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5925
5926   resolveIfx (&rIfx,ifx);
5927
5928   /* if left is a literal & right is not ||
5929      if left needs acc & right does not */
5930   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5931       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5932     {
5933       operand *tmp = right;
5934       right = left;
5935       left = tmp;
5936     }
5937
5938   /* if result = right then exchange them */
5939   if (pic16_sameRegs (AOP (result), AOP (right)))
5940     {
5941       operand *tmp = right ;
5942       right = left;
5943       left = tmp;
5944     }
5945
5946   /* if right is bit then exchange them */
5947   if (AOP_TYPE (right) == AOP_CRY &&
5948       AOP_TYPE (left) != AOP_CRY)
5949     {
5950       operand *tmp = right ;
5951       right = left;
5952       left = tmp;
5953     }
5954
5955   if (AOP_TYPE (right) == AOP_LIT)
5956     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5957
5958   size = AOP_SIZE (result);
5959
5960   // if(bit ^ yy)
5961   // xx = bit ^ yy;
5962   if (AOP_TYPE(left) == AOP_CRY)
5963     {
5964       if (AOP_TYPE(right) == AOP_LIT)
5965         {
5966           // c = bit & literal;
5967           if (lit >> 1)
5968             {
5969               // lit>>1  != 0 => result = 1
5970               if (AOP_TYPE(result) == AOP_CRY)
5971                 {
5972                   if (size)
5973                     {
5974                       pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
5975                     }
5976                   else if (ifx)
5977                     continueIfTrue(ifx);
5978                   goto release;
5979                 }
5980               pic16_emitcode("setb", "c");
5981             }
5982           else
5983             {
5984               // lit == (0 or 1)
5985               if (lit == 0)
5986                 {
5987                   // lit == 0, result = left
5988                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
5989                     goto release;
5990                   pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
5991                 }
5992               else
5993                 {
5994                   // lit == 1, result = not(left)
5995                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
5996                     {
5997                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
5998                       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
5999                       pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
6000                       goto release;
6001                     }
6002                   else
6003                     {
6004                       pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6005                       pic16_emitcode("cpl", "c");
6006                     }
6007                 }
6008             }
6009         }
6010       else
6011         {
6012           // right != literal
6013           symbol *tlbl = newiTempLabel(NULL);
6014           if (AOP_TYPE(right) == AOP_CRY)
6015             {
6016               // c = bit ^ bit;
6017               pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
6018             }
6019           else
6020             {
6021               int sizer = AOP_SIZE(right);
6022               // c = bit ^ val
6023               // if val>>1 != 0, result = 1
6024               pic16_emitcode("setb", "c");
6025               while (sizer)
6026                 {
6027                   MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
6028                   if (sizer == 1)
6029                     // test the msb of the lsb
6030                     pic16_emitcode("anl", "a,#0xfe");
6031                   pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
6032                   sizer--;
6033                 }
6034               // val = (0,1)
6035               pic16_emitcode("rrc", "a");
6036             }
6037           pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
6038           pic16_emitcode("cpl", "c");
6039           pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
6040         }
6041       // bit = c
6042       // val = c
6043       if (size)
6044         pic16_outBitC(result);
6045       // if(bit | ...)
6046       else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
6047         genIfxJump(ifx, "c");
6048       goto release;
6049     }
6050
6051   // if(val ^ 0xZZ)       - size = 0, ifx != FALSE  -
6052   // bit = val ^ 0xZZ     - size = 1, ifx = FALSE -
6053   if ((AOP_TYPE (right) == AOP_LIT) &&
6054      (AOP_TYPE (result) == AOP_CRY) &&
6055      (AOP_TYPE (left) != AOP_CRY))
6056     {
6057       symbol *tlbl = newiTempLabel (NULL);
6058       int sizel;
6059
6060       if (size)
6061         emitSETC;
6062
6063       for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
6064         {
6065           unsigned char bytelit = lit;
6066
6067           switch (bytelit)
6068             {
6069             case 0xff:
6070               pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6071               break;
6072
6073             case 0x00:
6074               pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6075               break;
6076
6077             default:
6078               pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
6079               pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6080               break;
6081             }
6082           if (sizel)
6083             {
6084               if (rIfx.condition)
6085                 {
6086                   /* rIfx.lbl might be far away... */
6087                   emitSKPZ;
6088                   pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
6089                 }
6090               else
6091                 {
6092                   pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
6093                 }
6094             }
6095           else
6096             {
6097               /* last non null byte */
6098               if (rIfx.condition)
6099                 emitSKPZ;
6100               else
6101                 emitSKPNZ;
6102             }
6103         }
6104
6105       // bit = left ^ literal
6106       if (size)
6107         {
6108           emitCLRC;
6109           pic16_emitpLabel (tlbl->key);
6110         }
6111       // if (left ^ literal)
6112       else
6113         {
6114           if (ifx)
6115             {
6116               pic16_emitpcode (POC_BRA, pic16_popGetLabel (rIfx.lbl->key));
6117               ifx->generated = 1;
6118             }
6119           pic16_emitpLabel (tlbl->key);
6120           goto release;
6121         }
6122
6123       pic16_outBitC (result);
6124       goto release;
6125   }
6126
6127   if (pic16_sameRegs(AOP(result), AOP(left)))
6128     {
6129       /* if left is same as result */
6130       for (; size--; offset++)
6131         {
6132           if (AOP_TYPE(right) == AOP_LIT)
6133             {
6134               int t  = (lit >> (offset * 8)) & 0x0FFL;
6135               if  (t == 0x00L)
6136                 continue;
6137               else
6138                 {
6139                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6140                   pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6141                 }
6142             }
6143           else
6144             {
6145               if (AOP_TYPE(left) == AOP_ACC)
6146                 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6147               else
6148                 {
6149                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6150                   pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6151                 }
6152             }
6153         }
6154     }
6155   else
6156     {
6157     // left ^ result in different registers
6158     if (AOP_TYPE(result) == AOP_CRY)
6159       {
6160         // result = bit
6161         // if(size), result in bit
6162         // if(!size && ifx), conditional oper: if(left ^ right)
6163         symbol *tlbl = newiTempLabel(NULL);
6164         int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
6165         if (size)
6166           pic16_emitcode("setb", "c");
6167         while (sizer--)
6168           {
6169             if ((AOP_TYPE(right) == AOP_LIT) &&
6170               (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
6171               {
6172                 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6173               }
6174             else
6175               {
6176                 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6177                 pic16_emitcode("xrl", "a,%s",
6178                                pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6179               }
6180             pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
6181             offset++;
6182           }
6183         if (size)
6184           {
6185             CLRC;
6186             pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
6187             pic16_outBitC(result);
6188           }
6189         else if (ifx)
6190           jmpTrueOrFalse(ifx, tlbl);
6191       }
6192     else
6193       {
6194         for (; (size--); offset++)
6195           {
6196             // normal case
6197             // result = left ^ right
6198             if (AOP_TYPE(right) == AOP_LIT)
6199               {
6200                 int t = (lit >> (offset * 8)) & 0x0FFL;
6201                 switch(t)
6202                   {
6203                   case 0x00:
6204                     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6205                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6206                     break;
6207
6208                   case 0xff:
6209                     pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
6210                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6211                     break;
6212
6213                   default:
6214                     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6215                     pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6216                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6217                   }
6218                 continue;
6219               }
6220
6221             // faster than result <- left, anl result,right
6222             // and better if result is SFR
6223             if (AOP_TYPE(left) == AOP_ACC)
6224               {
6225                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
6226               }
6227             else
6228               {
6229                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6230                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6231               }
6232             if ( AOP_TYPE(result) != AOP_ACC)
6233               {
6234                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6235               }
6236           }
6237       }
6238   }
6239
6240 release :
6241   pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6242   pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6243   pic16_freeAsmop(result, NULL, ic, TRUE);
6244 }
6245
6246 /*-----------------------------------------------------------------*/
6247 /* genInline - write the inline code out                           */
6248 /*-----------------------------------------------------------------*/
6249 static void genInline (iCode *ic)
6250 {
6251   char *buffer, *bp, *bp1;
6252   bool inComment = FALSE;
6253
6254   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6255
6256   _G.inLine += (!options.asmpeep);
6257
6258   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6259
6260   while((bp1=strstr(bp, "\\n"))) {
6261     *bp1++ = '\n';
6262     *bp1++ = ' ';
6263     bp = bp1;
6264   }
6265   bp = bp1 = buffer;
6266
6267 #if 0
6268   /* This is an experimental code for #pragma inline
6269      and is temporarily disabled for 2.5.0 release */
6270   if(asmInlineMap)
6271   {
6272     symbol *sym;
6273     char *s;
6274     char *cbuf;
6275     int cblen;
6276
6277       cbuf = Safe_strdup(buffer);
6278       cblen = strlen(buffer)+1;
6279       memset(cbuf, 0, cblen);
6280
6281       bp = buffer;
6282       bp1 = cbuf;
6283       while(*bp) {
6284         if(*bp != '%')*bp1++ = *bp++;
6285         else {
6286           int i;
6287
6288             bp++;
6289             i = *bp - '0';
6290             if(i>elementsInSet(asmInlineMap))break;
6291
6292             bp++;
6293             s = indexSet(asmInlineMap, i);
6294             DEBUGpc("searching symbol s = `%s'", s);
6295             sym = findSym(SymbolTab, NULL, s);
6296
6297             if(sym->reqv) {
6298               strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
6299             } else {
6300               strcat(bp1, sym->rname);
6301             }
6302
6303             while(*bp1)bp1++;
6304         }
6305
6306         if(strlen(bp1) > cblen - 16) {
6307           int i = strlen(cbuf);
6308           cblen += 50;
6309           cbuf = realloc(cbuf, cblen);
6310           memset(cbuf+i, 0, 50);
6311           bp1 = cbuf + i;
6312         }
6313       }
6314
6315       free(buffer);
6316       buffer = Safe_strdup( cbuf );
6317       free(cbuf);
6318
6319       bp = bp1 = buffer;
6320   }
6321 #endif  /* 0 */
6322
6323   /* emit each line as a code */
6324   while (*bp)
6325     {
6326       switch (*bp)
6327         {
6328         case ';':
6329           inComment = TRUE;
6330           ++bp;
6331           break;
6332
6333         case '\n':
6334           inComment = FALSE;
6335           *bp++ = '\0';
6336           if (*bp1)
6337             pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6338           bp1 = bp;
6339           break;
6340
6341         default:
6342           /* Add \n for labels, not dirs such as c:\mydir */
6343           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6344             {
6345               ++bp;
6346               *bp = '\0';
6347               ++bp;
6348               /* print label, use this special format with NULL directive
6349                * to denote that the argument should not be indented with tab */
6350               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6351               bp1 = bp;
6352             }
6353           else
6354             ++bp;
6355           break;
6356         }
6357     }
6358
6359   if ((bp1 != bp) && *bp1)
6360     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6361
6362   Safe_free (buffer);
6363
6364   _G.inLine -= (!options.asmpeep);
6365 }
6366
6367 /*-----------------------------------------------------------------*/
6368 /* genRRC - rotate right with carry                                */
6369 /*-----------------------------------------------------------------*/
6370 static void genRRC (iCode *ic)
6371 {
6372   operand *left , *result ;
6373   int size, offset = 0, same;
6374
6375   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6376
6377   /* rotate right with carry */
6378   left = IC_LEFT(ic);
6379   result=IC_RESULT(ic);
6380   pic16_aopOp (left,ic,FALSE);
6381   pic16_aopOp (result,ic,TRUE);
6382
6383   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6384
6385   same = pic16_sameRegs(AOP(result),AOP(left));
6386
6387   size = AOP_SIZE(result);
6388
6389   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6390
6391   /* get the lsb and put it into the carry */
6392   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6393
6394   offset = 0 ;
6395
6396   while(size--) {
6397
6398     if(same) {
6399       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6400     } else {
6401       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6402       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6403     }
6404
6405     offset++;
6406   }
6407
6408   pic16_freeAsmop(left,NULL,ic,TRUE);
6409   pic16_freeAsmop(result,NULL,ic,TRUE);
6410 }
6411
6412 /*-----------------------------------------------------------------*/
6413 /* genRLC - generate code for rotate left with carry               */
6414 /*-----------------------------------------------------------------*/
6415 static void genRLC (iCode *ic)
6416 {
6417   operand *left , *result ;
6418   int size, offset = 0;
6419   int same;
6420
6421   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6422   /* rotate right with carry */
6423   left = IC_LEFT(ic);
6424   result=IC_RESULT(ic);
6425   pic16_aopOp (left,ic,FALSE);
6426   pic16_aopOp (result,ic,TRUE);
6427
6428   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6429
6430   same = pic16_sameRegs(AOP(result),AOP(left));
6431
6432   /* move it to the result */
6433   size = AOP_SIZE(result);
6434
6435   /* get the msb and put it into the carry */
6436   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6437
6438   offset = 0 ;
6439
6440   while(size--) {
6441
6442     if(same) {
6443       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6444     } else {
6445       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6446       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6447     }
6448
6449     offset++;
6450   }
6451
6452
6453   pic16_freeAsmop(left,NULL,ic,TRUE);
6454   pic16_freeAsmop(result,NULL,ic,TRUE);
6455 }
6456
6457
6458 /* gpasm can get the highest order bit with HIGH/UPPER
6459  * so the following probably is not needed -- VR */
6460
6461 /*-----------------------------------------------------------------*/
6462 /* genGetHbit - generates code get highest order bit               */
6463 /*-----------------------------------------------------------------*/
6464 static void genGetHbit (iCode *ic)
6465 {
6466     operand *left, *result;
6467     left = IC_LEFT(ic);
6468     result=IC_RESULT(ic);
6469     pic16_aopOp (left,ic,FALSE);
6470     pic16_aopOp (result,ic,FALSE);
6471
6472     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6473     /* get the highest order byte into a */
6474     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6475     if(AOP_TYPE(result) == AOP_CRY){
6476         pic16_emitcode("rlc","a");
6477         pic16_outBitC(result);
6478     }
6479     else{
6480         pic16_emitcode("rl","a");
6481         pic16_emitcode("anl","a,#0x01");
6482         pic16_outAcc(result);
6483     }
6484
6485
6486     pic16_freeAsmop(left,NULL,ic,TRUE);
6487     pic16_freeAsmop(result,NULL,ic,TRUE);
6488 }
6489
6490 #if 0
6491 /*-----------------------------------------------------------------*/
6492 /* AccRol - rotate left accumulator by known count                 */
6493 /*-----------------------------------------------------------------*/
6494 static void AccRol (int shCount)
6495 {
6496     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6497     shCount &= 0x0007;              // shCount : 0..7
6498     switch(shCount){
6499         case 0 :
6500             break;
6501         case 1 :
6502             pic16_emitcode("rl","a");
6503             break;
6504         case 2 :
6505             pic16_emitcode("rl","a");
6506             pic16_emitcode("rl","a");
6507             break;
6508         case 3 :
6509             pic16_emitcode("swap","a");
6510             pic16_emitcode("rr","a");
6511             break;
6512         case 4 :
6513             pic16_emitcode("swap","a");
6514             break;
6515         case 5 :
6516             pic16_emitcode("swap","a");
6517             pic16_emitcode("rl","a");
6518             break;
6519         case 6 :
6520             pic16_emitcode("rr","a");
6521             pic16_emitcode("rr","a");
6522             break;
6523         case 7 :
6524             pic16_emitcode("rr","a");
6525             break;
6526     }
6527 }
6528 #endif
6529
6530 /*-----------------------------------------------------------------*/
6531 /* AccLsh - left shift accumulator by known count                  */
6532 /*-----------------------------------------------------------------*/
6533 static void AccLsh (int shCount, int doMask)
6534 {
6535         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6536         switch(shCount){
6537                 case 0 :
6538                         return;
6539                         break;
6540                 case 1 :
6541                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6542                         break;
6543                 case 2 :
6544                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6545                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6546                         break;
6547                 case 3 :
6548                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6549                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6550                         break;
6551                 case 4 :
6552                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6553                         break;
6554                 case 5 :
6555                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6556                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6557                         break;
6558                 case 6 :
6559                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6560                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6561                         break;
6562                 case 7 :
6563                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6564                         break;
6565         }
6566         if (doMask) {
6567                 /* no masking is required in genPackBits */
6568                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6569         }
6570 }
6571
6572 /*-----------------------------------------------------------------*/
6573 /* AccRsh - right shift accumulator by known count                 */
6574 /*-----------------------------------------------------------------*/
6575 static void AccRsh (int shCount, int andmask)
6576 {
6577         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6578         assert ((shCount >= 0) && (shCount <= 8));
6579         switch (shCount) {
6580                 case 0 :
6581                         return; break;
6582                 case 1 :
6583                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6584                         break;
6585                 case 2 :
6586                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6587                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6588                         break;
6589                 case 3 :
6590                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6591                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6592                         break;
6593                 case 4 :
6594                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6595                         break;
6596                 case 5 :
6597                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6598                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6599                         break;
6600                 case 6 :
6601                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6602                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6603                         break;
6604                 case 7 :
6605                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6606                         break;
6607                 default:
6608                         // Rotating by 8 is a NOP.
6609                         break;
6610         }
6611
6612         if (andmask)
6613                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6614         else
6615                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6616 }
6617
6618 /*-----------------------------------------------------------------*/
6619 /* shiftR1Left2Result - shift right one byte from left to result   */
6620 /*-----------------------------------------------------------------*/
6621 static void shiftR1Left2ResultSigned (operand *left, int offl,
6622                                 operand *result, int offr,
6623                                 int shCount)
6624 {
6625   int same;
6626
6627   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6628   assert ((shCount >= 0) && (shCount <= 8));
6629
6630   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6631
6632   /* Do NOT use result for intermediate results, it might be an SFR!. */
6633   switch (shCount) {
6634   case 0:
6635     if (!same) {
6636       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6637       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6638     }
6639     break;
6640
6641   case 1:
6642     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
6643     if (same)
6644       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6645     else {
6646       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
6647       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6648     }
6649     break;
6650
6651   case 2:
6652     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6653     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6654     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
6655     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
6656     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
6657     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6658     break;
6659
6660   case 3:
6661     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6662     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6663     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
6664     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
6665     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
6666     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6667     break;
6668
6669   case 4:
6670     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6671     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
6672     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
6673     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
6674     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6675     break;
6676
6677   case 5:
6678     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6679     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6680     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
6681     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
6682     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
6683     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6684     break;
6685
6686   case 6:
6687     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6688     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6689     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
6690     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
6691     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
6692     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6693     break;
6694
6695   case 7:
6696     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6697     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
6698     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6699     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6700     break;
6701
6702   default:
6703     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6704     break;
6705   }
6706 }
6707
6708 /*-----------------------------------------------------------------*/
6709 /* shiftR1Left2Result - shift right one byte from left to result   */
6710 /*-----------------------------------------------------------------*/
6711 static void shiftR1Left2Result (operand *left, int offl,
6712                                 operand *result, int offr,
6713                                 int shCount, int sign)
6714 {
6715   int same;
6716
6717   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6718   assert ((shCount >= 0) && (shCount <= 8));
6719
6720   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6721
6722   /* Copy the msb into the carry if signed. */
6723   if (sign) {
6724     shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
6725     return;
6726   }
6727
6728   /* Do NOT use result for intermediate results, it might be an SFR!. */
6729   switch (shCount) {
6730   case 0:
6731     if (!same) {
6732       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6733       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6734     }
6735     break;
6736
6737   case 1:
6738     if (same) {
6739       emitCLRC;
6740       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6741     } else {
6742       pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6743       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
6744       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6745     }
6746     break;
6747
6748   case 2:
6749     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6750     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6751     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
6752     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6753     break;
6754
6755   case 3:
6756     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6757     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6758     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6759     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6760     break;
6761
6762   case 4:
6763     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6764     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6765     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6766     break;
6767
6768   case 5:
6769     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6770     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6771     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
6772     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6773     break;
6774
6775   case 6:
6776     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6777     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6778     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
6779     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6780     break;
6781
6782   case 7:
6783     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6784     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
6785     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6786     break;
6787
6788   default:
6789     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6790     break;
6791   }
6792 }
6793
6794 /*-----------------------------------------------------------------*/
6795 /* shiftL1Left2Result - shift left one byte from left to result    */
6796 /*-----------------------------------------------------------------*/
6797 static void shiftL1Left2Result (operand *left, int offl,
6798                                 operand *result, int offr, int shCount)
6799 {
6800   int same;
6801
6802   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6803   assert ((shCount >= 0) && (shCount <= 8));
6804
6805   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6806
6807   /* Do NOT use result for intermediate results, it might be an SFR!. */
6808   switch (shCount) {
6809   case 0:
6810     if (!same) {
6811       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6812       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6813     }
6814     break;
6815
6816   case 1:
6817     if (same) {
6818       emitCLRC;
6819       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
6820     } else {
6821       pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6822       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
6823       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6824     }
6825     break;
6826
6827   case 2:
6828     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6829     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6830     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
6831     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6832     break;
6833
6834   case 3:
6835     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6836     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6837     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
6838     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6839     break;
6840
6841   case 4:
6842     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6843     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6844     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6845     break;
6846
6847   case 5:
6848     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6849     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6850     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
6851     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6852     break;
6853
6854   case 6:
6855     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6856     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6857     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
6858     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6859     break;
6860
6861   case 7:
6862     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6863     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6864     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6865     break;
6866
6867   default:
6868     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6869     break;
6870   }
6871 }
6872
6873 /*-----------------------------------------------------------------*/
6874 /* movLeft2Result - move byte from left to result                  */
6875 /*-----------------------------------------------------------------*/
6876 static void movLeft2Result (operand *left, int offl,
6877                             operand *result, int offr)
6878 {
6879   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6880   if (!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)) {
6881     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6882     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6883   }
6884 }
6885
6886 /*-----------------------------------------------------------------*/
6887 /* shiftL2Left2Result - shift left two bytes from left to result   */
6888 /*-----------------------------------------------------------------*/
6889 static void shiftL2Left2Result (operand *left, int offl,
6890                                 operand *result, int offr, int shCount)
6891 {
6892   int same = pic16_sameRegs(AOP(result), AOP(left));
6893   int i;
6894
6895   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6896
6897   if (same && (offl != offr)) { // shift bytes
6898     if (offr > offl) {
6899        for(i=1;i>-1;i--) {
6900          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6901          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6902        }
6903     } else { // just treat as different later on
6904                 same = 0;
6905     }
6906   }
6907
6908   if(same) {
6909     switch(shCount) {
6910     case 0:
6911       break;
6912     case 1:
6913     case 2:
6914     case 3:
6915
6916       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6917       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6918       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6919
6920       while(--shCount) {
6921                 emitCLRC;
6922                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6923                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6924       }
6925
6926       break;
6927     case 4:
6928     case 5:
6929       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6930       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6931       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6932       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6933       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6934       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6935       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6936       if(shCount >=5) {
6937                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6938                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6939       }
6940       break;
6941     case 6:
6942       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6943       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6944       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6945       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6946       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6947       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6948       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6949       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6950       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6951       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6952       break;
6953     case 7:
6954       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6955       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6956       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6957       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6958       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6959     }
6960
6961   } else {
6962     switch(shCount) {
6963     case 0:
6964       break;
6965     case 1:
6966     case 2:
6967     case 3:
6968       /* note, use a mov/add for the shift since the mov has a
6969          chance of getting optimized out */
6970       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6971       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6972       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
6973       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
6974       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6975
6976       while(--shCount) {
6977                 emitCLRC;
6978                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6979                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6980       }
6981       break;
6982
6983     case 4:
6984     case 5:
6985       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
6986       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
6987       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
6988       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6989       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6990       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
6991       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6992       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6993
6994
6995       if(shCount == 5) {
6996                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6997                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6998       }
6999       break;
7000     case 6:
7001       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7002       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7003       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7004       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7005
7006       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7007       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7008       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7009       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7010       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7011       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7012       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7013       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7014       break;
7015     case 7:
7016       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7017       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7018       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7019       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7020       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7021     }
7022   }
7023
7024 }
7025 /*-----------------------------------------------------------------*/
7026 /* shiftR2Left2Result - shift right two bytes from left to result  */
7027 /*-----------------------------------------------------------------*/
7028 static void shiftR2Left2Result (operand *left, int offl,
7029                                 operand *result, int offr,
7030                                 int shCount, int sign)
7031 {
7032   int same = pic16_sameRegs(AOP(result), AOP(left));
7033   int i;
7034   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7035
7036   if (same && (offl != offr)) { // shift right bytes
7037     if (offr < offl) {
7038        for(i=0;i<2;i++) {
7039          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7040          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7041        }
7042     } else { // just treat as different later on
7043                 same = 0;
7044     }
7045   }
7046
7047   switch(shCount) {
7048   case 0:
7049     break;
7050   case 1:
7051   case 2:
7052   case 3:
7053     /* obtain sign from left operand */
7054     if(sign)
7055       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
7056     else
7057       emitCLRC;
7058
7059     if(same) {
7060       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7061       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7062     } else {
7063       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7064       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7065       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7066       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7067     }
7068
7069     while(--shCount) {
7070       if(sign)
7071         /* now get sign from already assigned result (avoid BANKSEL) */
7072         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7073       else
7074         emitCLRC;
7075       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7076       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7077     }
7078     break;
7079   case 4:
7080   case 5:
7081     if(same) {
7082
7083       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7084       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7085       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7086
7087       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7088       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7089       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7090       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7091     } else {
7092       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7093       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7094       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7095
7096       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7097       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7098       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7099       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7100       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7101     }
7102
7103     if(shCount >=5) {
7104       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7105       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7106     }
7107
7108     if(sign) {
7109       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7110       pic16_emitpcode(POC_BTFSC,
7111                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7112       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7113     }
7114
7115     break;
7116
7117   case 6:
7118     if(same) {
7119
7120       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7121       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7122
7123       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7124       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7125       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7126       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7127       if(sign) {
7128         pic16_emitpcode(POC_BTFSC,
7129                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7130         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7131       }
7132       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7133       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7134       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7135       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7136     } else {
7137       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7138       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7139       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7140       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7141       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7142       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7143       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7144       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7145       if(sign) {
7146         pic16_emitpcode(POC_BTFSC,
7147                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7148         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7149       }
7150       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7151       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7152
7153
7154     }
7155
7156     break;
7157   case 7:
7158     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7159     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7160     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7161     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7162     if(sign) {
7163       emitSKPNC;
7164       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7165     } else
7166       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7167   }
7168 }
7169
7170
7171 /*-----------------------------------------------------------------*/
7172 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7173 /*-----------------------------------------------------------------*/
7174 static void shiftLLeftOrResult (operand *left, int offl,
7175                                 operand *result, int offr, int shCount)
7176 {
7177     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7178
7179     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7180     /* shift left accumulator */
7181     AccLsh(shCount, 1);
7182     /* or with result */
7183     /* back to result */
7184     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7185 }
7186
7187 /*-----------------------------------------------------------------*/
7188 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7189 /*-----------------------------------------------------------------*/
7190 static void shiftRLeftOrResult (operand *left, int offl,
7191                                 operand *result, int offr, int shCount)
7192 {
7193     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7194
7195     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7196     /* shift right accumulator */
7197     AccRsh(shCount, 1);
7198     /* or with result */
7199     /* back to result */
7200     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7201 }
7202
7203 /*-----------------------------------------------------------------*/
7204 /* genlshOne - left shift a one byte quantity by known count       */
7205 /*-----------------------------------------------------------------*/
7206 static void genlshOne (operand *result, operand *left, int shCount)
7207 {
7208     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7209     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7210 }
7211
7212 /*-----------------------------------------------------------------*/
7213 /* genlshTwo - left shift two bytes by known amount != 0           */
7214 /*-----------------------------------------------------------------*/
7215 static void genlshTwo (operand *result,operand *left, int shCount)
7216 {
7217     int size;
7218
7219     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7220     size = pic16_getDataSize(result);
7221
7222     /* if shCount >= 8 */
7223     if (shCount >= 8) {
7224         shCount -= 8 ;
7225
7226         if (size > 1){
7227             if (shCount)
7228                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7229             else
7230                 movLeft2Result(left, LSB, result, MSB16);
7231         }
7232         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7233     }
7234
7235     /*  1 <= shCount <= 7 */
7236     else {
7237         if(size == 1)
7238             shiftL1Left2Result(left, LSB, result, LSB, shCount);
7239         else
7240             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7241     }
7242 }
7243
7244 /*-----------------------------------------------------------------*/
7245 /* shiftLLong - shift left one long from left to result            */
7246 /* offr = LSB or MSB16                                             */
7247 /*-----------------------------------------------------------------*/
7248 static void shiftLLong (operand *left, operand *result, int offr )
7249 {
7250     int size = AOP_SIZE(result);
7251     int same = pic16_sameRegs(AOP(left),AOP(result));
7252         int i;
7253
7254     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7255
7256         if (same && (offr == MSB16)) { //shift one byte
7257                 for(i=size-1;i>=MSB16;i--) {
7258                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7259                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7260                 }
7261         } else {
7262                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7263         }
7264
7265     if (size > LSB+offr ){
7266                 if (same) {
7267                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7268                 } else {
7269                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7270                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7271                 }
7272          }
7273
7274     if(size > MSB16+offr){
7275                 if (same) {
7276                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7277                 } else {
7278                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7279                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7280                 }
7281     }
7282
7283     if(size > MSB24+offr){
7284                 if (same) {
7285                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7286                 } else {
7287                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7288                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7289                 }
7290     }
7291
7292     if(size > MSB32+offr){
7293                 if (same) {
7294                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7295                 } else {
7296                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7297                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7298                 }
7299     }
7300     if(offr != LSB)
7301                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7302
7303 }
7304
7305 /*-----------------------------------------------------------------*/
7306 /* genlshFour - shift four byte by a known amount != 0             */
7307 /*-----------------------------------------------------------------*/
7308 static void genlshFour (operand *result, operand *left, int shCount)
7309 {
7310     int size;
7311
7312     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7313     size = AOP_SIZE(result);
7314
7315     /* if shifting more that 3 bytes */
7316     if (shCount >= 24 ) {
7317         shCount -= 24;
7318         if (shCount)
7319             /* lowest order of left goes to the highest
7320             order of the destination */
7321             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7322         else
7323             movLeft2Result(left, LSB, result, MSB32);
7324
7325                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7326                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7327                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7328
7329         return;
7330     }
7331
7332     /* more than two bytes */
7333     else if ( shCount >= 16 ) {
7334         /* lower order two bytes goes to higher order two bytes */
7335         shCount -= 16;
7336         /* if some more remaining */
7337         if (shCount)
7338             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7339         else {
7340             movLeft2Result(left, MSB16, result, MSB32);
7341             movLeft2Result(left, LSB, result, MSB24);
7342         }
7343                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7344                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7345         return;
7346     }
7347
7348     /* if more than 1 byte */
7349     else if ( shCount >= 8 ) {
7350         /* lower order three bytes goes to higher order  three bytes */
7351         shCount -= 8;
7352         if(size == 2){
7353             if(shCount)
7354                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7355             else
7356                 movLeft2Result(left, LSB, result, MSB16);
7357         }
7358         else{   /* size = 4 */
7359             if(shCount == 0){
7360                 movLeft2Result(left, MSB24, result, MSB32);
7361                 movLeft2Result(left, MSB16, result, MSB24);
7362                 movLeft2Result(left, LSB, result, MSB16);
7363                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7364             }
7365             else if(shCount == 1)
7366                 shiftLLong(left, result, MSB16);
7367             else{
7368                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7369                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7370                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7371                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7372             }
7373         }
7374     }
7375
7376     /* 1 <= shCount <= 7 */
7377     else if(shCount <= 3)
7378     {
7379         shiftLLong(left, result, LSB);
7380         while(--shCount >= 1)
7381             shiftLLong(result, result, LSB);
7382     }
7383     /* 3 <= shCount <= 7, optimize */
7384     else{
7385         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7386         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7387         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7388     }
7389 }
7390
7391 /*-----------------------------------------------------------------*/
7392 /* genLeftShiftLiteral - left shifting by known count              */
7393 /*-----------------------------------------------------------------*/
7394 void pic16_genLeftShiftLiteral (operand *left,
7395                                  operand *right,
7396                                  operand *result,
7397                                  iCode *ic)
7398 {
7399     int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7400     int size;
7401
7402     FENTRY;
7403     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
7404     pic16_freeAsmop(right,NULL,ic,TRUE);
7405
7406     pic16_aopOp(left,ic,FALSE);
7407     pic16_aopOp(result,ic,TRUE);
7408
7409     size = getSize(operandType(result));
7410
7411 #if VIEW_SIZE
7412     pic16_emitcode("; shift left ","result %d, left %d",size,
7413              AOP_SIZE(left));
7414 #endif
7415
7416     /* I suppose that the left size >= result size */
7417     if(shCount == 0){
7418         while(size--){
7419             movLeft2Result(left, size, result, size);
7420         }
7421     }
7422
7423     else if(shCount >= (size * 8))
7424         while(size--)
7425             pic16_aopPut(AOP(result),zero,size);
7426     else{
7427         switch (size) {
7428             case 1:
7429                 genlshOne (result,left,shCount);
7430                 break;
7431
7432             case 2:
7433             case 3:
7434                 genlshTwo (result,left,shCount);
7435                 break;
7436
7437             case 4:
7438                 genlshFour (result,left,shCount);
7439                 break;
7440         }
7441     }
7442     pic16_freeAsmop(left,NULL,ic,TRUE);
7443     pic16_freeAsmop(result,NULL,ic,TRUE);
7444 }
7445
7446 /*-----------------------------------------------------------------*
7447  * genMultiAsm - repeat assembly instruction for size of register.
7448  * if endian == 1, then the high byte (i.e base address + size of
7449  * register) is used first else the low byte is used first;
7450  *-----------------------------------------------------------------*/
7451 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7452 {
7453
7454   int offset = 0;
7455
7456   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7457
7458   if(!reg)
7459     return;
7460
7461   if(!endian) {
7462     endian = 1;
7463   } else {
7464     endian = -1;
7465     offset = size-1;
7466   }
7467
7468   while(size--) {
7469     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7470     offset += endian;
7471   }
7472
7473 }
7474
7475 /*-----------------------------------------------------------------*/
7476 /* genrshOne - right shift a one byte quantity by known count      */
7477 /*-----------------------------------------------------------------*/
7478 static void genrshOne (operand *result, operand *left,
7479                        int shCount, int sign)
7480 {
7481     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7482     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7483 }
7484
7485 /*-----------------------------------------------------------------*/
7486 /* genrshTwo - right shift two bytes by known amount != 0          */
7487 /*-----------------------------------------------------------------*/
7488 static void genrshTwo (operand *result,operand *left,
7489                        int shCount, int sign)
7490 {
7491   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7492   /* if shCount >= 8 */
7493   if (shCount >= 8) {
7494     shCount -= 8 ;
7495     if (shCount)
7496       shiftR1Left2Result(left, MSB16, result, LSB,
7497                          shCount, sign);
7498     else
7499       movLeft2Result(left, MSB16, result, LSB);
7500
7501     pic16_addSign (result, 1, sign);
7502   }
7503
7504   /*  1 <= shCount <= 7 */
7505   else
7506     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7507 }
7508
7509 /*-----------------------------------------------------------------*/
7510 /* shiftRLong - shift right one long from left to result           */
7511 /* offl = LSB or MSB16                                             */
7512 /*-----------------------------------------------------------------*/
7513 static void shiftRLong (operand *left, int offl,
7514                         operand *result, int sign)
7515 {
7516     int size = AOP_SIZE(result);
7517     int same = pic16_sameRegs(AOP(left),AOP(result));
7518     int i;
7519     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7520
7521         if (same && (offl == MSB16)) { //shift one byte right
7522                 for(i=MSB16;i<size;i++) {
7523                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7524                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7525                 }
7526         }
7527
7528     if(sign)
7529                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7530         else
7531                 emitCLRC;
7532
7533         if (same) {
7534                 if (offl == LSB)
7535                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7536         } else {
7537         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7538         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7539         }
7540
7541     if(offl == MSB16) {
7542         /* add sign of "a" */
7543         pic16_addSign(result, MSB32, sign);
7544         }
7545
7546         if (same) {
7547         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7548         } else {
7549         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7550         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7551         }
7552
7553         if (same) {
7554         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7555         } else {
7556         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7557         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7558         }
7559
7560         if (same) {
7561         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7562         } else {
7563         if(offl == LSB){
7564                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7565                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7566         }
7567         }
7568 }
7569
7570 /*-----------------------------------------------------------------*/
7571 /* genrshFour - shift four byte by a known amount != 0             */
7572 /*-----------------------------------------------------------------*/
7573 static void genrshFour (operand *result, operand *left,
7574                         int shCount, int sign)
7575 {
7576   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7577   /* if shifting more that 3 bytes */
7578   if(shCount >= 24 ) {
7579     shCount -= 24;
7580     if(shCount)
7581       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7582     else
7583       movLeft2Result(left, MSB32, result, LSB);
7584
7585     pic16_addSign(result, MSB16, sign);
7586   }
7587   else if(shCount >= 16){
7588     shCount -= 16;
7589     if(shCount)
7590       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7591     else{
7592       movLeft2Result(left, MSB24, result, LSB);
7593       movLeft2Result(left, MSB32, result, MSB16);
7594     }
7595     pic16_addSign(result, MSB24, sign);
7596   }
7597   else if(shCount >= 8){
7598     shCount -= 8;
7599     if(shCount == 1)
7600       shiftRLong(left, MSB16, result, sign);
7601     else if(shCount == 0){
7602       movLeft2Result(left, MSB16, result, LSB);
7603       movLeft2Result(left, MSB24, result, MSB16);
7604       movLeft2Result(left, MSB32, result, MSB24);
7605       pic16_addSign(result, MSB32, sign);
7606     }
7607     else{ //shcount >= 2
7608       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7609       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7610       /* the last shift is signed */
7611       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7612       pic16_addSign(result, MSB32, sign);
7613     }
7614   }
7615   else{   /* 1 <= shCount <= 7 */
7616     if(shCount <= 2){
7617       shiftRLong(left, LSB, result, sign);
7618       if(shCount == 2)
7619         shiftRLong(result, LSB, result, sign);
7620     }
7621     else{
7622       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7623       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7624       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7625     }
7626   }
7627 }
7628
7629 /*-----------------------------------------------------------------*/
7630 /* genRightShiftLiteral - right shifting by known count            */
7631 /*-----------------------------------------------------------------*/
7632 static void genRightShiftLiteral (operand *left,
7633                                   operand *right,
7634                                   operand *result,
7635                                   iCode *ic,
7636                                   int sign)
7637 {
7638   int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7639   int lsize,res_size;
7640
7641   pic16_freeAsmop(right,NULL,ic,TRUE);
7642
7643   pic16_aopOp(left,ic,FALSE);
7644   pic16_aopOp(result,ic,TRUE);
7645
7646   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7647
7648 #if VIEW_SIZE
7649   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7650                  AOP_SIZE(left));
7651 #endif
7652
7653   lsize = pic16_getDataSize(left);
7654   res_size = pic16_getDataSize(result);
7655   /* test the LEFT size !!! */
7656
7657   /* I suppose that the left size >= result size */
7658   if (shCount == 0) {
7659     assert (res_size <= lsize);
7660     while (res_size--) {
7661       pic16_mov2f (AOP(result), AOP(left), res_size);
7662     } // for
7663   } else if (shCount >= (lsize * 8)) {
7664     if (sign) {
7665       /* 
7666        * Do NOT use
7667        *    CLRF    result
7668        *    BTFSC   left, 7
7669        *    SETF    result
7670        * even for 8-bit operands; result might be an SFR.
7671        */
7672       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7673       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
7674       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7675       while (res_size--) {
7676         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
7677       }
7678     } else { // unsigned
7679       while (res_size--) {
7680         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
7681       }
7682     }
7683   } else { // 0 < shCount < 8*lsize
7684     switch (res_size) {
7685     case 1:
7686       genrshOne (result,left,shCount,sign);
7687       break;
7688
7689     case 2:
7690       genrshTwo (result,left,shCount,sign);
7691       break;
7692
7693     case 4:
7694       genrshFour (result,left,shCount,sign);
7695       break;
7696     default :
7697       break;
7698     }
7699   }
7700
7701   pic16_freeAsmop(left,NULL,ic,TRUE);
7702   pic16_freeAsmop(result,NULL,ic,TRUE);
7703 }
7704
7705 /*-----------------------------------------------------------------*/
7706 /* genGenericShift - generates code for left or right shifting     */
7707 /*-----------------------------------------------------------------*/
7708 static void genGenericShift (iCode *ic, int isShiftLeft)
7709 {
7710   operand *left,*right, *result;
7711   int offset;
7712   int sign, signedCount;
7713   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
7714   PIC_OPCODE pos_shift, neg_shift;
7715
7716   FENTRY;
7717
7718   right = IC_RIGHT(ic);
7719   left  = IC_LEFT(ic);
7720   result = IC_RESULT(ic);
7721
7722   pic16_aopOp(right,ic,FALSE);
7723   pic16_aopOp(left,ic,FALSE);
7724   pic16_aopOp(result,ic,TRUE);
7725
7726   sign = !SPEC_USIGN(operandType (left));
7727   signedCount = !SPEC_USIGN(operandType (right));
7728
7729   /* if the shift count is known then do it
7730      as efficiently as possible */
7731   if (AOP_TYPE(right) == AOP_LIT) {
7732     long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
7733     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
7734     // we should modify right->aopu.aop_lit here!
7735     // Instead we use abs(shCount) in genXXXShiftLiteral()...
7736     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
7737     if (isShiftLeft)
7738       pic16_genLeftShiftLiteral (left,right,result,ic);
7739     else
7740       genRightShiftLiteral (left,right,result,ic, sign);
7741
7742     goto release;
7743   } // if (right is literal)
7744
7745   /* shift count is unknown then we have to form a loop.
7746    * Note: we take only the lower order byte since shifting
7747    * more than 32 bits make no sense anyway, ( the
7748    * largest size of an object can be only 32 bits )
7749    * Note: we perform arithmetic shifts if the left operand is
7750    * signed and we do an (effective) right shift, i. e. we
7751    * shift in the sign bit from the left. */
7752
7753   label_complete = newiTempLabel ( NULL );
7754   label_loop_pos = newiTempLabel ( NULL );
7755   label_loop_neg = NULL;
7756   label_negative = NULL;
7757   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
7758   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
7759
7760   if (signedCount) {
7761     // additional labels needed
7762     label_loop_neg = newiTempLabel ( NULL );
7763     label_negative = newiTempLabel ( NULL );
7764   } // if
7765
7766   // copy source to result -- this will effectively truncate the left operand to the size of result!
7767   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
7768   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
7769   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
7770     pic16_mov2f (AOP(result),AOP(left), offset);
7771   } // for
7772
7773   // if result is longer than left, fill with zeros (or sign)
7774   if (AOP_SIZE(left) < AOP_SIZE(result)) {
7775     if (sign && AOP_SIZE(left) > 0) {
7776       // shift signed operand -- fill with sign
7777       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
7778       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
7779       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
7780       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7781         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
7782       } // for
7783     } else {
7784       // shift unsigned operand -- fill result with zeros
7785       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7786         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
7787       } // for
7788     }
7789   } // if (size mismatch)
7790
7791   pic16_mov2w (AOP(right), 0);
7792   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
7793   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
7794
7795 #if 0
7796   // perform a shift by one (shift count is positive)
7797   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7798   // 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])
7799   pic16_emitpLabel (label_loop_pos->key);
7800   emitCLRC;
7801   if (sign && (pos_shift == POC_RRCF)) {
7802     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7803     emitSETC;
7804   } // if
7805   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7806   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
7807   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
7808 #else
7809   // perform a shift by one (shift count is positive)
7810   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7811   // 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])
7812   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
7813   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
7814   emitCLRC;
7815   pic16_emitpLabel (label_loop_pos->key);
7816   if (sign && (pos_shift == POC_RRCF)) {
7817     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7818     emitSETC;
7819   } // if
7820   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7821   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7822   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7823   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
7824 #endif
7825
7826   if (signedCount) {
7827     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
7828
7829     pic16_emitpLabel (label_negative->key);
7830     // perform a shift by -1 (shift count is negative)
7831     // 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)
7832     emitCLRC;
7833     pic16_emitpLabel (label_loop_neg->key);
7834     if (sign && (neg_shift == POC_RRCF)) {
7835       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7836       emitSETC;
7837     } // if
7838     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
7839     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7840     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7841     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
7842   } // if (signedCount)
7843
7844   pic16_emitpLabel (label_complete->key);
7845
7846 release:
7847   pic16_freeAsmop (right,NULL,ic,TRUE);
7848   pic16_freeAsmop(left,NULL,ic,TRUE);
7849   pic16_freeAsmop(result,NULL,ic,TRUE);
7850 }
7851
7852 static void genLeftShift (iCode *ic) {
7853   genGenericShift (ic, 1);
7854 }
7855
7856 static void genRightShift (iCode *ic) {
7857   genGenericShift (ic, 0);
7858 }
7859
7860
7861 /* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */
7862 void pic16_loadFSR0(operand *op, int lit)
7863 {
7864   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || pic16_isLitOp( op )) {
7865     if (AOP_TYPE(op) == AOP_LIT) {
7866       /* handle 12 bit integers correctly */
7867       unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
7868       if ((val & 0x0fff) != val) {
7869         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
7870                 val, (val & 0x0fff) );
7871         val &= 0x0fff;
7872       }
7873       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
7874     } else {
7875       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
7876     }
7877   } else {
7878     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
7879     // set up FSR0 with address of result
7880     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
7881     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
7882   }
7883 }
7884
7885 /*----------------------------------------------------------------*/
7886 /* pic16_derefPtr - move one byte from the location ptr points to */
7887 /*                  to WREG (doWrite == 0) or one byte from WREG   */
7888 /*                  to the location ptr points to (doWrite != 0)   */
7889 /*----------------------------------------------------------------*/
7890 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
7891 {
7892   if (!IS_PTR(operandType(ptr)))
7893   {
7894     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
7895     else pic16_mov2w (AOP(ptr), 0);
7896     return;
7897   }
7898
7899   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
7900   /* We might determine pointer type right here: */
7901   p_type = DCL_TYPE(operandType(ptr));
7902
7903   switch (p_type) {
7904     case FPOINTER:
7905     case POINTER:
7906       if (!fsr0_setup || !*fsr0_setup)
7907       {
7908         pic16_loadFSR0( ptr, 0 );
7909         if (fsr0_setup) *fsr0_setup = 1;
7910       }
7911       if (doWrite)
7912         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7913       else
7914         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7915       break;
7916
7917     case GPOINTER:
7918       if (AOP(ptr)->aopu.aop_reg[2]) {
7919         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
7920         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
7921         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
7922         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
7923         pic16_mov2w(AOP(ptr), 2);
7924         pic16_callGenericPointerRW(doWrite, 1);
7925       } else {
7926         // data pointer (just 2 byte given)
7927         if (!fsr0_setup || !*fsr0_setup)
7928         {
7929           pic16_loadFSR0( ptr, 0 );
7930           if (fsr0_setup) *fsr0_setup = 1;
7931         }
7932         if (doWrite)
7933           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7934         else
7935           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7936       }
7937       break;
7938
7939     default:
7940       assert (0 && "invalid pointer type specified");
7941       break;
7942   }
7943 }
7944
7945 /*-----------------------------------------------------------------*/
7946 /* genUnpackBits - generates code for unpacking bits               */
7947 /*-----------------------------------------------------------------*/
7948 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
7949 {
7950   int shCnt ;
7951   sym_link *etype, *letype;
7952   int blen=0, bstr=0;
7953   int lbstr;
7954   int same;
7955   pCodeOp *op;
7956
7957   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7958   etype = getSpec(operandType(result));
7959   letype = getSpec(operandType(left));
7960
7961   //    if(IS_BITFIELD(etype)) {
7962   blen = SPEC_BLEN(etype);
7963   bstr = SPEC_BSTR(etype);
7964   //    }
7965
7966   lbstr = SPEC_BSTR( letype );
7967
7968   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
7969       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
7970
7971 #if 1
7972   if((blen == 1) && (bstr < 8)
7973       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
7974     /* it is a single bit, so use the appropriate bit instructions */
7975     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
7976
7977     same = pic16_sameRegs(AOP(left),AOP(result));
7978     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
7979     pic16_emitpcode(POC_CLRF, op);
7980
7981     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
7982       /* workaround to reduce the extra lfsr instruction */
7983       pic16_emitpcode(POC_BTFSC,
7984           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
7985     } else {
7986       assert (PIC_IS_DATA_PTR (operandType(left)));
7987       pic16_loadFSR0 (left, 0);
7988       pic16_emitpcode(POC_BTFSC,
7989           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
7990     }
7991
7992     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
7993       /* unsigned bitfields result in either 0 or 1 */
7994       pic16_emitpcode(POC_INCF, op);
7995     } else {
7996       /* signed bitfields result in either 0 or -1 */
7997       pic16_emitpcode(POC_DECF, op);
7998     }
7999     if (same) {
8000       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
8001     }
8002
8003     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8004     return;
8005   }
8006
8007 #endif
8008
8009   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8010     // access symbol directly
8011     pic16_mov2w (AOP(left), 0);
8012   } else {
8013     pic16_derefPtr (left, ptype, 0, NULL);
8014   }
8015
8016   /* if we have bitdisplacement then it fits   */
8017   /* into this byte completely or if length is */
8018   /* less than a byte                          */
8019   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
8020
8021     /* shift right acc */
8022     AccRsh(shCnt, 0);
8023
8024     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8025           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8026
8027     /* VR -- normally I would use the following, but since we use the hack,
8028      * to avoid the masking from AccRsh, why not mask it right now? */
8029
8030     /*
8031        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8032      */
8033
8034     /* extend signed bitfields to 8 bits */
8035     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
8036     {
8037       assert (blen + bstr > 0);
8038       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
8039       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
8040     }
8041
8042     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8043
8044     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8045     return ;
8046   }
8047
8048   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
8049   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8050   exit(EXIT_FAILURE);
8051
8052   return ;
8053 }
8054
8055
8056 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
8057 {
8058   int size, offset = 0, leoffset=0 ;
8059
8060         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8061         pic16_aopOp(result, ic, TRUE);
8062
8063         FENTRY;
8064
8065         size = AOP_SIZE(result);
8066 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8067
8068
8069 #if 1
8070         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
8071                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
8072                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
8073                 goto release;
8074         }
8075 #endif
8076
8077         if(AOP(left)->aopu.pcop->type == PO_DIR)
8078                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8079
8080         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8081
8082         while (size--) {
8083                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8084
8085 //              pic16_DumpOp("(result)",result);
8086                 if(pic16_isLitAop(AOP(result))) {
8087                         pic16_mov2w(AOP(left), offset); // patch 8
8088                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8089                 } else {
8090                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8091                                 pic16_popGet(AOP(left), offset), //patch 8
8092                                 pic16_popGet(AOP(result), offset)));
8093                 }
8094
8095                 offset++;
8096                 leoffset++;
8097         }
8098
8099 release:
8100     pic16_freeAsmop(result,NULL,ic,TRUE);
8101 }
8102
8103
8104
8105 /*-----------------------------------------------------------------*/
8106 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8107 /*-----------------------------------------------------------------*/
8108 static void genNearPointerGet (operand *left,
8109                                operand *result,
8110                                iCode *ic)
8111 {
8112 //  asmop *aop = NULL;
8113   //regs *preg = NULL ;
8114   sym_link *rtype, *retype;
8115   sym_link *ltype, *letype;
8116
8117     FENTRY;
8118
8119     rtype = operandType(result);
8120     retype= getSpec(rtype);
8121     ltype = operandType(left);
8122     letype= getSpec(ltype);
8123
8124     pic16_aopOp(left,ic,FALSE);
8125
8126 //    pic16_DumpOp("(left)",left);
8127 //    pic16_DumpOp("(result)",result);
8128
8129     /* if left is rematerialisable and
8130      * result is not bit variable type and
8131      * the left is pointer to data space i.e
8132      * lower 128 bytes of space */
8133
8134     if (AOP_TYPE(left) == AOP_PCODE
8135       && !IS_BITFIELD(retype)
8136       && DCL_TYPE(ltype) == POINTER) {
8137
8138         genDataPointerGet (left,result,ic);
8139         pic16_freeAsmop(left, NULL, ic, TRUE);
8140         return ;
8141     }
8142
8143     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8144     pic16_aopOp (result,ic,TRUE);
8145
8146     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
8147
8148 #if 1
8149     if(IS_BITFIELD( retype )
8150       && (SPEC_BLEN(operandType(result))==1)
8151     ) {
8152       iCode *nextic;
8153       pCodeOp *jop;
8154       int bitstrt, bytestrt;
8155
8156         /* if this is bitfield of size 1, see if we are checking the value
8157          * of a single bit in an if-statement,
8158          * if yes, then don't generate usual code, but execute the
8159          * genIfx directly -- VR */
8160
8161         nextic = ic->next;
8162
8163         /* CHECK: if next iCode is IFX
8164          * and current result operand is nextic's conditional operand
8165          * and current result operand live ranges ends at nextic's key number
8166          */
8167         if((nextic->op == IFX)
8168           && (result == IC_COND(nextic))
8169           && (OP_LIVETO(result) == nextic->seq)
8170           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
8171           ) {
8172             /* everything is ok then */
8173             /* find a way to optimize the genIfx iCode */
8174
8175             bytestrt = SPEC_BSTR(operandType(result))/8;
8176             bitstrt = SPEC_BSTR(operandType(result))%8;
8177
8178             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
8179
8180             genIfxpCOpJump(nextic, jop);
8181
8182             pic16_freeAsmop(left, NULL, ic, TRUE);
8183             pic16_freeAsmop(result, NULL, ic, TRUE);
8184             return;
8185         }
8186     }
8187 #endif
8188
8189     /* if bitfield then unpack the bits */
8190     if (IS_BITFIELD(letype))
8191       genUnpackBits (result, left, NULL, POINTER);
8192     else {
8193       /* we have can just get the values */
8194       int size = AOP_SIZE(result);
8195       int offset = 0;
8196
8197       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8198
8199       pic16_loadFSR0( left, 0 );
8200
8201       while(size--) {
8202         if(size) {
8203           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8204                 pic16_popGet(AOP(result), offset++)));
8205         } else {
8206           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8207                 pic16_popGet(AOP(result), offset++)));
8208         }
8209       }
8210     }
8211
8212 #if 0
8213     /* now some housekeeping stuff */
8214     if (aop) {
8215       /* we had to allocate for this iCode */
8216       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8217       pic16_freeAsmop(NULL,aop,ic,TRUE);
8218     } else {
8219       /* we did not allocate which means left
8220        * already in a pointer register, then
8221        * if size > 0 && this could be used again
8222        * we have to point it back to where it
8223        * belongs */
8224       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8225       if (AOP_SIZE(result) > 1
8226         && !OP_SYMBOL(left)->remat
8227         && ( OP_SYMBOL(left)->liveTo > ic->seq
8228             || ic->depth )) {
8229 //        int size = AOP_SIZE(result) - 1;
8230 //        while (size--)
8231 //          pic16_emitcode("dec","%s",rname);
8232         }
8233     }
8234 #endif
8235
8236     /* done */
8237     pic16_freeAsmop(left,NULL,ic,TRUE);
8238     pic16_freeAsmop(result,NULL,ic,TRUE);
8239 }
8240
8241 /*-----------------------------------------------------------------*/
8242 /* genGenPointerGet - gget value from generic pointer space        */
8243 /*-----------------------------------------------------------------*/
8244 static void genGenPointerGet (operand *left,
8245                               operand *result, iCode *ic)
8246 {
8247   int size;
8248   sym_link *letype = getSpec(operandType(left));
8249
8250   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8251   pic16_aopOp(left,ic,FALSE);
8252   pic16_aopOp(result,ic,TRUE);
8253   size = AOP_SIZE(result);
8254
8255   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8256
8257   /* if bit then unpack */
8258   if (IS_BITFIELD(letype)) {
8259     genUnpackBits(result,left,"BAD",GPOINTER);
8260     goto release;
8261   }
8262
8263   /* set up WREG:PRODL:FSR0L with address from left */
8264   mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
8265   mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
8266   pic16_mov2w(AOP(left), 2);
8267   pic16_callGenericPointerRW(0, size);
8268
8269   assignResultValue(result, size, 1);
8270
8271 release:
8272   pic16_freeAsmop(left,NULL,ic,TRUE);
8273   pic16_freeAsmop(result,NULL,ic,TRUE);
8274 }
8275
8276 /*-----------------------------------------------------------------*/
8277 /* genConstPointerGet - get value from const generic pointer space */
8278 /*-----------------------------------------------------------------*/
8279 static void genConstPointerGet (operand *left,
8280                                 operand *result, iCode *ic)
8281 {
8282   //sym_link *retype = getSpec(operandType(result));
8283   // symbol *albl = newiTempLabel(NULL);        // patch 15
8284   // symbol *blbl = newiTempLabel(NULL);        //
8285   // PIC_OPCODE poc;                            // patch 15
8286   int size;
8287   int offset = 0;
8288
8289   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8290   pic16_aopOp(left,ic,FALSE);
8291   pic16_aopOp(result,ic,TRUE);
8292   size = AOP_SIZE(result);
8293
8294   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8295
8296   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8297
8298   // set up table pointer
8299   if( (AOP_TYPE(left) == AOP_PCODE)
8300       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8301           || (AOP(left)->aopu.pcop->type == PO_DIR)))
8302     {
8303       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
8304       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
8305       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
8306       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
8307       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
8308       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
8309   } else {
8310     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
8311     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
8312     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
8313   }
8314
8315   while(size--) {
8316     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
8317     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
8318     offset++;
8319   }
8320
8321   pic16_freeAsmop(left,NULL,ic,TRUE);
8322   pic16_freeAsmop(result,NULL,ic,TRUE);
8323 }
8324
8325
8326 /*-----------------------------------------------------------------*/
8327 /* genPointerGet - generate code for pointer get                   */
8328 /*-----------------------------------------------------------------*/
8329 static void genPointerGet (iCode *ic)
8330 {
8331   operand *left, *result ;
8332   sym_link *type, *etype;
8333   int p_type;
8334
8335     FENTRY;
8336
8337     left = IC_LEFT(ic);
8338     result = IC_RESULT(ic) ;
8339
8340     /* depending on the type of pointer we need to
8341     move it to the correct pointer register */
8342     type = operandType(left);
8343     etype = getSpec(type);
8344
8345 #if 0
8346     if (IS_PTR_CONST(type))
8347 #else
8348     if (IS_CODEPTR(type))
8349 #endif
8350       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8351
8352     /* if left is of type of pointer then it is simple */
8353     if (IS_PTR(type) && !IS_FUNC(type->next))
8354       p_type = DCL_TYPE(type);
8355     else {
8356       /* we have to go by the storage class */
8357       p_type = PTR_TYPE(SPEC_OCLS(etype));
8358
8359       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8360
8361       if (SPEC_OCLS(etype)->codesp ) {
8362         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8363         //p_type = CPOINTER ;
8364       } else
8365       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
8366         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8367         /*p_type = FPOINTER ;*/
8368       } else
8369       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
8370         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8371         /* p_type = PPOINTER; */
8372       } else
8373       if (SPEC_OCLS(etype) == idata ) {
8374         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8375         /* p_type = IPOINTER; */
8376       } else {
8377         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8378         /* p_type = POINTER ; */
8379       }
8380     }
8381
8382     /* now that we have the pointer type we assign
8383     the pointer values */
8384     switch (p_type) {
8385       case POINTER:
8386       case FPOINTER:
8387       case IPOINTER:
8388         genNearPointerGet (left,result,ic);
8389         break;
8390
8391 #if 0
8392       /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8393       case PPOINTER:
8394         genPagedPointerGet(left,result,ic);
8395         break;
8396
8397       case FPOINTER:
8398         genFarPointerGet (left,result,ic);
8399         break;
8400 #endif
8401
8402       case CPOINTER:
8403         genConstPointerGet (left,result,ic);
8404         //pic16_emitcodePointerGet (left,result,ic);
8405         break;
8406
8407       case GPOINTER:
8408 #if 0
8409       if (IS_PTR_CONST(type))
8410         genConstPointerGet (left,result,ic);
8411       else
8412 #endif
8413         genGenPointerGet (left,result,ic);
8414       break;
8415
8416     default:
8417       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8418               "genPointerGet: illegal pointer type");
8419
8420     }
8421 }
8422
8423 /*-----------------------------------------------------------------*/
8424 /* genPackBits - generates code for packed bit storage             */
8425 /*-----------------------------------------------------------------*/
8426 static void genPackBits (sym_link    *etype , operand *result,
8427                          operand *right ,
8428                          char *rname, int p_type)
8429 {
8430   int shCnt = 0 ;
8431   int offset = 0  ;
8432   int rLen = 0 ;
8433   int blen, bstr ;
8434   int shifted_and_masked = 0;
8435   unsigned long lit = (unsigned long)-1;
8436   sym_link *retype;
8437
8438   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8439   blen = SPEC_BLEN(etype);
8440   bstr = SPEC_BSTR(etype);
8441
8442   retype = getSpec(operandType(right));
8443
8444   if(AOP_TYPE(right) == AOP_LIT) {
8445     lit = ulFromVal (AOP(right)->aopu.aop_lit);
8446
8447     if((blen == 1) && (bstr < 8)) {
8448       /* it is a single bit, so use the appropriate bit instructions */
8449
8450       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
8451
8452       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
8453         /* workaround to reduce the extra lfsr instruction */
8454         if(lit) {
8455           pic16_emitpcode(POC_BSF,
8456               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8457         } else {
8458           pic16_emitpcode(POC_BCF,
8459               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8460         }
8461       } else {
8462         if (PIC_IS_DATA_PTR(operandType(result))) {
8463           pic16_loadFSR0(result, 0);
8464           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8465               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8466         } else {
8467           /* get old value */
8468           pic16_derefPtr (result, p_type, 0, NULL);
8469           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8470               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8471           /* write back new value */
8472           pic16_derefPtr (result, p_type, 1, NULL);
8473         }
8474       }
8475
8476       return;
8477     }
8478     /* IORLW below is more efficient */
8479     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
8480     lit = (lit & ((1UL << blen) - 1)) << bstr;
8481     shifted_and_masked = 1;
8482     offset++;
8483   } else
8484     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
8485         && IS_BITFIELD(retype)
8486         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
8487         && (blen == 1)) {
8488       int rblen, rbstr;
8489
8490       rblen = SPEC_BLEN( retype );
8491       rbstr = SPEC_BSTR( retype );
8492
8493       if(IS_BITFIELD(etype)) {
8494         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
8495         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8496       } else {
8497         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
8498       }
8499
8500       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
8501
8502       if(IS_BITFIELD(etype)) {
8503         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8504       } else {
8505         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
8506       }
8507
8508       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
8509
8510       return;
8511     } else {
8512       /* move right to W */
8513       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
8514     }
8515
8516   /* if the bit length is less than or   */
8517   /* it exactly fits a byte then         */
8518   if((shCnt=SPEC_BSTR(etype))
8519       || SPEC_BLEN(etype) <= 8 )  {
8520     int fsr0_setup = 0;
8521
8522     if (blen != 8 || (bstr % 8) != 0) {
8523       // we need to combine the value with the old value
8524       if(!shifted_and_masked)
8525       {
8526         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
8527
8528         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
8529             SPEC_BSTR(etype), SPEC_BLEN(etype));
8530
8531         /* shift left acc, do NOT mask the result again */
8532         AccLsh(shCnt, 0);
8533
8534         /* using PRODH as a temporary register here */
8535         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
8536       }
8537
8538       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
8539         || IS_DIRECT(result)) {
8540         /* access symbol directly */
8541         pic16_mov2w (AOP(result), 0);
8542       } else {
8543         /* get old value */
8544         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
8545       }
8546 #if 1
8547       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8548             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
8549                             (unsigned char)(0xff >> (8-bstr))) ));
8550       if (!shifted_and_masked) {
8551         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8552       } else {
8553         /* We have the shifted and masked (literal) right value in `lit' */
8554         if (lit != 0)
8555           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
8556       }
8557     } else { // if (blen == 8 && (bstr % 8) == 0)
8558         if (shifted_and_masked) {
8559             // move right (literal) to WREG (only case where right is not yet in WREG)
8560             pic16_mov2w(AOP(right), (bstr / 8));
8561         }
8562     }
8563
8564     /* write new value back */
8565     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
8566         || IS_DIRECT(result)) {
8567       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
8568     } else {
8569       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
8570     }
8571 #endif
8572
8573     return;
8574   }
8575
8576
8577 #if 0
8578   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8579   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8580   exit(EXIT_FAILURE);
8581 #endif
8582
8583
8584   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
8585   rLen = SPEC_BLEN(etype)-8;
8586
8587   /* now generate for lengths greater than one byte */
8588   while (1) {
8589     rLen -= 8 ;
8590     if (rLen <= 0 ) {
8591       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
8592       break ;
8593     }
8594
8595     switch (p_type) {
8596       case POINTER:
8597         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
8598         break;
8599
8600         /*
8601            case FPOINTER:
8602            MOVA(l);
8603            pic16_emitcode("movx","@dptr,a");
8604            break;
8605
8606            case GPOINTER:
8607            MOVA(l);
8608            DEBUGpic16_emitcode(";lcall","__gptrput");
8609            break;
8610          */
8611       default:
8612         assert(0);
8613     }
8614
8615
8616     pic16_mov2w(AOP(right), offset++);
8617   }
8618
8619   /* last last was not complete */
8620   if (rLen)   {
8621     /* save the byte & read byte */
8622     switch (p_type) {
8623       case POINTER:
8624         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
8625         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8626         break;
8627
8628         /*
8629            case FPOINTER:
8630            pic16_emitcode ("mov","b,a");
8631            pic16_emitcode("movx","a,@dptr");
8632            break;
8633
8634            case GPOINTER:
8635            pic16_emitcode ("push","b");
8636            pic16_emitcode ("push","acc");
8637            pic16_emitcode ("lcall","__gptrget");
8638            pic16_emitcode ("pop","b");
8639            break;
8640          */
8641       default:
8642         assert(0);
8643     }
8644     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
8645     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
8646     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8647     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8648     //        pic16_emitcode ("orl","a,b");
8649   }
8650
8651   //    if (p_type == GPOINTER)
8652   //        pic16_emitcode("pop","b");
8653
8654   switch (p_type) {
8655
8656     case POINTER:
8657       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8658       //        pic16_emitcode("mov","@%s,a",rname);
8659       break;
8660       /*
8661          case FPOINTER:
8662          pic16_emitcode("movx","@dptr,a");
8663          break;
8664
8665          case GPOINTER:
8666          DEBUGpic16_emitcode(";lcall","__gptrput");
8667          break;
8668        */
8669     default:
8670       assert(0);
8671   }
8672
8673   //    pic16_freeAsmop(right, NULL, ic, TRUE);
8674 }
8675
8676 /*-----------------------------------------------------------------*/
8677 /* genDataPointerSet - remat pointer to data space                 */
8678 /*-----------------------------------------------------------------*/
8679 static void genDataPointerSet(operand *right,
8680                               operand *result,
8681                               iCode *ic)
8682 {
8683   int size, offset = 0, resoffset=0 ;
8684
8685     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8686     pic16_aopOp(right,ic,FALSE);
8687
8688     size = AOP_SIZE(right);
8689
8690 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8691
8692 #if 0
8693     if ( AOP_TYPE(result) == AOP_PCODE) {
8694       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8695               AOP(result)->aopu.pcop->name,
8696                 (AOP(result)->aopu.pcop->type == PO_DIR)?
8697               PCOR(AOP(result)->aopu.pcop)->instance:
8698               PCOI(AOP(result)->aopu.pcop)->offset);
8699     }
8700 #endif
8701
8702     if(AOP(result)->aopu.pcop->type == PO_DIR)
8703       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
8704
8705     while (size--) {
8706       if (AOP_TYPE(right) == AOP_LIT) {
8707         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
8708         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
8709       } else {
8710         pic16_mov2w(AOP(right), offset);
8711         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
8712       }
8713       offset++;
8714       resoffset++;
8715     }
8716
8717     pic16_freeAsmop(right,NULL,ic,TRUE);
8718 }
8719
8720
8721
8722 /*-----------------------------------------------------------------*/
8723 /* genNearPointerSet - pic16_emitcode for near pointer put         */
8724 /*-----------------------------------------------------------------*/
8725 static void genNearPointerSet (operand *right,
8726                                operand *result,
8727                                iCode *ic)
8728 {
8729   asmop *aop = NULL;
8730   sym_link *retype;
8731   sym_link *ptype = operandType(result);
8732   sym_link *resetype;
8733
8734     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8735     retype= getSpec(operandType(right));
8736     resetype = getSpec(operandType(result));
8737
8738     pic16_aopOp(result,ic,FALSE);
8739
8740     /* if the result is rematerializable &
8741      * in data space & not a bit variable */
8742
8743     /* and result is not a bit variable */
8744     if (AOP_TYPE(result) == AOP_PCODE
8745       && DCL_TYPE(ptype) == POINTER
8746       && !IS_BITFIELD(retype)
8747       && !IS_BITFIELD(resetype)) {
8748
8749         genDataPointerSet (right,result,ic);
8750         pic16_freeAsmop(result,NULL,ic,TRUE);
8751       return;
8752     }
8753
8754     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8755     pic16_aopOp(right,ic,FALSE);
8756     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8757
8758     /* if bitfield then unpack the bits */
8759     if (IS_BITFIELD(resetype)) {
8760       genPackBits (resetype, result, right, NULL, POINTER);
8761     } else {
8762       /* we have can just get the values */
8763       int size = AOP_SIZE(right);
8764       int offset = 0 ;
8765
8766         pic16_loadFSR0(result, 0);
8767
8768         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8769         while (size--) {
8770           if (pic16_isLitOp(right)) {
8771             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
8772             if (size) {
8773               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
8774             } else {
8775               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
8776             }
8777           } else { // no literal
8778             if(size) {
8779               pic16_emitpcode(POC_MOVFF,
8780                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
8781                   pic16_popCopyReg(&pic16_pc_postinc0)));
8782             } else {
8783               pic16_emitpcode(POC_MOVFF,
8784                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
8785                   pic16_popCopyReg(&pic16_pc_indf0)));
8786             }
8787           }
8788
8789           offset++;
8790         }
8791     }
8792
8793     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8794     /* now some housekeeping stuff */
8795     if (aop) {
8796       /* we had to allocate for this iCode */
8797       pic16_freeAsmop(NULL,aop,ic,TRUE);
8798     } else {
8799       /* we did not allocate which means left
8800        * already in a pointer register, then
8801        * if size > 0 && this could be used again
8802        * we have to point it back to where it
8803        * belongs */
8804       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8805       if (AOP_SIZE(right) > 1
8806         && !OP_SYMBOL(result)->remat
8807         && ( OP_SYMBOL(result)->liveTo > ic->seq
8808         || ic->depth )) {
8809
8810           int size = AOP_SIZE(right) - 1;
8811
8812             while (size--)
8813               pic16_emitcode("decf","fsr0,f");
8814               //pic16_emitcode("dec","%s",rname);
8815       }
8816     }
8817
8818     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8819     /* done */
8820 //release:
8821     pic16_freeAsmop(right,NULL,ic,TRUE);
8822     pic16_freeAsmop(result,NULL,ic,TRUE);
8823 }
8824
8825 /*-----------------------------------------------------------------*/
8826 /* genGenPointerSet - set value from generic pointer space         */
8827 /*-----------------------------------------------------------------*/
8828 static void genGenPointerSet (operand *right,
8829                               operand *result, iCode *ic)
8830 {
8831   int size;
8832   sym_link *retype = getSpec(operandType(result));
8833
8834     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8835
8836     pic16_aopOp(result,ic,FALSE);
8837     pic16_aopOp(right,ic,FALSE);
8838     size = AOP_SIZE(right);
8839
8840     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8841
8842
8843     /* if bit then unpack */
8844     if (IS_BITFIELD(retype)) {
8845 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8846       genPackBits(retype,result,right,"dptr",GPOINTER);
8847       goto release;
8848     }
8849
8850     size = AOP_SIZE(right);
8851
8852     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
8853
8854
8855     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
8856
8857     /* value of right+0 is placed on stack, which will be retrieved
8858      * by the support function thus restoring the stack. The important
8859      * thing is that there is no need to manually restore stack pointer
8860      * here */
8861     pushaop(AOP(right), 0);
8862 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
8863     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
8864     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
8865     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
8866
8867     /* load address to write to in WREG:FSR0H:FSR0L */
8868     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
8869                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
8870     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
8871                                 pic16_popCopyReg(&pic16_pc_prodl)));
8872     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
8873
8874     pic16_callGenericPointerRW(1, size);
8875
8876 release:
8877     pic16_freeAsmop(right,NULL,ic,TRUE);
8878     pic16_freeAsmop(result,NULL,ic,TRUE);
8879 }
8880
8881 /*-----------------------------------------------------------------*/
8882 /* genPointerSet - stores the value into a pointer location        */
8883 /*-----------------------------------------------------------------*/
8884 static void genPointerSet (iCode *ic)
8885 {
8886   operand *right, *result ;
8887   sym_link *type, *etype;
8888   int p_type;
8889
8890     FENTRY;
8891
8892     right = IC_RIGHT(ic);
8893     result = IC_RESULT(ic) ;
8894
8895     /* depending on the type of pointer we need to
8896     move it to the correct pointer register */
8897     type = operandType(result);
8898     etype = getSpec(type);
8899
8900     /* if left is of type of pointer then it is simple */
8901     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8902         p_type = DCL_TYPE(type);
8903     }
8904     else {
8905         /* we have to go by the storage class */
8906         p_type = PTR_TYPE(SPEC_OCLS(etype));
8907
8908 /*      if (SPEC_OCLS(etype)->codesp ) { */
8909 /*          p_type = CPOINTER ;  */
8910 /*      } */
8911 /*      else */
8912 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8913 /*              p_type = FPOINTER ; */
8914 /*          else */
8915 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8916 /*                  p_type = PPOINTER ; */
8917 /*              else */
8918 /*                  if (SPEC_OCLS(etype) == idata ) */
8919 /*                      p_type = IPOINTER ; */
8920 /*                  else */
8921 /*                      p_type = POINTER ; */
8922     }
8923
8924     /* now that we have the pointer type we assign
8925     the pointer values */
8926     switch (p_type) {
8927       case POINTER:
8928       case FPOINTER:
8929       case IPOINTER:
8930         genNearPointerSet (right,result,ic);
8931         break;
8932
8933 #if 0
8934       /* MUST move them somewhere; handle [PF]POINTERs like POINTERS or like GPOINTERs?!? */
8935       case PPOINTER:
8936         genPagedPointerSet (right,result,ic);
8937         break;
8938
8939       case FPOINTER:
8940         genFarPointerSet (right,result,ic);
8941         break;
8942 #endif
8943
8944       case GPOINTER:
8945         genGenPointerSet (right,result,ic);
8946         break;
8947
8948       default:
8949         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8950           "genPointerSet: illegal pointer type");
8951     }
8952 }
8953
8954 /*-----------------------------------------------------------------*/
8955 /* genIfx - generate code for Ifx statement                        */
8956 /*-----------------------------------------------------------------*/
8957 static void genIfx (iCode *ic, iCode *popIc)
8958 {
8959   operand *cond = IC_COND(ic);
8960   int isbit =0;
8961
8962     FENTRY;
8963
8964     pic16_aopOp(cond,ic,FALSE);
8965
8966     /* get the value into acc */
8967     if (AOP_TYPE(cond) != AOP_CRY)
8968       pic16_toBoolean(cond);
8969     else
8970       isbit = 1;
8971     /* the result is now in the accumulator */
8972     pic16_freeAsmop(cond,NULL,ic,TRUE);
8973
8974     /* if there was something to be popped then do it */
8975     if (popIc)
8976       genIpop(popIc);
8977
8978     /* if the condition is  a bit variable */
8979     if (isbit && IS_ITEMP(cond) &&
8980         SPIL_LOC(cond)) {
8981       genIfxJump(ic,"c");
8982       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8983     } else {
8984       if (isbit && !IS_ITEMP(cond))
8985         genIfxJump(ic,OP_SYMBOL(cond)->rname);
8986         else
8987         genIfxJump(ic,"a");
8988     }
8989     ic->generated = 1;
8990 }
8991
8992 /*-----------------------------------------------------------------*/
8993 /* genAddrOf - generates code for address of                       */
8994 /*-----------------------------------------------------------------*/
8995 static void genAddrOf (iCode *ic)
8996 {
8997   operand *result, *left;
8998   int size;
8999   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9000   pCodeOp *pcop0, *pcop1, *pcop2;
9001
9002     FENTRY;
9003
9004     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9005
9006     sym = OP_SYMBOL( IC_LEFT(ic) );
9007
9008     if(sym->onStack) {
9009       /* get address of symbol on stack */
9010       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
9011 #if 0
9012       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
9013                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
9014 #endif
9015
9016       // operands on stack are accessible via "FSR2 + index" with index
9017       // starting at 2 for arguments and growing from 0 downwards for
9018       // local variables (index == 0 is not assigned so we add one here)
9019       {
9020         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
9021
9022           if (soffs <= 0) {
9023             assert (soffs < 0);
9024             soffs++;
9025           } // if
9026
9027           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
9028           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
9029           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
9030           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
9031           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
9032           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
9033           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
9034       }
9035
9036       goto release;
9037     }
9038
9039 //      if(pic16_debug_verbose) {
9040 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9041 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9042 //      }
9043
9044     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9045     size = AOP_SIZE(IC_RESULT(ic));
9046
9047     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9048     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9049     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9050
9051     if (size == 3) {
9052       pic16_emitpcode(POC_MOVLW, pcop0);
9053       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9054       pic16_emitpcode(POC_MOVLW, pcop1);
9055       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9056       pic16_emitpcode(POC_MOVLW, pcop2);
9057       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9058     } else
9059     if (size == 2) {
9060       pic16_emitpcode(POC_MOVLW, pcop0);
9061       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9062       pic16_emitpcode(POC_MOVLW, pcop1);
9063     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9064     } else {
9065       pic16_emitpcode(POC_MOVLW, pcop0);
9066       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9067     }
9068
9069     pic16_freeAsmop(left, NULL, ic, FALSE);
9070 release:
9071     pic16_freeAsmop(result,NULL,ic,TRUE);
9072 }
9073
9074
9075 /*-----------------------------------------------------------------*/
9076 /* genAssign - generate code for assignment                        */
9077 /*-----------------------------------------------------------------*/
9078 static void genAssign (iCode *ic)
9079 {
9080   operand *result, *right;
9081   sym_link *restype, *rtype;
9082   int size, offset,know_W;
9083   unsigned long lit = 0L;
9084
9085     result = IC_RESULT(ic);
9086     right  = IC_RIGHT(ic) ;
9087
9088     FENTRY;
9089
9090     /* if they are the same */
9091     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9092       return ;
9093
9094     /* reversed order operands are aopOp'ed so that result operand
9095      * is effective in case right is a stack symbol. This maneauver
9096      * allows to use the _G.resDirect flag later */
9097      pic16_aopOp(result,ic,TRUE);
9098     pic16_aopOp(right,ic,FALSE);
9099
9100     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9101
9102     /* if they are the same registers */
9103     if (pic16_sameRegs(AOP(right),AOP(result)))
9104       goto release;
9105
9106     /* if the result is a bit */
9107     if (AOP_TYPE(result) == AOP_CRY) {
9108       /* if the right size is a literal then
9109          we know what the value is */
9110       if (AOP_TYPE(right) == AOP_LIT) {
9111
9112         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9113             pic16_popGet(AOP(result),0));
9114
9115         if (((int) operandLitValue(right)))
9116           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9117               AOP(result)->aopu.aop_dir,
9118               AOP(result)->aopu.aop_dir);
9119         else
9120           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9121               AOP(result)->aopu.aop_dir,
9122               AOP(result)->aopu.aop_dir);
9123
9124         goto release;
9125       }
9126
9127       /* the right is also a bit variable */
9128       if (AOP_TYPE(right) == AOP_CRY) {
9129         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9130         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9131         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9132
9133         goto release ;
9134       }
9135
9136       /* we need to or */
9137       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9138       pic16_toBoolean(right);
9139       emitSKPZ;
9140       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9141       //pic16_aopPut(AOP(result),"a",0);
9142       goto release ;
9143     }
9144
9145     /* bit variables done */
9146     /* general case */
9147     size = AOP_SIZE(result);
9148     offset = 0 ;
9149
9150   /* bit variables done */
9151   /* general case */
9152   size = AOP_SIZE(result);
9153   restype = operandType(result);
9154   rtype = operandType(right);
9155   offset = 0 ;
9156
9157   if(AOP_TYPE(right) == AOP_LIT) {
9158     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
9159     {
9160       lit = ulFromVal (AOP(right)->aopu.aop_lit);
9161
9162       /* patch tag for literals that are cast to pointers */
9163       if (IS_CODEPTR(restype)) {
9164         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
9165         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9166       } else {
9167         if (IS_GENPTR(restype))
9168         {
9169           if (IS_CODEPTR(rtype)) {
9170             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
9171             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9172           } else if (PIC_IS_DATA_PTR(rtype)) {
9173             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
9174             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9175           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
9176             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
9177           } else if (IS_PTR(rtype)) {
9178             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
9179             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9180           }
9181         }
9182       }
9183     } else {
9184       union {
9185         unsigned long lit_int;
9186         float lit_float;
9187       } info;
9188
9189
9190       if(IS_FIXED16X16(operandType(right))) {
9191         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
9192       } else {
9193         /* take care if literal is a float */
9194         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
9195         lit = info.lit_int;
9196       }
9197     }
9198   }
9199
9200 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
9201 //                      sizeof(unsigned long int), sizeof(float));
9202
9203
9204     if (AOP_TYPE(right) == AOP_REG) {
9205       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
9206       while (size--) {
9207         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
9208       } // while
9209       goto release;
9210     }
9211
9212     /* when do we have to read the program memory?
9213      * - if right itself is a symbol in code space
9214      *   (we don't care what it points to if it's a pointer)
9215      * - AND right is not a function (we would want its address)
9216      */
9217     if(AOP_TYPE(right) != AOP_LIT
9218       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
9219       && !IS_FUNC(OP_SYM_TYPE(right))
9220       && !IS_ITEMP(right)) {
9221
9222       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
9223       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
9224
9225       // set up table pointer
9226       if(pic16_isLitOp(right)) {
9227 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
9228         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
9229         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9230         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
9231         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9232         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
9233         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9234       } else {
9235 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
9236         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
9237             pic16_popCopyReg(&pic16_pc_tblptrl)));
9238         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
9239             pic16_popCopyReg(&pic16_pc_tblptrh)));
9240         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
9241             pic16_popCopyReg(&pic16_pc_tblptru)));
9242       }
9243
9244       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
9245       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
9246       while(size--) {
9247         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9248         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
9249             pic16_popGet(AOP(result),offset)));
9250         offset++;
9251       }
9252
9253       /* FIXME: for pointers we need to extend differently (according
9254        * to pointer type DATA/CODE/EEPROM/... :*/
9255       size = getSize(OP_SYM_TYPE(right));
9256       if(AOP_SIZE(result) > size) {
9257         size = AOP_SIZE(result) - size;
9258         while(size--) {
9259           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
9260           offset++;
9261         }
9262       }
9263       goto release;
9264     }
9265
9266 #if 0
9267     /* VR - What is this?! */
9268     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9269       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9270
9271       if(aopIdx(AOP(result),0) == 4) {
9272         /* this is a workaround to save value of right into wreg too,
9273          * value of wreg is going to be used later */
9274         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9275         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9276         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9277         goto release;
9278       } else
9279 //      assert(0);
9280       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9281     }
9282 #endif
9283
9284     size = AOP_SIZE(right);
9285     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
9286     know_W=-1;
9287     while (size--) {
9288       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
9289       if(AOP_TYPE(right) == AOP_LIT) {
9290         if(lit&0xff) {
9291           if(know_W != (lit&0xff))
9292             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9293           know_W = lit&0xff;
9294           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9295         } else
9296           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9297
9298         lit >>= 8;
9299
9300       } else if (AOP_TYPE(right) == AOP_CRY) {
9301         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9302         if(offset == 0) {
9303           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
9304           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9305           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9306         }
9307       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
9308         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9309         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9310       } else {
9311         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9312
9313         if(!_G.resDirect) {                                             /* use this aopForSym feature */
9314           if(AOP_TYPE(result) == AOP_ACC) {
9315             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
9316           } else
9317             if(AOP_TYPE(right) == AOP_ACC) {
9318               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9319             } else {
9320               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9321             }
9322         }
9323       }
9324
9325       offset++;
9326     }
9327     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
9328
9329 release:
9330   pic16_freeAsmop (right,NULL,ic,FALSE);
9331   pic16_freeAsmop (result,NULL,ic,TRUE);
9332 }
9333
9334 /*-----------------------------------------------------------------*/
9335 /* genJumpTab - generates code for jump table                       */
9336 /*-----------------------------------------------------------------*/
9337 static void genJumpTab (iCode *ic)
9338 {
9339   symbol *jtab;
9340   char *l;
9341   pCodeOp *jt_offs;
9342   pCodeOp *jt_offs_hi;
9343   pCodeOp *jt_label;
9344
9345     FENTRY;
9346
9347     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9348     /* get the condition into accumulator */
9349     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9350     MOVA(l);
9351     /* multiply by three */
9352     pic16_emitcode("add","a,acc");
9353     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9354
9355     jtab = newiTempLabel(NULL);
9356     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9357     pic16_emitcode("jmp","@a+dptr");
9358     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9359
9360 #if 0
9361     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9362     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9363     emitSKPNC;
9364     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9365     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9366     pic16_emitpLabel(jtab->key);
9367
9368 #else
9369
9370     jt_offs = pic16_popGetTempReg(0);
9371     jt_offs_hi = pic16_popGetTempReg(1);
9372     jt_label = pic16_popGetLabel (jtab->key);
9373     //fprintf (stderr, "Creating jump table...\n");
9374
9375     // calculate offset into jump table (idx * sizeof (GOTO))
9376     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
9377     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
9378     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
9379     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
9380     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
9381     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
9382     pic16_emitpcode(POC_MOVWF , jt_offs);
9383
9384     // prepare PCLATx (set to first entry in jump table)
9385     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
9386     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
9387     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
9388     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
9389     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
9390
9391     // set PCLATx to selected entry (new PCL is stored in jt_offs)
9392     pic16_emitpcode(POC_ADDWF , jt_offs);
9393     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
9394     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
9395     emitSKPNC;
9396     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
9397
9398     // release temporaries and prepare jump into table (new PCL --> WREG)
9399     pic16_emitpcode(POC_MOVFW , jt_offs);
9400     pic16_popReleaseTempReg (jt_offs_hi, 1);
9401     pic16_popReleaseTempReg (jt_offs, 0);
9402
9403     // jump into the table
9404     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
9405
9406     pic16_emitpLabelFORCE(jtab->key);
9407 #endif
9408
9409     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9410 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
9411
9412     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
9413     /* now generate the jump labels */
9414     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9415          jtab = setNextItem(IC_JTLABELS(ic))) {
9416 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9417         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9418
9419     }
9420     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
9421
9422 }
9423
9424 /*-----------------------------------------------------------------*/
9425 /* genMixedOperation - gen code for operators between mixed types  */
9426 /*-----------------------------------------------------------------*/
9427 /*
9428   TSD - Written for the PIC port - but this unfortunately is buggy.
9429   This routine is good in that it is able to efficiently promote
9430   types to different (larger) sizes. Unfortunately, the temporary
9431   variables that are optimized out by this routine are sometimes
9432   used in other places. So until I know how to really parse the
9433   iCode tree, I'm going to not be using this routine :(.
9434 */
9435 static int genMixedOperation (iCode *ic)
9436 {
9437 #if 0
9438   operand *result = IC_RESULT(ic);
9439   sym_link *ctype = operandType(IC_LEFT(ic));
9440   operand *right = IC_RIGHT(ic);
9441   int ret = 0;
9442   int big,small;
9443   int offset;
9444
9445   iCode *nextic;
9446   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9447
9448   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9449
9450   nextic = ic->next;
9451   if(!nextic)
9452     return 0;
9453
9454   nextright = IC_RIGHT(nextic);
9455   nextleft  = IC_LEFT(nextic);
9456   nextresult = IC_RESULT(nextic);
9457
9458   pic16_aopOp(right,ic,FALSE);
9459   pic16_aopOp(result,ic,FALSE);
9460   pic16_aopOp(nextright,  nextic, FALSE);
9461   pic16_aopOp(nextleft,   nextic, FALSE);
9462   pic16_aopOp(nextresult, nextic, FALSE);
9463
9464   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9465
9466     operand *t = right;
9467     right = nextright;
9468     nextright = t;
9469
9470     pic16_emitcode(";remove right +","");
9471
9472   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9473 /*
9474     operand *t = right;
9475     right = nextleft;
9476     nextleft = t;
9477 */
9478     pic16_emitcode(";remove left +","");
9479   } else
9480     return 0;
9481
9482   big = AOP_SIZE(nextleft);
9483   small = AOP_SIZE(nextright);
9484
9485   switch(nextic->op) {
9486
9487   case '+':
9488     pic16_emitcode(";optimize a +","");
9489     /* if unsigned or not an integral type */
9490     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9491       pic16_emitcode(";add a bit to something","");
9492     } else {
9493
9494       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9495
9496       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9497         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9498         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9499       } else
9500         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9501
9502       offset = 0;
9503       while(--big) {
9504
9505         offset++;
9506
9507         if(--small) {
9508           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9509             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9510             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9511           }
9512
9513           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9514           emitSKPNC;
9515           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9516                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9517                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9518           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9519           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9520
9521         } else {
9522           pic16_emitcode("rlf","known_zero,w");
9523
9524           /*
9525             if right is signed
9526               btfsc  right,7
9527                addlw ff
9528           */
9529           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9530             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9531             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9532           } else {
9533             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9534           }
9535         }
9536       }
9537       ret = 1;
9538     }
9539   }
9540   ret = 1;
9541
9542 release:
9543   pic16_freeAsmop(right,NULL,ic,TRUE);
9544   pic16_freeAsmop(result,NULL,ic,TRUE);
9545   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9546   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9547   if(ret)
9548     nextic->generated = 1;
9549
9550   return ret;
9551 #else
9552   return 0;
9553 #endif
9554 }
9555 /*-----------------------------------------------------------------*/
9556 /* genCast - gen code for casting                                  */
9557 /*-----------------------------------------------------------------*/
9558 static void genCast (iCode *ic)
9559 {
9560   operand *result = IC_RESULT(ic);
9561   sym_link *ctype = operandType(IC_LEFT(ic));
9562   sym_link *rtype = operandType(IC_RIGHT(ic));
9563   sym_link *restype = operandType(IC_RESULT(ic));
9564   operand *right = IC_RIGHT(ic);
9565   int size, offset ;
9566
9567
9568     FENTRY;
9569
9570         /* if they are equivalent then do nothing */
9571 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9572 //              return ;
9573
9574         pic16_aopOp(result,ic,FALSE);
9575         pic16_aopOp(right,ic,FALSE) ;
9576
9577         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9578
9579
9580         /* if the result is a bit */
9581         if (AOP_TYPE(result) == AOP_CRY) {
9582
9583                 /* if the right size is a literal then
9584                  * we know what the value is */
9585                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9586
9587                 if (AOP_TYPE(right) == AOP_LIT) {
9588                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9589                                 pic16_popGet(AOP(result),0));
9590
9591                         if (((int) operandLitValue(right)))
9592                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9593                                         AOP(result)->aopu.aop_dir,
9594                                         AOP(result)->aopu.aop_dir);
9595                         else
9596                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9597                                         AOP(result)->aopu.aop_dir,
9598                                         AOP(result)->aopu.aop_dir);
9599                         goto release;
9600                 }
9601
9602                 /* the right is also a bit variable */
9603                 if (AOP_TYPE(right) == AOP_CRY) {
9604                         emitCLRC;
9605                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9606
9607                         pic16_emitcode("clrc","");
9608                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9609                                 AOP(right)->aopu.aop_dir,
9610                                 AOP(right)->aopu.aop_dir);
9611                         pic16_aopPut(AOP(result),"c",0);
9612                         goto release ;
9613                 }
9614
9615                 /* we need to or */
9616                 if (AOP_TYPE(right) == AOP_REG) {
9617                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9618                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9619                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9620                 }
9621                 pic16_toBoolean(right);
9622                 pic16_aopPut(AOP(result),"a",0);
9623                 goto release ;
9624         }
9625
9626         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9627           int offset = 1;
9628
9629                 size = AOP_SIZE(result);
9630
9631                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9632
9633                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9634                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9635                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9636
9637                 while (size--)
9638                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9639
9640                 goto release;
9641         }
9642
9643         if(IS_BITFIELD(getSpec(restype))
9644           && IS_BITFIELD(getSpec(rtype))) {
9645           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
9646         }
9647
9648         /* port from pic14 to cope with generic pointers */
9649         if (PIC_IS_TAGGED(restype))
9650         {
9651           operand *result = IC_RESULT(ic);
9652           //operand *left = IC_LEFT(ic);
9653           operand *right = IC_RIGHT(ic);
9654           int tag = 0xff;
9655
9656           /* copy common part */
9657           int max, size = AOP_SIZE(result);
9658           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
9659           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9660
9661           max = size;
9662           while (size--)
9663           {
9664             pic16_mov2w (AOP(right), size);
9665             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
9666           } // while
9667
9668           /* upcast into generic pointer type? */
9669           if (IS_GENPTR(restype)
9670               && !PIC_IS_TAGGED(rtype)
9671               && (AOP_SIZE(result) > max))
9672           {
9673             /* determine appropriate tag for right */
9674             if (PIC_IS_DATA_PTR(rtype))
9675               tag = GPTR_TAG_DATA;
9676             else if (IS_CODEPTR(rtype))
9677               tag = GPTR_TAG_CODE;
9678             else if (PIC_IS_DATA_PTR(ctype)) {
9679               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
9680               tag = GPTR_TAG_DATA;
9681             } else if (IS_CODEPTR(ctype)) {
9682               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
9683               tag = GPTR_TAG_CODE;
9684             } else if (IS_PTR(rtype)) {
9685               PERFORM_ONCE(weirdcast,
9686               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
9687               );
9688               tag = GPTR_TAG_DATA;
9689             } else {
9690               PERFORM_ONCE(weirdcast,
9691               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
9692               );
9693               tag = GPTR_TAG_DATA;
9694             }
9695
9696             assert (AOP_SIZE(result) == 3);
9697             /* zero-extend address... */
9698             for (size = max; size < AOP_SIZE(result)-1; size++)
9699               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
9700             /* ...and add tag */
9701             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
9702           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
9703             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
9704             for (size = max; size < AOP_SIZE(result)-1; size++)
9705               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
9706             /* add __code tag */
9707             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
9708           } else if (AOP_SIZE(result) > max) {
9709             /* extend non-pointers */
9710             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
9711             pic16_addSign(result, max, 0);
9712           } // if
9713           goto release;
9714         }
9715
9716         /* if they are the same size : or less */
9717         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9718
9719                 /* if they are in the same place */
9720                 if (pic16_sameRegs(AOP(right),AOP(result)))
9721                         goto release;
9722
9723                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9724 #if 0
9725                 if (IS_PTR_CONST(rtype))
9726 #else
9727                 if (IS_CODEPTR(rtype))
9728 #endif
9729                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9730
9731 #if 0
9732                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9733 #else
9734                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9735 #endif
9736                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9737
9738                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9739                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9740                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9741
9742                         if(AOP_SIZE(result) < 2) {
9743                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
9744                         } else {
9745                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9746                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9747                         }
9748                 } else {
9749                         /* if they in different places then copy */
9750                         size = AOP_SIZE(result);
9751                         offset = 0 ;
9752                         while (size--) {
9753                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9754                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9755                                 offset++;
9756                         }
9757                 }
9758                 goto release;
9759         }
9760
9761         /* if the result is of type pointer */
9762         if (IS_PTR(ctype)) {
9763           int p_type;
9764           sym_link *type = operandType(right);
9765           sym_link *etype = getSpec(type);
9766
9767                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9768
9769                 /* pointer to generic pointer */
9770                 if (IS_GENPTR(ctype)) {
9771                   char *l = zero;
9772
9773                         if (IS_PTR(type))
9774                                 p_type = DCL_TYPE(type);
9775                         else {
9776                 /* we have to go by the storage class */
9777                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9778
9779 /*              if (SPEC_OCLS(etype)->codesp )  */
9780 /*                  p_type = CPOINTER ;  */
9781 /*              else */
9782 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9783 /*                      p_type = FPOINTER ; */
9784 /*                  else */
9785 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9786 /*                          p_type = PPOINTER; */
9787 /*                      else */
9788 /*                          if (SPEC_OCLS(etype) == idata ) */
9789 /*                              p_type = IPOINTER ; */
9790 /*                          else */
9791 /*                              p_type = POINTER ; */
9792             }
9793
9794             /* the first two bytes are known */
9795       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9796             size = GPTRSIZE - 1;
9797             offset = 0 ;
9798             while (size--) {
9799               if(offset < AOP_SIZE(right)) {
9800                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
9801                 pic16_mov2f(AOP(result), AOP(right), offset);
9802 /*
9803                 if ((AOP_TYPE(right) == AOP_PCODE) &&
9804                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9805                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9806                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9807                 } else {
9808
9809                   pic16_aopPut(AOP(result),
9810                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9811                          offset);
9812                 }
9813 */
9814               } else
9815                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9816               offset++;
9817             }
9818             /* the last byte depending on type */
9819             switch (p_type) {
9820             case IPOINTER:
9821             case POINTER:
9822             case FPOINTER:
9823                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9824                 break;
9825
9826             case CPOINTER:
9827                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9828                 break;
9829
9830             case PPOINTER:
9831               pic16_emitcode(";BUG!? ","%d",__LINE__);
9832                 l = "#0x03";
9833                 break;
9834
9835             case GPOINTER:
9836                 if (GPTRSIZE > AOP_SIZE(right)) {
9837                   // assume __data pointer... THIS MIGHT BE WRONG!
9838                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9839                 } else {
9840                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9841                 }
9842               break;
9843
9844             default:
9845                 /* this should never happen */
9846                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9847                        "got unknown pointer type");
9848                 exit(1);
9849             }
9850             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
9851             goto release ;
9852         }
9853
9854
9855         assert( 0 );
9856         /* just copy the pointers */
9857         size = AOP_SIZE(result);
9858         offset = 0 ;
9859         while (size--) {
9860             pic16_aopPut(AOP(result),
9861                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9862                    offset);
9863             offset++;
9864         }
9865         goto release ;
9866     }
9867
9868
9869
9870     /* so we now know that the size of destination is greater
9871     than the size of the source.
9872     Now, if the next iCode is an operator then we might be
9873     able to optimize the operation without performing a cast.
9874     */
9875     if(genMixedOperation(ic))
9876       goto release;
9877
9878     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9879
9880     /* we move to result for the size of source */
9881     size = AOP_SIZE(right);
9882     offset = 0 ;
9883
9884     while (size--) {
9885       if(!_G.resDirect)
9886         pic16_mov2f(AOP(result), AOP(right), offset);
9887       offset++;
9888     }
9889
9890     /* now depending on the sign of the destination */
9891     size = AOP_SIZE(result) - AOP_SIZE(right);
9892     /* if unsigned or not an integral type */
9893     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
9894       while (size--)
9895         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9896     } else {
9897       /* we need to extend the sign :( */
9898
9899       if(size == 1) {
9900         /* Save one instruction of casting char to int */
9901         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
9902         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9903         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
9904       } else {
9905         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9906
9907         if(offset)
9908           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9909         else
9910           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9911
9912         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
9913
9914         while (size--)
9915           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
9916       }
9917     }
9918
9919 release:
9920     pic16_freeAsmop(right,NULL,ic,TRUE);
9921     pic16_freeAsmop(result,NULL,ic,TRUE);
9922
9923 }
9924
9925 /*-----------------------------------------------------------------*/
9926 /* genDjnz - generate decrement & jump if not zero instrucion      */
9927 /*-----------------------------------------------------------------*/
9928 static int genDjnz (iCode *ic, iCode *ifx)
9929 {
9930     symbol *lbl, *lbl1;
9931     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9932
9933     if (!ifx)
9934         return 0;
9935
9936     /* if the if condition has a false label
9937        then we cannot save */
9938     if (IC_FALSE(ifx))
9939         return 0;
9940
9941     /* if the minus is not of the form
9942        a = a - 1 */
9943     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9944         !IS_OP_LITERAL(IC_RIGHT(ic)))
9945         return 0;
9946
9947     if (operandLitValue(IC_RIGHT(ic)) != 1)
9948         return 0;
9949
9950     /* if the size of this greater than one then no
9951        saving */
9952     if (getSize(operandType(IC_RESULT(ic))) > 1)
9953         return 0;
9954
9955     /* otherwise we can save BIG */
9956     lbl = newiTempLabel(NULL);
9957     lbl1= newiTempLabel(NULL);
9958
9959     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9960
9961     pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9962     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9963
9964     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9965     ifx->generated = 1;
9966     return 1;
9967 }
9968
9969 /*-----------------------------------------------------------------*/
9970 /* genReceive - generate code for a receive iCode                  */
9971 /*-----------------------------------------------------------------*/
9972 static void genReceive (iCode *ic)
9973 {
9974
9975   FENTRY;
9976
9977 #if 0
9978   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
9979         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
9980 #endif
9981 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
9982
9983   if (isOperandInFarSpace(IC_RESULT(ic))
9984       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
9985           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9986
9987     int size = getSize(operandType(IC_RESULT(ic)));
9988     int offset =  pic16_fReturnSizePic - size;
9989
9990       assert( 0 );
9991       while (size--) {
9992         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
9993                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
9994                       offset++;
9995         }
9996
9997       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
9998
9999       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10000       size = AOP_SIZE(IC_RESULT(ic));
10001       offset = 0;
10002       while (size--) {
10003         pic16_emitcode ("pop","acc");
10004         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10005       }
10006   } else {
10007     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
10008     _G.accInUse++;
10009     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10010     _G.accInUse--;
10011
10012     /* set pseudo stack pointer to where it should be - dw*/
10013     GpsuedoStkPtr = ic->parmBytes;
10014
10015     /* setting GpsuedoStkPtr has side effects here: */
10016     /* FIXME: What's the correct size of the return(ed) value?
10017      *        For now, assuming '4' as before... */
10018     assignResultValue(IC_RESULT(ic), 4, 0);
10019   }
10020
10021   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10022 }
10023
10024 /*-----------------------------------------------------------------*/
10025 /* genDummyRead - generate code for dummy read of volatiles        */
10026 /*-----------------------------------------------------------------*/
10027 static void
10028 genDummyRead (iCode * ic)
10029 {
10030   operand *op;
10031
10032   op = IC_RIGHT(ic);
10033   if (op && IS_SYMOP(op)) {
10034     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
10035       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
10036       return;
10037     }
10038     pic16_aopOp (op, ic, FALSE);
10039     pic16_mov2w_volatile(AOP(op));
10040     pic16_freeAsmop (op, NULL, ic, TRUE);
10041   } else if (op) {
10042     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
10043   } // if
10044 }
10045
10046 /*-----------------------------------------------------------------*/
10047 /* genpic16Code - generate code for pic16 based controllers        */
10048 /*-----------------------------------------------------------------*/
10049 /*
10050  * At this point, ralloc.c has gone through the iCode and attempted
10051  * to optimize in a way suitable for a PIC. Now we've got to generate
10052  * PIC instructions that correspond to the iCode.
10053  *
10054  * Once the instructions are generated, we'll pass through both the
10055  * peep hole optimizer and the pCode optimizer.
10056  *-----------------------------------------------------------------*/
10057
10058 void genpic16Code (iCode *lic)
10059 {
10060   iCode *ic;
10061   int cln = 0;
10062
10063     lineHead = lineCurr = NULL;
10064
10065     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10066     pic16_addpBlock(pb);
10067
10068 #if 0
10069     /* if debug information required */
10070     if (options.debug && currFunc) {
10071       if (currFunc) {
10072         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10073       }
10074     }
10075 #endif
10076
10077     for (ic = lic ; ic ; ic = ic->next ) {
10078
10079       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
10080       if ( cln != ic->lineno ) {
10081         if ( options.debug ) {
10082           debugFile->writeCLine (ic);
10083         }
10084
10085         if(!options.noCcodeInAsm) {
10086           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
10087               printCLine(ic->filename, ic->lineno)));
10088         }
10089
10090         cln = ic->lineno ;
10091       }
10092
10093       if(options.iCodeInAsm) {
10094         const char *iLine;
10095
10096         /* insert here code to print iCode as comment */
10097         iLine = printILine(ic);
10098         pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
10099         dbuf_free(iLine);
10100       }
10101
10102       /* if the result is marked as
10103        * spilt and rematerializable or code for
10104        * this has already been generated then
10105        * do nothing */
10106       if (resultRemat(ic) || ic->generated )
10107         continue ;
10108
10109       /* depending on the operation */
10110       switch (ic->op) {
10111         case '!' :
10112           pic16_genNot(ic);
10113           break;
10114
10115         case '~' :
10116           pic16_genCpl(ic);
10117           break;
10118
10119         case UNARYMINUS:
10120           genUminus (ic);
10121           break;
10122
10123         case IPUSH:
10124           genIpush (ic);
10125           break;
10126
10127         case IPOP:
10128           /* IPOP happens only when trying to restore a
10129            * spilt live range, if there is an ifx statement
10130            * following this pop then the if statement might
10131            * be using some of the registers being popped which
10132            * would destroy the contents of the register so
10133            * we need to check for this condition and handle it */
10134            if (ic->next
10135              && ic->next->op == IFX
10136              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10137                genIfx (ic->next,ic);
10138           else
10139             genIpop (ic);
10140           break;
10141
10142         case CALL:
10143           genCall (ic);
10144           break;
10145
10146         case PCALL:
10147           genPcall (ic);
10148           break;
10149
10150         case FUNCTION:
10151           genFunction (ic);
10152           break;
10153
10154         case ENDFUNCTION:
10155           genEndFunction (ic);
10156           break;
10157
10158         case RETURN:
10159           genRet (ic);
10160           break;
10161
10162         case LABEL:
10163           genLabel (ic);
10164           break;
10165
10166         case GOTO:
10167           genGoto (ic);
10168           break;
10169
10170         case '+' :
10171           pic16_genPlus (ic) ;
10172           break;
10173
10174         case '-' :
10175           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10176             pic16_genMinus (ic);
10177           break;
10178
10179         case '*' :
10180           genMult (ic);
10181           break;
10182
10183         case '/' :
10184           genDiv (ic) ;
10185           break;
10186
10187         case '%' :
10188           genMod (ic);
10189           break;
10190
10191         case '>' :
10192           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10193           break;
10194
10195         case '<' :
10196           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10197           break;
10198
10199         case LE_OP:
10200         case GE_OP:
10201         case NE_OP:
10202           /* note these two are xlated by algebraic equivalence
10203            * during parsing SDCC.y */
10204           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10205             "got '>=' or '<=' shouldn't have come here");
10206           break;
10207
10208         case EQ_OP:
10209           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10210           break;
10211
10212         case AND_OP:
10213           genAndOp (ic);
10214           break;
10215
10216         case OR_OP:
10217           genOrOp (ic);
10218           break;
10219
10220         case '^' :
10221           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10222           break;
10223
10224         case '|' :
10225           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10226           break;
10227
10228         case BITWISEAND:
10229           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10230           break;
10231
10232         case INLINEASM:
10233           genInline (ic);
10234           break;
10235
10236         case RRC:
10237           genRRC (ic);
10238           break;
10239
10240         case RLC:
10241           genRLC (ic);
10242           break;
10243
10244         case GETHBIT:
10245           genGetHbit (ic);
10246           break;
10247
10248         case LEFT_OP:
10249           genLeftShift (ic);
10250           break;
10251
10252         case RIGHT_OP:
10253           genRightShift (ic);
10254           break;
10255
10256         case GET_VALUE_AT_ADDRESS:
10257           genPointerGet(ic);
10258           break;
10259
10260         case '=' :
10261           if (POINTER_SET(ic))
10262             genPointerSet(ic);
10263           else
10264             genAssign(ic);
10265           break;
10266
10267         case IFX:
10268           genIfx (ic,NULL);
10269           break;
10270
10271         case ADDRESS_OF:
10272           genAddrOf (ic);
10273           break;
10274
10275         case JUMPTABLE:
10276           genJumpTab (ic);
10277           break;
10278
10279         case CAST:
10280           genCast (ic);
10281           break;
10282
10283         case RECEIVE:
10284           genReceive(ic);
10285           break;
10286
10287         case SEND:
10288           addSet(&_G.sendSet,ic);
10289           break;
10290
10291         case DUMMY_READ_VOLATILE:
10292           genDummyRead (ic);
10293           break;
10294
10295         default :
10296           ic = ic;
10297       }
10298     }
10299
10300
10301     /* now we are ready to call the
10302        peep hole optimizer */
10303     if (!options.nopeep)
10304       peepHole (&lineHead);
10305
10306     /* now do the actual printing */
10307     printLine (lineHead, codeOutBuf);
10308
10309 #ifdef PCODE_DEBUG
10310     DFPRINTF((stderr,"printing pBlock\n\n"));
10311     pic16_printpBlock(stdout,pb);
10312 #endif
10313
10314     return;
10315 }