* src/pic16/gen.c (genNearPointerGet): fix double indirect
[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   Bug Fixes  -  Mauro Giachero <maurogiachero AT users.sourceforge.net> (2008)
13
14   This program is free software; you can redistribute it and/or modify it
15   under the terms of the GNU General Public License as published by the
16   Free Software Foundation; either version 2, or (at your option) any
17   later version.
18
19   This program is distributed in the hope that it will be useful,
20   but WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22   GNU General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, write to the Free Software
26   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27
28   In other words, you are welcome to use, share and improve this program.
29   You are forbidden to forbid anyone else to use, share and improve
30   what you give them.   Help stamp out software-hoarding!
31
32   Notes:
33   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
34                 Made everything static
35 -------------------------------------------------------------------------*/
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <ctype.h>
41 #include "SDCCglobl.h"
42 #include "newalloc.h"
43
44 #include "common.h"
45 #include "SDCCpeeph.h"
46 #include "ralloc.h"
47 #include "pcode.h"
48 #include "gen.h"
49 #include "genutils.h"
50 #include "device.h"
51 #include "main.h"
52 #include "glue.h"
53
54 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
55 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
56 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
57 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
58 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
59
60 /* Wrapper to execute `code' at most once. */
61 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
62
63 void pic16_genMult8X8_n (operand *, operand *,operand *);
64 extern void pic16_printpBlock(FILE *of, pBlock *pb);
65 static asmop *newAsmop (short type);
66 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
67 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
68 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
69 static pCodeOp *pic16_popRegFromIdx(int rIdx);
70
71 int pic16_labelOffset=0;
72 extern int pic16_debug_verbose;
73
74 extern set *externs;
75
76 /* max_key keeps track of the largest label number used in
77    a function. This is then used to adjust the label offset
78    for the next function.
79 */
80 static int max_key=0;
81 static int GpsuedoStkPtr=0;
82
83 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
84
85 const char *pic16_AopType(short type);
86 static iCode *ifxForOp ( operand *op, iCode *ic );
87
88 void pic16_pushpCodeOp(pCodeOp *pcop);
89 void pic16_poppCodeOp(pCodeOp *pcop);
90
91
92 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
93
94 /* set the following macro to 1 to enable passing the
95  * first byte of functions parameters via WREG */
96 #define USE_WREG_IN_FUNC_PARAMS 0
97
98
99 /* this is the down and dirty file with all kinds of
100    kludgy & hacky stuff. This is what it is all about
101    CODE GENERATION for a specific MCU . some of the
102    routines may be reusable, will have to see */
103 static char *zero = "#0x00";
104 static char *one  = "#0x01";
105
106
107 /*
108  * Function return value policy (MSB-->LSB):
109  *  8 bits      -> WREG
110  * 16 bits      -> PRODL:WREG
111  * 24 bits      -> PRODH:PRODL:WREG
112  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
113  * >32 bits     -> on stack, and FSR0 points to the beginning
114  */
115 char *fReturnpic16[] = { "WREG", "PRODL", "PRODH", "FSR0L" };
116 int fReturnIdx[] = { IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
117 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
118 static char **fReturn = fReturnpic16;
119
120 static char *accUse[] = {"WREG"};
121
122 static struct {
123     short accInUse;
124     short inLine;
125     short debugLine;
126     short nRegsSaved;
127     set *sendSet;
128     set *stackRegSet;
129     int usefastretfie;
130     bitVect *fregsUsed;                 /* registers used in function */
131     bitVect *sregsAlloc;
132     set *sregsAllocSet;                 /* registers used to store stack variables */
133     int stack_lat;                      /* stack offset latency */
134     int resDirect;
135     int useWreg;                        /* flag when WREG is used to pass function parameter */
136 } _G;
137
138 extern struct dbuf_s *codeOutBuf;
139
140 static lineNode *lineHead = NULL;
141 static lineNode *lineCurr = NULL;
142
143 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
144 0xE0, 0xC0, 0x80, 0x00};
145 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
146 0x07, 0x03, 0x01, 0x00};
147
148 static  pBlock *pb;
149
150 /*-----------------------------------------------------------------*/
151 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
152 /*                 exponent of 2 is returned, otherwise -1 is      */
153 /*                 returned.                                       */
154 /* note that this is similar to the function `powof2' in SDCCsymt  */
155 /* if(n == 2^y)                                                    */
156 /*   return y;                                                     */
157 /* return -1;                                                      */
158 /*-----------------------------------------------------------------*/
159 int pic16_my_powof2 (unsigned long num)
160 {
161   if(num) {
162     if( (num & (num-1)) == 0) {
163       int nshifts = -1;
164       while(num) {
165         num>>=1;
166         nshifts++;
167       }
168       return nshifts;
169     }
170   }
171
172   return -1;
173 }
174
175 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
176 {
177   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
178                        line_no,
179                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
180                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
181                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
182                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
183                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
184                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
185                        ((result) ? AOP_SIZE(result) : 0));
186 }
187
188 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
189 {
190
191   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
192                        line_no,
193                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
194                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
195                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
196                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
197                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
198                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
199
200 }
201
202 void pic16_emitpcomment (char *fmt, ...)
203 {
204     va_list ap;
205     char lb[INITIAL_INLINEASM];
206     unsigned char *lbp = (unsigned char *)lb;
207
208     va_start(ap,fmt);
209
210     lb[0] = ';';
211     vsprintf(lb+1,fmt,ap);
212
213     while (isspace(*lbp)) lbp++;
214
215     if (lbp && *lbp)
216         lineCurr = (lineCurr ?
217                     connectLine(lineCurr,newLineNode(lb)) :
218                     (lineHead = newLineNode(lb)));
219     lineCurr->isInline = _G.inLine;
220     lineCurr->isDebug  = _G.debugLine;
221     lineCurr->isComment = 1;
222
223     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
224     va_end(ap);
225
226 //      fprintf(stderr, "%s\n", lb);
227 }
228
229 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
230 {
231     va_list ap;
232     char lb[INITIAL_INLINEASM];
233     unsigned char *lbp = (unsigned char *)lb;
234
235     if(!pic16_debug_verbose)
236       return;
237
238     va_start(ap,fmt);
239
240     if (inst && *inst) {
241         if (fmt && *fmt)
242             sprintf(lb,"%s\t",inst);
243         else
244             sprintf(lb,"%s",inst);
245         vsprintf(lb+(strlen(lb)),fmt,ap);
246     }  else
247         vsprintf(lb,fmt,ap);
248
249     while (isspace(*lbp)) lbp++;
250
251     if (lbp && *lbp)
252         lineCurr = (lineCurr ?
253                     connectLine(lineCurr,newLineNode(lb)) :
254                     (lineHead = newLineNode(lb)));
255     lineCurr->isInline = _G.inLine;
256     lineCurr->isDebug  = _G.debugLine;
257
258     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
259     va_end(ap);
260
261 //      fprintf(stderr, "%s\n", lb);
262 }
263
264
265
266 void pic16_emitpLabel(int key)
267 {
268   if(key>max_key)
269     max_key = key;
270
271   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
272 }
273
274 void pic16_emitpLabelFORCE(int key)
275 {
276   if(key>max_key)
277     max_key = key;
278
279   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
280 }
281
282 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
283  * NEVER call pic16_emitpcode_real directly, please... */
284 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
285 {
286
287   if(pcop)
288     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
289   else
290     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
291 }
292
293 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
294 {
295   if(pcop)
296     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
297   else
298     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
299 }
300
301 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
302 {
303
304   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
305
306 }
307
308
309 #if 1
310 #define pic16_emitcode  DEBUGpic16_emitcode
311 #else
312 /*-----------------------------------------------------------------*/
313 /* pic16_emitcode - writes the code into a file : for now it is simple    */
314 /*-----------------------------------------------------------------*/
315 void pic16_emitcode (char *inst,char *fmt, ...)
316 {
317     va_list ap;
318     char lb[INITIAL_INLINEASM];
319     unsigned char *lbp = lb;
320
321     va_start(ap,fmt);
322
323     if (inst && *inst) {
324         if (fmt && *fmt)
325             sprintf(lb,"%s\t",inst);
326         else
327             sprintf(lb,"%s",inst);
328         vsprintf(lb+(strlen(lb)),fmt,ap);
329     }  else
330         vsprintf(lb,fmt,ap);
331
332     while (isspace(*lbp)) lbp++;
333
334     if (lbp && *lbp)
335         lineCurr = (lineCurr ?
336                     connectLine(lineCurr,newLineNode(lb)) :
337                     (lineHead = newLineNode(lb)));
338     lineCurr->isInline = _G.inLine;
339     lineCurr->isDebug  = _G.debugLine;
340     lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
341     lineCurr->isComment = (*lbp == ';');
342
343 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
344
345 //    if(pic16_debug_verbose)
346 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
347
348     va_end(ap);
349 }
350 #endif
351
352
353 /*-----------------------------------------------------------------*/
354 /* pic16_emitDebuggerSymbol - associate the current code location  */
355 /*   with a debugger symbol                                        */
356 /*-----------------------------------------------------------------*/
357 void
358 pic16_emitDebuggerSymbol (char * debugSym)
359 {
360   _G.debugLine = 1;
361   pic16_emitcode (";", "%s ==.", debugSym);
362   _G.debugLine = 0;
363 }
364
365 /*-----------------------------------------------------------------*/
366 /* newAsmop - creates a new asmOp                                  */
367 /*-----------------------------------------------------------------*/
368 static asmop *newAsmop (short type)
369 {
370     asmop *aop;
371
372     aop = Safe_calloc(1,sizeof(asmop));
373     aop->type = type;
374     return aop;
375 }
376
377 /*-----------------------------------------------------------------*/
378 /* resolveIfx - converts an iCode ifx into a form more useful for  */
379 /*              generating code                                    */
380 /*-----------------------------------------------------------------*/
381 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
382 {
383   FENTRY2;
384
385 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
386
387   if(!resIfx)
388     return;
389
390
391   resIfx->condition = 1;    /* assume that the ifx is true */
392   resIfx->generated = 0;    /* indicate that the ifx has not been used */
393
394   if(!ifx) {
395     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
396
397 #if 1
398     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
399                         __FUNCTION__,__LINE__,resIfx->lbl->key);
400 #endif
401
402   } else {
403     if(IC_TRUE(ifx)) {
404       resIfx->lbl = IC_TRUE(ifx);
405     } else {
406       resIfx->lbl = IC_FALSE(ifx);
407       resIfx->condition = 0;
408     }
409
410 #if 1
411     if(IC_TRUE(ifx))
412       DEBUGpic16_emitcode("; +++","ifx true is non-null");
413     else
414       DEBUGpic16_emitcode("; +++","ifx true is null");
415     if(IC_FALSE(ifx))
416       DEBUGpic16_emitcode("; +++","ifx false is non-null");
417     else
418       DEBUGpic16_emitcode("; +++","ifx false is null");
419 #endif
420   }
421
422   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
423
424 }
425 #if 0
426 /*-----------------------------------------------------------------*/
427 /* pointerCode - returns the code for a pointer type               */
428 /*-----------------------------------------------------------------*/
429 static int pointerCode (sym_link *etype)
430 {
431
432     return PTR_TYPE(SPEC_OCLS(etype));
433
434 }
435 #endif
436
437 /*-----------------------------------------------------------------*/
438 /* aopForSym - for a true symbol                                   */
439 /*-----------------------------------------------------------------*/
440 static asmop *aopForSym (iCode *ic, operand *op, bool result)
441 {
442     symbol *sym=OP_SYMBOL(op);
443     asmop *aop;
444     memmap *space= SPEC_OCLS(sym->etype);
445
446     FENTRY2;
447
448     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
449
450 //    sym = OP_SYMBOL(op);
451
452     /* if already has one */
453     if (sym->aop) {
454             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
455         return sym->aop;
456     }
457
458 #if 0
459     /* if symbol was initially placed onStack then we must re-place it
460      * to direct memory, since pic16 does not have a specific stack */
461     if(sym->onStack) {
462         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
463     }
464 #endif
465
466
467 #if 0
468     if(sym->iaccess) {
469       if(space->paged) {
470         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
471
472         sym->aop = aop = newAsmop (AOP_PAGED);
473         aop->aopu.aop_dir = sym->rname ;
474         aop->size = getSize(sym->type);
475         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
476         pic16_allocDirReg( IC_LEFT(ic) );
477         return aop;
478       }
479       assert( 0 );
480     }
481 #endif
482
483 #if 1
484     /* assign depending on the storage class */
485     /* if it is on the stack or indirectly addressable */
486     /* space we need to assign either r0 or r1 to it   */
487     if (sym->onStack)   // || sym->iaccess)
488     {
489       pCodeOp *pcop[4];
490       int i;
491
492         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
493                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
494
495         /* acquire a temporary register -- it is saved in function */
496
497         sym->aop = aop = newAsmop(AOP_STA);
498         aop->aopu.stk.stk = sym->stack;
499         aop->size = getSize(sym->type);
500
501
502         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
503         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
504           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
505 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
506
507           for(i=0;i<aop->size;i++)
508             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
509             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
510         } else
511         if(1 && ic->op == SEND) {
512
513           /* if SEND do the send here */
514           _G.resDirect = 1;
515         } else {
516 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
517           for(i=0;i<aop->size;i++) {
518             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
519             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
520           }
521         }
522
523
524 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
525
526 #if 1
527         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
528
529         // we do not need to load the value if it is to be defined...
530         if (result) return aop;
531
532         if(_G.accInUse) {
533                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
534         }
535
536         for(i=0;i<aop->size;i++) {
537
538           /* initialise for stack access via frame pointer */
539           // operands on stack are accessible via "{FRAME POINTER} + index" with index
540           // starting at 2 for arguments and growing from 0 downwards for
541           // local variables (index == 0 is not assigned so we add one here)
542           {
543             int soffs = sym->stack;
544             if (soffs <= 0) {
545               assert (soffs < 0);
546               soffs++;
547             } // if
548
549             if(1 && ic->op == SEND) {
550               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
551               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
552                     pic16_popCopyReg( pic16_frame_plusw ),
553                     pic16_popCopyReg(pic16_stack_postdec )));
554             } else {
555               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
556               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
557                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
558             }
559           }
560         }
561
562         if(_G.accInUse) {
563                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
564         }
565
566         return (aop);
567 #endif
568
569 #if 0
570         /* now assign the address of the variable to
571         the pointer register */
572         if (aop->type != AOP_STK) {
573
574             if (sym->onStack) {
575                     if ( _G.accInUse )
576                         pic16_emitcode("push","acc");
577
578                     pic16_emitcode("mov","a,_bp");
579                     pic16_emitcode("add","a,#0x%02x",
580                              ((sym->stack < 0) ?
581                               ((char)(sym->stack - _G.nRegsSaved )) :
582                               ((char)sym->stack)) & 0xff);
583                     pic16_emitcode("mov","%s,a",
584                              aop->aopu.aop_ptr->name);
585
586                     if ( _G.accInUse )
587                         pic16_emitcode("pop","acc");
588             } else
589                 pic16_emitcode("mov","%s,#%s",
590                          aop->aopu.aop_ptr->name,
591                          sym->rname);
592             aop->paged = space->paged;
593         } else
594             aop->aopu.aop_stk = sym->stack;
595         return aop;
596 #endif
597
598     }
599 #endif
600
601 #if 1
602     /* special case for a function */
603     if (IS_FUNC(sym->type)) {
604         sym->aop = aop = newAsmop(AOP_PCODE);
605         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
606         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
607         PCOI(aop->aopu.pcop)->index = 0;
608         aop->size = FPTRSIZE;
609         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
610         return aop;
611     }
612 #endif
613
614
615
616     //DEBUGpic16_emitcode(";","%d",__LINE__);
617     /* if in bit space */
618     if (IN_BITSPACE(space)) {
619         sym->aop = aop = newAsmop (AOP_CRY);
620         aop->aopu.aop_dir = sym->rname ;
621         aop->size = getSize(sym->type);
622         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
623         return aop;
624     }
625     /* if it is in direct space */
626     if (IN_DIRSPACE(space)) {
627                 if(!strcmp(sym->rname, "_WREG")) {
628                         sym->aop = aop = newAsmop (AOP_ACC);
629                         aop->size = getSize(sym->type);         /* should always be 1 */
630                         assert(aop->size == 1);
631                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
632                         return (aop);
633                 } else {
634                         sym->aop = aop = newAsmop (AOP_DIR);
635                 aop->aopu.aop_dir = sym->rname ;
636             aop->size = getSize(sym->type);
637                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
638                         pic16_allocDirReg( IC_LEFT(ic) );
639                         return (aop);
640                 }
641         }
642
643     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
644         sym->aop = aop = newAsmop (AOP_DIR);
645         aop->aopu.aop_dir = sym->rname ;
646         aop->size = getSize(sym->type);
647         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
648         pic16_allocDirReg( IC_LEFT(ic) );
649         return aop;
650     }
651
652
653     /* only remaining is far space */
654     sym->aop = aop = newAsmop(AOP_PCODE);
655
656 /* change the next if to 1 to revert to good old immediate code */
657         if(IN_CODESPACE(space)) {
658                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
659                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
660                 PCOI(aop->aopu.pcop)->index = 0;
661         } else {
662                 /* try to allocate via direct register */
663                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
664 //              aop->size = getSize( sym->type );
665         }
666
667         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
668                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
669
670 #if 0
671         if(!pic16_allocDirReg (IC_LEFT(ic)))
672                 return NULL;
673 #endif
674
675         if(IN_DIRSPACE( space ))
676                 aop->size = PTRSIZE;
677         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
678                 aop->size = FPTRSIZE;
679         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
680         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
681         else if(sym->onStack) {
682                 aop->size = PTRSIZE;
683         } else {
684           if(SPEC_SCLS(sym->etype) == S_PDATA) {
685             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
686             aop->size = FPTRSIZE;
687           } else
688                 assert( 0 );
689         }
690
691     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
692
693     /* if it is in code space */
694     if (IN_CODESPACE(space))
695         aop->code = 1;
696
697     return aop;
698 }
699
700 /*-----------------------------------------------------------------*/
701 /* aopForRemat - rematerialzes an object                           */
702 /*-----------------------------------------------------------------*/
703 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
704 {
705   symbol *sym = OP_SYMBOL(op);
706   operand *refop;
707   iCode *ic = NULL, *oldic;
708   asmop *aop = newAsmop(AOP_PCODE);
709   int val = 0;
710   int offset = 0;
711   int viaimmd=0;
712
713     FENTRY2;
714
715         ic = sym->rematiCode;
716
717         if(IS_OP_POINTER(op)) {
718                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
719         }
720
721 //    if(!result)               /* fixme-vr */
722         for (;;) {
723                 oldic = ic;
724
725 //              chat *iLine = printILine(ic);
726 //              pic16_emitpcomment("ic: %s\n", iLine);
727 //              dbuf_free(iLine);
728
729                 if (ic->op == '+') {
730                         val += (int) operandLitValue(IC_RIGHT(ic));
731                 } else if (ic->op == '-') {
732                         val -= (int) operandLitValue(IC_RIGHT(ic));
733                 } else
734                         break;
735
736                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
737         }
738
739         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
740         refop = IC_LEFT(ic);
741
742         if(!op->isaddr)viaimmd++; else viaimmd=0;
743
744 /* set the following if to 1 to revert to good old immediate code */
745         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
746                 || viaimmd) {
747
748                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
749
750                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
751
752 #if 0
753                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
754 #else
755                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
756 #endif
757
758                 PCOI(aop->aopu.pcop)->index = val;
759
760                 aop->size = getSize( sym->type );
761         } else {
762                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
763
764                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
765                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
766
767                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
768         }
769
770
771         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
772                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
773 #if 0
774                 val, IS_PTR_CONST(operandType(op)));
775 #else
776                 val, IS_CODEPTR(operandType(op)));
777 #endif
778
779 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
780
781         pic16_allocDirReg (IC_LEFT(ic));
782
783         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
784                 aop->code = 1;
785
786   return aop;
787 }
788
789 #if 0
790 static int aopIdx (asmop *aop, int offset)
791 {
792   if(!aop)
793     return -1;
794
795   if(aop->type !=  AOP_REG)
796     return -2;
797
798   return aop->aopu.aop_reg[offset]->rIdx;
799
800 }
801 #endif
802
803 /*-----------------------------------------------------------------*/
804 /* regsInCommon - two operands have some registers in common       */
805 /*-----------------------------------------------------------------*/
806 static bool regsInCommon (operand *op1, operand *op2)
807 {
808     symbol *sym1, *sym2;
809     int i;
810
811     /* if they have registers in common */
812     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
813         return FALSE ;
814
815     sym1 = OP_SYMBOL(op1);
816     sym2 = OP_SYMBOL(op2);
817
818     if (sym1->nRegs == 0 || sym2->nRegs == 0)
819         return FALSE ;
820
821     for (i = 0 ; i < sym1->nRegs ; i++) {
822         int j;
823         if (!sym1->regs[i])
824             continue ;
825
826         for (j = 0 ; j < sym2->nRegs ;j++ ) {
827             if (!sym2->regs[j])
828                 continue ;
829
830             if (sym2->regs[j] == sym1->regs[i])
831                 return TRUE ;
832         }
833     }
834
835     return FALSE ;
836 }
837
838 /*-----------------------------------------------------------------*/
839 /* operandsEqu - equivalent                                        */
840 /*-----------------------------------------------------------------*/
841 static bool operandsEqu ( operand *op1, operand *op2)
842 {
843     symbol *sym1, *sym2;
844
845     /* if they not symbols */
846     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
847         return FALSE;
848
849     sym1 = OP_SYMBOL(op1);
850     sym2 = OP_SYMBOL(op2);
851
852     /* if both are itemps & one is spilt
853        and the other is not then false */
854     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
855         sym1->isspilt != sym2->isspilt )
856         return FALSE ;
857
858     /* if they are the same */
859     if (sym1 == sym2)
860         return TRUE ;
861
862     if (sym1->rname[0] && sym2->rname[0]
863         && strcmp (sym1->rname, sym2->rname) == 0)
864         return TRUE;
865
866
867     /* if left is a tmp & right is not */
868     if (IS_ITEMP(op1)  &&
869         !IS_ITEMP(op2) &&
870         sym1->isspilt  &&
871         (SYM_SPIL_LOC(sym1) == sym2))
872         return TRUE;
873
874     if (IS_ITEMP(op2)  &&
875         !IS_ITEMP(op1) &&
876         sym2->isspilt  &&
877         sym1->level > 0 &&
878         (SYM_SPIL_LOC(sym2) == sym1))
879         return TRUE ;
880
881     return FALSE ;
882 }
883
884 /*-----------------------------------------------------------------*/
885 /* pic16_sameRegs - two asmops have the same registers                   */
886 /*-----------------------------------------------------------------*/
887 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
888 {
889     int i;
890
891     if (aop1 == aop2)
892         return TRUE ;
893
894     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
895                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
896
897     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
898
899     if (aop1->type != AOP_REG ||
900         aop2->type != AOP_REG )
901         return FALSE ;
902
903     /* This is a bit too restrictive if one is a subset of the other...
904     if (aop1->size != aop2->size )
905         return FALSE ;
906     */
907
908     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
909 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
910
911 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
912         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
913             return FALSE ;
914     }
915
916     return TRUE ;
917 }
918
919 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
920 {
921     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
922                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
923
924     if(aop1 == aop2)return TRUE;
925     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
926
927       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
928
929   return TRUE;
930 }
931
932
933 /*-----------------------------------------------------------------*/
934 /* pic16_aopOp - allocates an asmop for an operand  :                    */
935 /*-----------------------------------------------------------------*/
936 void pic16_aopOp (operand *op, iCode *ic, bool result)
937 {
938     asmop *aop;
939     symbol *sym;
940     int i;
941
942     if (!op)
943         return ;
944
945     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
946
947     /* if this a literal */
948     if (IS_OP_LITERAL(op)) {
949         op->aop = aop = newAsmop(AOP_LIT);
950         aop->aopu.aop_lit = op->operand.valOperand;
951         aop->size = getSize(operandType(op));
952         return;
953     }
954
955     {
956       sym_link *type = operandType(op);
957 #if 0
958       if(IS_PTR_CONST(type))
959 #else
960       if(IS_CODEPTR(type))
961 #endif
962         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
963     }
964
965     /* if already has a asmop then continue */
966     if (op->aop)
967         return ;
968
969     /* if the underlying symbol has a aop */
970     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
971       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
972         op->aop = OP_SYMBOL(op)->aop;
973         return;
974     }
975
976     /* if this is a true symbol */
977     if (IS_TRUE_SYMOP(op)) {
978         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
979       op->aop = aopForSym(ic, op, result);
980       return ;
981     }
982
983     /* this is a temporary : this has
984     only four choices :
985     a) register
986     b) spillocation
987     c) rematerialize
988     d) conditional
989     e) can be a return use only */
990
991     sym = OP_SYMBOL(op);
992
993     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
994     /* if the type is a conditional */
995     if (sym->regType == REG_CND) {
996         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
997         aop->size = 0;
998         return;
999     }
1000
1001     /* if it is spilt then two situations
1002     a) is rematerialize
1003     b) has a spill location */
1004     if (sym->isspilt || sym->nRegs == 0) {
1005
1006 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1007       DEBUGpic16_emitcode(";","%d",__LINE__);
1008         /* rematerialize it NOW */
1009         if (sym->remat) {
1010
1011             sym->aop = op->aop = aop = aopForRemat (op, result);
1012             return;
1013         }
1014
1015 #if 1
1016         if (sym->accuse) {
1017             int i;
1018             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1019             aop->size = getSize(sym->type);
1020             for ( i = 0 ; i < 1 ; i++ ) {
1021                 aop->aopu.aop_str[i] = accUse[i];
1022 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, SYM_SPIL_LOC(sym)->offset);
1023             }
1024             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1025             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1026             return;
1027         }
1028 #endif
1029
1030 #if 1
1031         if (sym->ruonly) {
1032           /*
1033           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1034           aop->aopu.pcop = pic16_popGetImmd(SYM_SPIL_LOC(sym)->rname,0,SYM_SPIL_LOC(sym)->offset);
1035           //pic16_allocDirReg (IC_LEFT(ic));
1036           aop->size = getSize(sym->type);
1037           */
1038
1039           unsigned i;
1040
1041           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1042           aop->size = getSize(sym->type);
1043           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1044             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1045
1046           DEBUGpic16_emitcode(";","%d",__LINE__);
1047           return;
1048         }
1049 #endif
1050         /* else spill location  */
1051         if (SYM_SPIL_LOC(sym) && getSize(sym->type) != getSize(SYM_SPIL_LOC(sym)->type)) {
1052             /* force a new aop if sizes differ */
1053             SYM_SPIL_LOC(sym)->aop = NULL;
1054         }
1055
1056 #if 0
1057         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1058                             __FUNCTION__,__LINE__,
1059                             SYM_SPIL_LOC(sym)->rname,
1060                             sym->rname, SYM_SPIL_LOC(sym)->offset);
1061 #endif
1062
1063         //aop->aopu.pcop = pic16_popGetImmd(SYM_SPIL_LOC(sym)->rname,0,SYM_SPIL_LOC(sym)->offset);
1064         if (SYM_SPIL_LOC(sym) && SYM_SPIL_LOC(sym)->rname) {
1065           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1066           aop->aopu.pcop = pic16_popRegFromString(SYM_SPIL_LOC(sym)->rname,
1067                                                   getSize(sym->type),
1068                                                   SYM_SPIL_LOC(sym)->offset, op);
1069         } else if (getSize(sym->type) <= 1) {
1070           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1071           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1072           assert (getSize(sym->type) <= 1);
1073           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1074           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1075         } else {
1076           /* We need some kind of dummy area for getSize(sym->type) byte,
1077            * use WREG for all storage locations.
1078            * XXX: This only works if we are implementing a `dummy read',
1079            *      the stored value will not be retrievable...
1080            *      See #1503234 for a case requiring this. */
1081           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1082           aop->size = getSize(sym->type);
1083           for ( i = 0 ; i < aop->size ;i++)
1084             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1085         }
1086         aop->size = getSize(sym->type);
1087
1088         return;
1089     }
1090
1091     {
1092       sym_link *type = operandType(op);
1093 #if 0
1094       if(IS_PTR_CONST(type))
1095 #else
1096       if(IS_CODEPTR(type))
1097 #endif
1098         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1099     }
1100
1101     /* must be in a register */
1102     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1103     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1104     aop->size = sym->nRegs;
1105     for ( i = 0 ; i < sym->nRegs ;i++)
1106         aop->aopu.aop_reg[i] = sym->regs[i];
1107 }
1108
1109 /*-----------------------------------------------------------------*/
1110 /* pic16_freeAsmop - free up the asmop given to an operand               */
1111 /*----------------------------------------------------------------*/
1112 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1113 {
1114     asmop *aop ;
1115
1116     if (!op)
1117         aop = aaop;
1118     else
1119         aop = op->aop;
1120
1121     if (!aop)
1122         return ;
1123
1124     if (aop->freed)
1125         goto dealloc;
1126
1127     aop->freed = 1;
1128
1129 #if 1
1130     switch (aop->type) {
1131         case AOP_STA:
1132           {
1133             int i;
1134
1135               /* we must store the result on stack */
1136               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1137                 // operands on stack are accessible via "FSR2 + index" with index
1138                 // starting at 2 for arguments and growing from 0 downwards for
1139                 // local variables (index == 0 is not assigned so we add one here)
1140                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1141                 if (soffs <= 0) {
1142                   assert (soffs < 0);
1143                   soffs++;
1144                 } // if
1145                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1146                 for(i=0;i<aop->size;i++) {
1147                   /* initialise for stack access via frame pointer */
1148                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1149                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1150                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1151                 }
1152
1153                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1154               }
1155
1156               if(!_G.resDirect) {
1157                 for(i=0;i<aop->size;i++) {
1158                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1159
1160                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1161                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1162 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1163                   }
1164                 }
1165
1166                 if (_G.sregsAllocSet) {
1167                   regs *sr;
1168
1169                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1170                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1171                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1172                       deleteSetItem( &_G.sregsAllocSet, sr );
1173                     }
1174                 }
1175               }
1176               _G.resDirect = 0;
1177           }
1178           break;
1179 #if 0
1180         case AOP_STK :
1181         {
1182             int sz = aop->size;
1183             int stk = aop->aopu.aop_stk + aop->size;
1184             bitVectUnSetBit(ic->rUsed,R0_IDX);
1185             bitVectUnSetBit(ic->rUsed,R1_IDX);
1186
1187             getFreePtr(ic,&aop,FALSE);
1188
1189             if (options.stack10bit)
1190             {
1191                 /* I'm not sure what to do here yet... */
1192                 /* #STUB */
1193                 fprintf(stderr,
1194                         "*** Warning: probably generating bad code for "
1195                         "10 bit stack mode.\n");
1196             }
1197
1198             if (stk) {
1199                 pic16_emitcode ("mov","a,_bp");
1200                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1201                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1202             } else {
1203                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1204             }
1205
1206             while (sz--) {
1207                 pic16_emitcode("pop","acc");
1208                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1209                 if (!sz) break;
1210                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1211             }
1212             op->aop = aop;
1213             pic16_freeAsmop(op,NULL,ic,TRUE);
1214             if (_G.r0Pushed) {
1215                 pic16_emitcode("pop","ar0");
1216                 _G.r0Pushed--;
1217             }
1218
1219             if (_G.r1Pushed) {
1220                 pic16_emitcode("pop","ar1");
1221                 _G.r1Pushed--;
1222             }
1223         }
1224 #endif
1225
1226     }
1227 #endif
1228
1229 dealloc:
1230     /* all other cases just dealloc */
1231     if (op ) {
1232         op->aop = NULL;
1233         if (IS_SYMOP(op)) {
1234             OP_SYMBOL(op)->aop = NULL;
1235             /* if the symbol has a spill */
1236             if (SPIL_LOC(op))
1237                 SPIL_LOC(op)->aop = NULL;
1238         }
1239     }
1240 }
1241
1242 /*-----------------------------------------------------------------*/
1243 /* pic16_aopGet - for fetching value of the aop                          */
1244 /*-----------------------------------------------------------------*/
1245 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1246 {
1247     char *s = buffer ;
1248     char *rs;
1249
1250     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1251
1252     /* offset is greater than size then zero */
1253     if (offset > (aop->size - 1) &&
1254         aop->type != AOP_LIT)
1255         return zero;
1256
1257     /* depending on type */
1258     switch (aop->type) {
1259     case AOP_DIR:
1260       if (offset) {
1261         sprintf(s,"(%s + %d)",
1262                 aop->aopu.aop_dir,
1263                 offset);
1264         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1265       } else
1266             sprintf(s,"%s",aop->aopu.aop_dir);
1267         rs = Safe_calloc(1,strlen(s)+1);
1268         strcpy(rs,s);
1269         return rs;
1270
1271     case AOP_REG:
1272       return aop->aopu.aop_reg[offset]->name;
1273
1274     case AOP_CRY:
1275       return aop->aopu.aop_dir;
1276
1277     case AOP_ACC:
1278         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1279 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1280 //        assert( 0 );
1281 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1282         rs = Safe_strdup("WREG");
1283         return (rs);
1284
1285     case AOP_LIT:
1286         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1287         rs = Safe_calloc(1,strlen(s)+1);
1288         strcpy(rs,s);
1289         return rs;
1290
1291     case AOP_STR:
1292         aop->coff = offset ;
1293
1294 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1295 //          dname)
1296 //          return "acc";
1297         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1298           aop->type = AOP_ACC;
1299           return Safe_strdup("_WREG");
1300         }
1301         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1302
1303         return aop->aopu.aop_str[offset];
1304
1305     case AOP_PCODE:
1306       {
1307         pCodeOp *pcop = aop->aopu.pcop;
1308         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1309         if(pcop->name) {
1310           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1311           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1312           if (offset) {
1313             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1314           } else {
1315             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1316           }
1317         } else
1318           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1319
1320       }
1321       rs = Safe_calloc(1,strlen(s)+1);
1322       strcpy(rs,s);
1323       return rs;
1324
1325 #if 0
1326     case AOP_PAGED:
1327       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1328       if (offset) {
1329         sprintf(s,"(%s + %d)",
1330                 aop->aopu.aop_dir,
1331                 offset);
1332       } else
1333             sprintf(s,"%s",aop->aopu.aop_dir);
1334       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1335       rs = Safe_calloc(1,strlen(s)+1);
1336       strcpy(rs,s);
1337       return rs;
1338 #endif
1339
1340     case AOP_STA:
1341         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1342         return (rs);
1343
1344     case AOP_STK:
1345 //        pCodeOp *pcop = aop->aop
1346         break;
1347
1348     }
1349
1350     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1351     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1352            "aopget got unsupported aop->type");
1353     exit(0);
1354 }
1355
1356
1357
1358 /* lock has the following meaning: When allocating temporary registers
1359  * for stack variables storage, the value of the temporary register is
1360  * saved on stack. Its value is restored at the end. This procedure is
1361  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1362  * a possibility that before a call to pic16_aopOp, a temporary register
1363  * is allocated for a while and it is freed after some time, this will
1364  * mess the stack and values will not be restored properly. So use lock=1
1365  * to allocate temporary registers used internally by the programmer, and
1366  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1367  * to inform the compiler developer about a possible bug. This is an internal
1368  * feature for developing the compiler -- VR */
1369
1370 int _TempReg_lock = 0;
1371 /*-----------------------------------------------------------------*/
1372 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1373 /*-----------------------------------------------------------------*/
1374 pCodeOp *pic16_popGetTempReg(int lock)
1375 {
1376   pCodeOp *pcop=NULL;
1377   symbol *cfunc;
1378
1379 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1380     if(_TempReg_lock) {
1381 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1382     }
1383
1384     _TempReg_lock += lock;
1385
1386     cfunc = currFunc;
1387     currFunc = NULL;
1388
1389     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1390     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1391       PCOR(pcop)->r->wasUsed=1;
1392       PCOR(pcop)->r->isFree=0;
1393
1394       /* push value on stack */
1395       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1396     }
1397
1398     currFunc = cfunc;
1399
1400   return pcop;
1401 }
1402
1403 /*-----------------------------------------------------------------*/
1404 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1405 /*                           is not part of f, but don't save if   */
1406 /*                           inside v                              */
1407 /*-----------------------------------------------------------------*/
1408 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1409 {
1410   pCodeOp *pcop=NULL;
1411   symbol *cfunc;
1412   int i;
1413
1414 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1415
1416     if(_TempReg_lock) {
1417 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1418     }
1419
1420     _TempReg_lock += lock;
1421
1422     cfunc = currFunc;
1423     currFunc = NULL;
1424
1425     i = bitVectFirstBit(f);
1426     while(i < 128) {
1427
1428       /* bypass registers that are used by function */
1429       if(!bitVectBitValue(f, i)) {
1430
1431         /* bypass registers that are already allocated for stack access */
1432         if(!bitVectBitValue(v, i))  {
1433
1434 //          debugf("getting register rIdx = %d\n", i);
1435           /* ok, get the operand */
1436           pcop = pic16_newpCodeOpReg( i );
1437
1438           /* should never by NULL */
1439           assert( pcop != NULL );
1440
1441
1442           /* sanity check */
1443           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1444             int found=0;
1445
1446               PCOR(pcop)->r->wasUsed=1;
1447               PCOR(pcop)->r->isFree=0;
1448
1449
1450               {
1451                 regs *sr;
1452
1453                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1454
1455                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1456                       /* already used in previous steps, break */
1457                       found=1;
1458                       break;
1459                     }
1460                   }
1461               }
1462
1463               /* caller takes care of the following */
1464 //              bitVectSetBit(v, i);
1465
1466               if(!found) {
1467                 /* push value on stack */
1468                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1469                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1470               }
1471
1472             break;
1473           }
1474         }
1475       }
1476       i++;
1477     }
1478
1479     currFunc = cfunc;
1480
1481   return pcop;
1482 }
1483
1484
1485 /*-----------------------------------------------------------------*/
1486 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1487 /*-----------------------------------------------------------------*/
1488 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1489 {
1490   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1491
1492   _TempReg_lock -= lock;
1493
1494   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1495     PCOR(pcop)->r->isFree = 1;
1496
1497     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1498   }
1499 }
1500 /*-----------------------------------------------------------------*/
1501 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1502 /*-----------------------------------------------------------------*/
1503 pCodeOp *pic16_popGetLabel(int key)
1504 {
1505
1506   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1507
1508   if(key>max_key)
1509     max_key = key;
1510
1511   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1512 }
1513
1514 /*-----------------------------------------------------------------*/
1515 /* pic16_popCopyReg - copy a pcode operator                              */
1516 /*-----------------------------------------------------------------*/
1517 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1518 {
1519   pCodeOpReg *pcor;
1520
1521   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1522   memcpy (pcor, pc, sizeof (pCodeOpReg));
1523   pcor->r->wasUsed = 1;
1524
1525   //pcor->pcop.type = pc->pcop.type;
1526   if(pc->pcop.name) {
1527     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1528       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1529   } else
1530     pcor->pcop.name = NULL;
1531
1532   //pcor->r = pc->r;
1533   //pcor->rIdx = pc->rIdx;
1534   //pcor->r->wasUsed=1;
1535   //pcor->instance = pc->instance;
1536
1537 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1538
1539   return PCOP(pcor);
1540 }
1541
1542 /*-----------------------------------------------------------------*/
1543 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1544 /*-----------------------------------------------------------------*/
1545 pCodeOp *pic16_popGetLit(int lit)
1546 {
1547   return pic16_newpCodeOpLit(lit);
1548 }
1549
1550 /* Allow for 12 bit literals (LFSR x, <here!>). */
1551 pCodeOp *pic16_popGetLit12(int lit)
1552 {
1553   return pic16_newpCodeOpLit12(lit);
1554 }
1555
1556 /*-----------------------------------------------------------------*/
1557 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1558 /*-----------------------------------------------------------------*/
1559 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1560 {
1561   return pic16_newpCodeOpLit2(lit, arg2);
1562 }
1563
1564
1565 /*-----------------------------------------------------------------*/
1566 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1567 /*-----------------------------------------------------------------*/
1568 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1569 {
1570   return pic16_newpCodeOpImmd(name, offset,index, 0);
1571 }
1572
1573
1574 /*-----------------------------------------------------------------*/
1575 /* pic16_popGet - asm operator to pcode operator conversion              */
1576 /*-----------------------------------------------------------------*/
1577 pCodeOp *pic16_popGetWithString(char *str)
1578 {
1579   pCodeOp *pcop;
1580
1581
1582   if(!str) {
1583     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1584     exit (1);
1585   }
1586
1587   pcop = pic16_newpCodeOp(str,PO_STR);
1588
1589   return pcop;
1590 }
1591
1592 /*-----------------------------------------------------------------*/
1593 /* pic16_popRegFromString -                                        */
1594 /*-----------------------------------------------------------------*/
1595 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1596 {
1597
1598   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1599   pcop->type = PO_DIR;
1600
1601   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1602   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1603
1604   if(!str)
1605     str = "BAD_STRING";
1606
1607   pcop->name = Safe_calloc(1,strlen(str)+1);
1608   strcpy(pcop->name,str);
1609
1610   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1611
1612   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1613 //  PCOR(pcop)->r->wasUsed = 1;
1614
1615   /* make sure that register doesn't exist,
1616    * and operand isn't NULL
1617    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1618   if((PCOR(pcop)->r == NULL)
1619     && (op)
1620     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1621 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1622 //              __FUNCTION__, __LINE__, str, size, offset);
1623
1624     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1625     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1626
1627   }
1628   PCOR(pcop)->instance = offset;
1629
1630   return pcop;
1631 }
1632
1633 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1634 {
1635   pCodeOp *pcop;
1636
1637 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1638 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1639
1640         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1641         PCOR(pcop)->rIdx = rIdx;
1642         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1643         if(!PCOR(pcop)->r)
1644                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1645
1646         PCOR(pcop)->r->isFree = 0;
1647         PCOR(pcop)->r->wasUsed = 1;
1648
1649         pcop->type = PCOR(pcop)->r->pc_type;
1650
1651   return pcop;
1652 }
1653
1654 /*---------------------------------------------------------------------------------*/
1655 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1656 /*                 VR 030601                                                       */
1657 /*---------------------------------------------------------------------------------*/
1658 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1659 {
1660   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1661         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
1662   return PCOP(pcop2);
1663 }
1664
1665
1666
1667 /*--------------------------------------------------------------------------------.-*/
1668 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1669 /*                  VR 030601 , adapted by Hans Dorn                                */
1670 /*--------------------------------------------------------------------------------.-*/
1671 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1672 {
1673   pCodeOp2 *pcop2;
1674   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
1675   return PCOP(pcop2);
1676 }
1677
1678 /*---------------------------------------------------------------------------------*/
1679 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1680 /*                     movff instruction                                           */
1681 /*---------------------------------------------------------------------------------*/
1682 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1683 {
1684   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
1685         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
1686
1687   return PCOP(pcop2);
1688 }
1689
1690
1691 /*-----------------------------------------------------------------*/
1692 /* pic16_popGet - asm operator to pcode operator conversion              */
1693 /*-----------------------------------------------------------------*/
1694 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1695 {
1696 //  char *s = buffer ;
1697 //  char *rs;
1698   pCodeOp *pcop;
1699
1700     FENTRY2;
1701
1702       /* offset is greater than size then zero */
1703
1704 //    if (offset > (aop->size - 1) &&
1705 //        aop->type != AOP_LIT)
1706 //      return NULL;  //zero;
1707
1708     /* depending on type */
1709     switch (aop->type) {
1710                 case AOP_STA:
1711                         /* pCodeOp is already allocated from aopForSym */
1712                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
1713                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
1714                         return (pcop);
1715
1716                 case AOP_ACC:
1717                         {
1718                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
1719
1720                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1721
1722                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1723
1724                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1725                                 PCOR(pcop)->rIdx = rIdx;
1726                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1727                                 PCOR(pcop)->r->wasUsed=1;
1728                                 PCOR(pcop)->r->isFree=0;
1729
1730                                 PCOR(pcop)->instance = offset;
1731                                 pcop->type = PCOR(pcop)->r->pc_type;
1732 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1733                                 return pcop;
1734
1735
1736 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1737 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1738
1739 //      assert( 0 );
1740                         }
1741
1742     case AOP_DIR:
1743       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
1744       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1745
1746 #if 0
1747     case AOP_PAGED:
1748       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1749       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1750 #endif
1751
1752     case AOP_REG:
1753       {
1754         int rIdx;
1755
1756 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
1757 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
1758         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1759
1760         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1761
1762         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1763 //      pcop->type = PO_GPR_REGISTER;
1764         PCOR(pcop)->rIdx = rIdx;
1765         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1766         PCOR(pcop)->r->wasUsed=1;
1767         PCOR(pcop)->r->isFree=0;
1768
1769         PCOR(pcop)->instance = offset;
1770         pcop->type = PCOR(pcop)->r->pc_type;
1771
1772         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
1773 //      rs = aop->aopu.aop_reg[offset]->name;
1774 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
1775         return pcop;
1776       }
1777
1778     case AOP_CRY:
1779         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1780
1781       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1782       PCOR(pcop)->instance = offset;
1783       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1784       //if(PCOR(pcop)->r == NULL)
1785       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1786       return pcop;
1787
1788     case AOP_LIT:
1789         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1790       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1791
1792     case AOP_STR:
1793       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1794       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1795
1796       /*
1797       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1798       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1799       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1800       pcop->type = PCOR(pcop)->r->pc_type;
1801       pcop->name = PCOR(pcop)->r->name;
1802
1803       return pcop;
1804       */
1805
1806     case AOP_PCODE:
1807       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1808                           __LINE__,
1809                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1810       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1811       switch( aop->aopu.pcop->type ) {
1812         case PO_DIR: PCOR(pcop)->instance += offset; break;
1813         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1814         case PO_WREG:
1815             assert (offset==0);
1816             break;
1817         default:
1818           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
1819           assert( 0 );  /* should never reach here */;
1820       }
1821       return pcop;
1822     }
1823
1824     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1825            "pic16_popGet got unsupported aop->type");
1826     exit(0);
1827 }
1828 /*-----------------------------------------------------------------*/
1829 /* pic16_aopPut - puts a string for a aop                                */
1830 /*-----------------------------------------------------------------*/
1831 void pic16_aopPut (asmop *aop, char *s, int offset)
1832 {
1833     char *d = buffer ;
1834     symbol *lbl ;
1835
1836     return;
1837
1838     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1839
1840     if (aop->size && offset > ( aop->size - 1)) {
1841         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1842                "pic16_aopPut got offset > aop->size");
1843         exit(0);
1844     }
1845
1846     /* will assign value to value */
1847     /* depending on where it is ofcourse */
1848     switch (aop->type) {
1849     case AOP_DIR:
1850       if (offset) {
1851         sprintf(d,"(%s + %d)",
1852                 aop->aopu.aop_dir,offset);
1853         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1854
1855       } else
1856             sprintf(d,"%s",aop->aopu.aop_dir);
1857
1858         if (strcmp(d,s)) {
1859           DEBUGpic16_emitcode(";","%d",__LINE__);
1860           if(strcmp(s,"W"))
1861             pic16_emitcode("movf","%s,w",s);
1862           pic16_emitcode("movwf","%s",d);
1863
1864           if(strcmp(s,"W")) {
1865             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1866             if(offset >= aop->size) {
1867               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1868               break;
1869             } else
1870               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1871           }
1872
1873           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1874
1875
1876         }
1877         break;
1878
1879     case AOP_REG:
1880       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1881         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1882           /*
1883             if (*s == '@'           ||
1884                 strcmp(s,"r0") == 0 ||
1885                 strcmp(s,"r1") == 0 ||
1886                 strcmp(s,"r2") == 0 ||
1887                 strcmp(s,"r3") == 0 ||
1888                 strcmp(s,"r4") == 0 ||
1889                 strcmp(s,"r5") == 0 ||
1890                 strcmp(s,"r6") == 0 ||
1891                 strcmp(s,"r7") == 0 )
1892                 pic16_emitcode("mov","%s,%s  ; %d",
1893                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1894             else
1895           */
1896
1897           if(strcmp(s,"W")==0 )
1898             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1899
1900           pic16_emitcode("movwf","%s",
1901                    aop->aopu.aop_reg[offset]->name);
1902
1903           if(strcmp(s,zero)==0) {
1904             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1905
1906           } else if(strcmp(s,"W")==0) {
1907             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1908             pcop->type = PO_GPR_REGISTER;
1909
1910             PCOR(pcop)->rIdx = -1;
1911             PCOR(pcop)->r = NULL;
1912
1913             DEBUGpic16_emitcode(";","%d",__LINE__);
1914             pcop->name = Safe_strdup(s);
1915             pic16_emitpcode(POC_MOVFW,pcop);
1916             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1917           } else if(strcmp(s,one)==0) {
1918             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1919             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1920           } else {
1921             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1922           }
1923         }
1924         break;
1925
1926     case AOP_STK:
1927         if (strcmp(s,"a") == 0)
1928             pic16_emitcode("push","acc");
1929         else
1930             pic16_emitcode("push","%s",s);
1931
1932         break;
1933
1934     case AOP_CRY:
1935         /* if bit variable */
1936         if (!aop->aopu.aop_dir) {
1937             pic16_emitcode("clr","a");
1938             pic16_emitcode("rlc","a");
1939         } else {
1940             if (s == zero)
1941                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1942             else
1943                 if (s == one)
1944                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1945                 else
1946                     if (!strcmp(s,"c"))
1947                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1948                     else {
1949                         lbl = newiTempLabel(NULL);
1950
1951                         if (strcmp(s,"a")) {
1952                             MOVA(s);
1953                         }
1954                         pic16_emitcode("clr","c");
1955                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1956                         pic16_emitcode("cpl","c");
1957                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1958                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1959                     }
1960         }
1961         break;
1962
1963     case AOP_STR:
1964         aop->coff = offset;
1965         if (strcmp(aop->aopu.aop_str[offset],s))
1966             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1967         break;
1968
1969     case AOP_ACC:
1970         aop->coff = offset;
1971         if (!offset && (strcmp(s,"acc") == 0))
1972             break;
1973
1974         if (strcmp(aop->aopu.aop_str[offset],s))
1975             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1976         break;
1977
1978     default :
1979         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
1980 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1981 //             "pic16_aopPut got unsupported aop->type");
1982 //      exit(0);
1983     }
1984
1985 }
1986
1987 /*-----------------------------------------------------------------*/
1988 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
1989 /*-----------------------------------------------------------------*/
1990 void pic16_mov2w (asmop *aop, int offset)
1991 {
1992   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1993
1994   if(pic16_isLitAop(aop))
1995     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1996   else
1997     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1998 }
1999
2000 void pic16_mov2w_volatile (asmop *aop)
2001 {
2002   int i;
2003
2004   if(!pic16_isLitAop(aop)) {
2005     // may need to protect this from the peepholer -- this is not nice but works...
2006     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
2007     for (i = 0; i < aop->size; i++) {
2008       if (i > 0) {
2009         pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - MORE"));
2010       } // if
2011       pic16_emitpcode(POC_MOVFW, pic16_popGet(aop, i));
2012     } // for
2013     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
2014   }
2015 }
2016
2017 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2018 {
2019   if(pic16_isLitAop(src)) {
2020     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2021     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2022   } else {
2023     if(pic16_sameRegsOfs(src, dst, offset))return;
2024     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2025                       pic16_popGet(dst, offset)));
2026   }
2027 }
2028
2029 static void pic16_movLit2f(pCodeOp *pc, int lit)
2030 {
2031   if (0 == (lit & 0x00ff))
2032   {
2033     pic16_emitpcode (POC_CLRF, pc);
2034   } else if (0xff == (lit & 0x00ff))
2035   {
2036     pic16_emitpcode (POC_SETF, pc);
2037   } else {
2038     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2039     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2040   }
2041 }
2042
2043 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2044 {
2045   if(pic16_isLitAop(src)) {
2046     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2047     pic16_emitpcode(POC_MOVWF, dst);
2048   } else {
2049     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2050   }
2051 }
2052
2053 void pic16_testStackOverflow(void)
2054 {
2055 #define GSTACK_TEST_NAME        "_gstack_test"
2056
2057   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2058
2059   {
2060     symbol *sym;
2061
2062       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2063       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2064 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2065       checkAddSym(&externs, sym);
2066   }
2067
2068 }
2069
2070 /* push pcop into stack */
2071 void pic16_pushpCodeOp(pCodeOp *pcop)
2072 {
2073 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2074   if (pcop->type == PO_LITERAL) {
2075     pic16_emitpcode(POC_MOVLW, pcop);
2076     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2077   } else {
2078     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2079   }
2080   if(pic16_options.gstack)
2081     pic16_testStackOverflow();
2082
2083 }
2084
2085 /* pop pcop from stack */
2086 void pic16_poppCodeOp(pCodeOp *pcop)
2087 {
2088   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2089   if(pic16_options.gstack)
2090     pic16_testStackOverflow();
2091 }
2092
2093
2094 /*-----------------------------------------------------------------*/
2095 /* pushw - pushes wreg to stack                                    */
2096 /*-----------------------------------------------------------------*/
2097 void pushw(void)
2098 {
2099   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2100   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2101   if(pic16_options.gstack)
2102     pic16_testStackOverflow();
2103 }
2104
2105
2106 /*-----------------------------------------------------------------*/
2107 /* pushaop - pushes aop to stack                                   */
2108 /*-----------------------------------------------------------------*/
2109 void pushaop(asmop *aop, int offset)
2110 {
2111   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2112
2113   if(_G.resDirect)return;
2114
2115   if(pic16_isLitAop(aop)) {
2116     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2117     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2118   } else {
2119     pic16_emitpcode(POC_MOVFF,
2120       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2121   }
2122
2123   if(pic16_options.gstack)
2124     pic16_testStackOverflow();
2125 }
2126
2127 /*-----------------------------------------------------------------*/
2128 /* popaop - pops aop from stack                                    */
2129 /*-----------------------------------------------------------------*/
2130 void popaop(asmop *aop, int offset)
2131 {
2132   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2133   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2134   if(pic16_options.gstack)
2135     pic16_testStackOverflow();
2136 }
2137
2138 void popaopidx(asmop *aop, int offset, int index)
2139 {
2140   int ofs=1;
2141
2142     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2143
2144     if(STACK_MODEL_LARGE)ofs++;
2145
2146     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2147     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2148     if(pic16_options.gstack)
2149       pic16_testStackOverflow();
2150 }
2151
2152 /*-----------------------------------------------------------------*/
2153 /* pic16_getDataSize - get the operand data size                         */
2154 /*-----------------------------------------------------------------*/
2155 int pic16_getDataSize(operand *op)
2156 {
2157     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2158
2159
2160     return AOP_SIZE(op);
2161
2162     // tsd- in the pic port, the genptr size is 1, so this code here
2163     // fails. ( in the 8051 port, the size was 4).
2164 #if 0
2165     int size;
2166     size = AOP_SIZE(op);
2167     if (size == GPTRSIZE)
2168     {
2169         sym_link *type = operandType(op);
2170         if (IS_GENPTR(type))
2171         {
2172             /* generic pointer; arithmetic operations
2173              * should ignore the high byte (pointer type).
2174              */
2175             size--;
2176     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2177         }
2178     }
2179     return size;
2180 #endif
2181 }
2182
2183 /*-----------------------------------------------------------------*/
2184 /* pic16_outAcc - output Acc                                             */
2185 /*-----------------------------------------------------------------*/
2186 void pic16_outAcc(operand *result)
2187 {
2188   int size,offset;
2189   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2190   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2191
2192
2193   size = pic16_getDataSize(result);
2194   if(size){
2195     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2196     size--;
2197     offset = 1;
2198     /* unsigned or positive */
2199     while(size--)
2200       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2201   }
2202
2203 }
2204
2205 /*-----------------------------------------------------------------*/
2206 /* pic16_outBitC - output a bit C                                  */
2207 /*                 Move to result the value of Carry flag -- VR    */
2208 /*-----------------------------------------------------------------*/
2209 void pic16_outBitC(operand *result)
2210 {
2211   int i;
2212
2213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2214
2215     /* if the result is bit */
2216     if (AOP_TYPE(result) == AOP_CRY) {
2217         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2218         pic16_aopPut(AOP(result),"c",0);
2219     } else {
2220
2221         i = AOP_SIZE(result);
2222         while(i--) {
2223                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2224         }
2225         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2226     }
2227 }
2228
2229 /*-----------------------------------------------------------------*/
2230 /* pic16_outBitOp - output a bit from Op                           */
2231 /*                 Move to result the value of set/clr op -- VR    */
2232 /*-----------------------------------------------------------------*/
2233 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2234 {
2235   int i;
2236
2237     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2238
2239     /* if the result is bit */
2240     if (AOP_TYPE(result) == AOP_CRY) {
2241         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2242         pic16_aopPut(AOP(result),"c",0);
2243     } else {
2244
2245         i = AOP_SIZE(result);
2246         while(i--) {
2247                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2248         }
2249         pic16_emitpcode(POC_RRCF, pcop);
2250         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2251     }
2252 }
2253
2254 /*-----------------------------------------------------------------*/
2255 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2256 /*-----------------------------------------------------------------*/
2257 void pic16_toBoolean(operand *oper)
2258 {
2259     int size = AOP_SIZE(oper) - 1;
2260     int offset = 1;
2261
2262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2263
2264     if ( AOP_TYPE(oper) != AOP_ACC) {
2265       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2266     }
2267     while (size--) {
2268       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2269     }
2270 }
2271
2272 /*-----------------------------------------------------------------*/
2273 /* genUminusFloat - unary minus for floating points                */
2274 /*-----------------------------------------------------------------*/
2275 static void genUminusFloat(operand *op,operand *result)
2276 {
2277   int size ,offset =0 ;
2278
2279     FENTRY;
2280     /* for this we just need to flip the
2281     first it then copy the rest in place */
2282     size = AOP_SIZE(op);
2283     assert( size == AOP_SIZE(result) );
2284
2285     while(size--) {
2286       pic16_mov2f(AOP(result), AOP(op), offset);
2287       offset++;
2288     }
2289
2290     /* toggle the MSB's highest bit */
2291     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2292 }
2293
2294 /*-----------------------------------------------------------------*/
2295 /* genUminus - unary minus code generation                         */
2296 /*-----------------------------------------------------------------*/
2297 static void genUminus (iCode *ic)
2298 {
2299   int lsize, rsize, i;
2300   sym_link *optype, *rtype;
2301   symbol *label;
2302   int needLabel=0;
2303
2304     FENTRY;
2305
2306     /* assign asmops */
2307     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2308     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2309
2310     /* if both in bit space then special case */
2311     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2312       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
2313
2314         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2315         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2316         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2317         goto release;
2318     }
2319
2320     optype = operandType(IC_LEFT(ic));
2321     rtype = operandType(IC_RESULT(ic));
2322
2323
2324     /* if float then do float stuff */
2325     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2326       if(IS_FIXED(optype))
2327         debugf("implement fixed16x16 type\n", 0);
2328
2329         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2330         goto release;
2331     }
2332
2333     /* otherwise subtract from zero by taking the 2's complement */
2334     lsize = AOP_SIZE(IC_LEFT(ic));
2335     rsize = AOP_SIZE(IC_RESULT(ic));
2336     label = newiTempLabel ( NULL );
2337
2338     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2339       /* If the result is longer than the operand,
2340          store sign extension (0x00 or 0xff) in W */
2341       if (rsize > lsize) {
2342         pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0x00));
2343         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(IC_LEFT(ic)), lsize-1), 7));
2344         pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0xFF));
2345       }
2346       for (i = rsize - 1; i > 0; --i) {
2347         if (i > lsize - 1) {
2348           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2349         } else {
2350           pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2351         } // if
2352       } // for
2353       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_RESULT(ic)), 0));
2354       for (i = 1; i < rsize; ++i) {
2355         if (i == rsize - 1) {
2356           emitSKPNZ;
2357         } else {
2358           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2359         }
2360         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2361       } // for
2362     } else {
2363       for (i = min(rsize, lsize) - 1; i >= 0; i--) {
2364         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2365         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2366       } // for
2367       /* Sign extend if the result is longer than the operand */
2368       if (rsize > lsize) {
2369         pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0x00));
2370         pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(IC_RESULT(ic)), lsize - 1), 7));
2371         pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0xFF));
2372         for (i = rsize - 1; i > lsize - 1; --i) {
2373           pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2374         } // for
2375       } // if
2376       if (rsize > 1) {
2377         for (i = 0; i < rsize - 2; i++) {
2378           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2379           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key));
2380           needLabel++;
2381         } // for
2382         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), rsize - 2));
2383       } // if
2384       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), rsize - 1));
2385     }
2386     if (needLabel)
2387       pic16_emitpLabel (label->key);
2388
2389 release:
2390     /* release the aops */
2391     pic16_freeAsmop(IC_LEFT(ic), NULL, ic, (RESULTONSTACK(ic) ? 0 : 1));
2392     pic16_freeAsmop(IC_RESULT(ic), NULL, ic, TRUE);
2393 }
2394
2395 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2396 {
2397   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2398     pic16_emitpcode(POC_MOVFW, src);
2399     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2400   } else {
2401     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2402         src, pic16_popGet(AOP(op), offset)));
2403   }
2404 }
2405
2406
2407 /*-----------------------------------------------------------------*/
2408 /* assignResultValue - assign results to oper, rescall==1 is       */
2409 /*                     called from genCall() or genPcall()         */
2410 /*-----------------------------------------------------------------*/
2411 static void assignResultValue(operand * oper, int res_size, int rescall)
2412 {
2413   int size = AOP_SIZE(oper);
2414   int offset=0;
2415
2416     FENTRY2;
2417 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2418     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2419
2420     if(rescall) {
2421       /* assign result from a call/pcall function() */
2422
2423       /* function results are stored in a special order,
2424        * see top of file with Function return policy, or manual */
2425
2426       if(size <= 4) {
2427         /* 8-bits, result in WREG */
2428         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2429
2430         if(size > 1 && res_size > 1) {
2431           /* 16-bits, result in PRODL:WREG */
2432           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2433         }
2434
2435         if(size > 2 && res_size > 2) {
2436           /* 24-bits, result in PRODH:PRODL:WREG */
2437           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2438         }
2439
2440         if(size > 3 && res_size > 3) {
2441           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2442           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2443         }
2444
2445         pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
2446
2447       } else {
2448         /* >32-bits, result on stack, and FSR0 points to beginning.
2449          * Fix stack when done */
2450         /* FIXME FIXME */
2451 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2452         while (size--) {
2453 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2454 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2455
2456           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2457           GpsuedoStkPtr++;
2458         }
2459
2460         /* fix stack */
2461         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2462         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2463         if(STACK_MODEL_LARGE) {
2464           emitSKPNC;
2465           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2466         }
2467       }
2468     } else {
2469       int areg = 0;             /* matching argument register */
2470
2471 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2472       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2473
2474
2475       /* its called from genReceive (probably) -- VR */
2476       /* I hope this code will not be called from somewhere else in the future!
2477        * We manually set the pseudo stack pointer in genReceive. - dw
2478        */
2479       if(!GpsuedoStkPtr && _G.useWreg) {
2480 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2481
2482         /* The last byte in the assignment is in W */
2483         if(areg <= GpsuedoStkPtr) {
2484           size--;
2485           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2486           offset++;
2487 //          debugf("receive from WREG\n", 0);
2488         }
2489         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2490       }
2491 //      GpsuedoStkPtr++;
2492       _G.stack_lat = AOP_SIZE(oper)-1;
2493
2494       while (size) {
2495         size--;
2496         GpsuedoStkPtr++;
2497         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
2498 //        debugf("receive from STACK\n", 0);
2499         offset++;
2500       }
2501     }
2502 }
2503
2504
2505 /*-----------------------------------------------------------------*/
2506 /* genIpush - generate code for pushing this gets a little complex */
2507 /*-----------------------------------------------------------------*/
2508 static void genIpush (iCode *ic)
2509 {
2510 //  int size, offset=0;
2511
2512   FENTRY;
2513   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2514
2515   if(ic->parmPush) {
2516     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
2517
2518     /* send to stack as normal */
2519     addSet(&_G.sendSet,ic);
2520 //    addSetHead(&_G.sendSet,ic);
2521     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2522   }
2523
2524
2525 #if 0
2526     int size, offset = 0 ;
2527     char *l;
2528
2529
2530     /* if this is not a parm push : ie. it is spill push
2531     and spill push is always done on the local stack */
2532     if (!ic->parmPush) {
2533
2534         /* and the item is spilt then do nothing */
2535         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2536             return ;
2537
2538         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2539         size = AOP_SIZE(IC_LEFT(ic));
2540         /* push it on the stack */
2541         while(size--) {
2542             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2543             if (*l == '#') {
2544                 MOVA(l);
2545                 l = "acc";
2546             }
2547             pic16_emitcode("push","%s",l);
2548         }
2549         return ;
2550     }
2551
2552     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2553 #endif
2554 }
2555
2556 /*-----------------------------------------------------------------*/
2557 /* genIpop - recover the registers: can happen only for spilling   */
2558 /*-----------------------------------------------------------------*/
2559 static void genIpop (iCode *ic)
2560 {
2561   FENTRY;
2562   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2563 #if 0
2564     int size,offset ;
2565
2566
2567     /* if the temp was not pushed then */
2568     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2569         return ;
2570
2571     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2572     size = AOP_SIZE(IC_LEFT(ic));
2573     offset = (size-1);
2574     while (size--)
2575         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2576                                    FALSE,TRUE));
2577
2578     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2579 #endif
2580 }
2581
2582 static int wparamCmp(void *p1, void *p2)
2583 {
2584   return (!strcmp((char *)p1, (char *)p2));
2585 }
2586
2587 int inWparamList(char *s)
2588 {
2589   return isinSetWith(wparamList, s, wparamCmp);
2590 }
2591
2592
2593 /*-----------------------------------------------------------------*/
2594 /* genCall - generates a call statement                            */
2595 /*-----------------------------------------------------------------*/
2596 static void genCall (iCode *ic)
2597 {
2598   sym_link *ftype;
2599   int stackParms=0;
2600   int use_wreg=0;
2601   int inwparam=0;
2602   char *fname;
2603
2604     FENTRY;
2605
2606     ftype = OP_SYM_TYPE(IC_LEFT(ic));
2607     /* if caller saves & we have not saved then */
2608 //    if (!ic->regsSaved)
2609 //      saveRegisters(ic);
2610
2611         /* initialise stackParms for IPUSH pushes */
2612 //      stackParms = psuedoStkPtr;
2613 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2614     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
2615     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
2616
2617 #if 0
2618     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
2619 #endif
2620
2621     /* if send set is not empty the assign */
2622     if (_G.sendSet) {
2623       iCode *sic;
2624       int psuedoStkPtr=-1;
2625       int firstTimeThruLoop = 1;
2626
2627
2628         /* reverse sendSet if function is not reentrant */
2629         if(!IFFUNC_ISREENT(ftype))
2630           _G.sendSet = reverseSet(_G.sendSet);
2631
2632         /* First figure how many parameters are getting passed */
2633         stackParms = 0;
2634         use_wreg = 0;
2635
2636         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2637           int size;
2638 //          int offset = 0;
2639
2640             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2641             size = AOP_SIZE(IC_LEFT(sic));
2642
2643             stackParms += size;
2644
2645             /* pass the last byte through WREG */
2646             if(inwparam) {
2647
2648               while (size--) {
2649                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2650                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2651                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2652
2653                 if(!firstTimeThruLoop) {
2654                   /* If this is not the first time we've been through the loop
2655                    * then we need to save the parameter in a temporary
2656                    * register. The last byte of the last parameter is
2657                    * passed in W. */
2658
2659                   pushw();
2660 //                  --psuedoStkPtr;             // sanity check
2661                   use_wreg = 1;
2662                 }
2663
2664                 firstTimeThruLoop=0;
2665
2666                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
2667
2668 //                offset++;
2669               }
2670             } else {
2671               /* all arguments are passed via stack */
2672               use_wreg = 0;
2673
2674               while (size--) {
2675                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2676                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2677                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2678
2679 //                pushaop(AOP(IC_LEFT(sic)), size);
2680                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
2681
2682                 if(!_G.resDirect)
2683                   pushw();
2684               }
2685             }
2686
2687             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2688           }
2689
2690           if(inwparam) {
2691             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
2692               pushw();  /* save last parameter to stack if functions has varargs */
2693               use_wreg = 0;
2694             } else
2695               use_wreg = 1;
2696           } else use_wreg = 0;
2697
2698           _G.stackRegSet = _G.sendSet;
2699           _G.sendSet = NULL;
2700     }
2701
2702     /* make the call */
2703     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
2704
2705     GpsuedoStkPtr=0;
2706
2707     /* if we need to assign a result value */
2708     if ((IS_ITEMP(IC_RESULT(ic))
2709           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2710               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2711         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2712
2713       _G.accInUse++;
2714       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2715       _G.accInUse--;
2716
2717       /* Must not assign an 8-bit result to a 16-bit variable;
2718        * this would use (used...) the uninitialized PRODL! */
2719       /* FIXME: Need a proper way to obtain size of function result type,
2720        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
2721       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
2722
2723       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2724                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2725
2726       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2727     }
2728
2729     if(!stackParms && ic->parmBytes) {
2730       stackParms = ic->parmBytes;
2731     }
2732
2733     stackParms -= use_wreg;
2734
2735     if(stackParms>0) {
2736       if(stackParms == 1) {
2737         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
2738       } else {
2739         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2740         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2741       }
2742       if(STACK_MODEL_LARGE) {
2743         emitSKPNC;
2744         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
2745       }
2746     }
2747
2748 #if 0
2749     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
2750 #endif
2751
2752     /* adjust the stack for parameters if required */
2753 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2754
2755 #if 0
2756       /* if register bank was saved then pop them */
2757       if (ic->bankSaved)
2758         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2759
2760       /* if we hade saved some registers then unsave them */
2761       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2762         unsaveRegisters (ic);
2763 #endif
2764 }
2765
2766
2767
2768 /*-----------------------------------------------------------------*/
2769 /* genPcall - generates a call by pointer statement                */
2770 /*            new version, created from genCall - HJD              */
2771 /*-----------------------------------------------------------------*/
2772 static void genPcall (iCode *ic)
2773 {
2774   sym_link *fntype;
2775   int stackParms=0;
2776   symbol *retlbl = newiTempLabel(NULL);
2777   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2778
2779     FENTRY;
2780
2781     fntype = operandType( IC_LEFT(ic) )->next;
2782
2783     /* if send set is not empty the assign */
2784     if (_G.sendSet) {
2785       iCode *sic;
2786       int psuedoStkPtr=-1;
2787
2788       /* reverse sendSet if function is not reentrant */
2789       if(!IFFUNC_ISREENT(fntype))
2790         _G.sendSet = reverseSet(_G.sendSet);
2791
2792       stackParms = 0;
2793
2794       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2795         int size;
2796
2797           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2798           size = AOP_SIZE(IC_LEFT(sic));
2799           stackParms += size;
2800
2801           /* all parameters are passed via stack, since WREG is clobbered
2802            * by the calling sequence */
2803           while (size--) {
2804             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2805             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2806             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2807
2808             pic16_mov2w (AOP(IC_LEFT(sic)), size);
2809             pushw();
2810           }
2811
2812           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2813       }
2814
2815       _G.stackRegSet = _G.sendSet;
2816       _G.sendSet = NULL;
2817     }
2818
2819     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2820
2821     // push return address
2822     // push $ on return stack, then replace with retlbl
2823
2824     /* Thanks to Thorsten Klose for pointing out that the following
2825      * snippet should be interrupt safe */
2826     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
2827     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
2828
2829     pic16_emitpcodeNULLop(POC_PUSH);
2830
2831     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2832     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2833     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2834     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2835     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2836     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2837
2838
2839     /* restore interrupt control register */
2840     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
2841     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
2842
2843     /* make the call by writing the pointer into pc */
2844     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
2845     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
2846
2847     // note: MOVFF to PCL not allowed
2848     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
2849     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2850
2851
2852     /* return address is here: (X) */
2853     pic16_emitpLabelFORCE(retlbl->key);
2854
2855     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2856
2857     GpsuedoStkPtr=0;
2858     /* if we need assign a result value */
2859     if ((IS_ITEMP(IC_RESULT(ic))
2860           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
2861               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
2862         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2863
2864       _G.accInUse++;
2865       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2866       _G.accInUse--;
2867
2868       /* FIXME: Need proper way to obtain the function result's type.
2869        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
2870       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
2871
2872       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2873               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2874
2875       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2876     }
2877
2878 //    stackParms -= use_wreg;
2879
2880     if(stackParms>0) {
2881       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2882       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
2883       if(STACK_MODEL_LARGE) {
2884         emitSKPNC;
2885         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
2886       }
2887     }
2888 }
2889
2890 /*-----------------------------------------------------------------*/
2891 /* resultRemat - result  is rematerializable                       */
2892 /*-----------------------------------------------------------------*/
2893 static int resultRemat (iCode *ic)
2894 {
2895   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2896   if (SKIP_IC(ic) || ic->op == IFX)
2897     return 0;
2898
2899   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2900     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2901     if (sym->remat && !POINTER_SET(ic))
2902       return 1;
2903   }
2904
2905   return 0;
2906 }
2907
2908 #if 0
2909 /*-----------------------------------------------------------------*/
2910 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2911 /*-----------------------------------------------------------------*/
2912 static bool inExcludeList(char *s)
2913 {
2914   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2915     int i =0;
2916
2917     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2918     if (options.excludeRegs[i] &&
2919     STRCASECMP(options.excludeRegs[i],"none") == 0)
2920         return FALSE ;
2921
2922     for ( i = 0 ; options.excludeRegs[i]; i++) {
2923         if (options.excludeRegs[i] &&
2924         STRCASECMP(s,options.excludeRegs[i]) == 0)
2925             return TRUE;
2926     }
2927     return FALSE ;
2928 }
2929 #endif
2930
2931 /*-----------------------------------------------------------------*/
2932 /* genFunction - generated code for function entry                 */
2933 /*-----------------------------------------------------------------*/
2934 static void genFunction (iCode *ic)
2935 {
2936   symbol *sym;
2937   sym_link *ftype;
2938
2939     FENTRY;
2940     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
2941
2942     pic16_labelOffset += (max_key+4);
2943     max_key=0;
2944     GpsuedoStkPtr=0;
2945     _G.nRegsSaved = 0;
2946
2947     ftype = operandType(IC_LEFT(ic));
2948     sym = OP_SYMBOL(IC_LEFT(ic));
2949
2950     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
2951       /* create an absolute section at the interrupt vector:
2952        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
2953       symbol *asym;
2954       char asymname[128];
2955       pBlock *apb;
2956
2957 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
2958
2959         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
2960           sprintf(asymname, "ivec_%s", sym->name);
2961         else
2962           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
2963
2964         /* when an interrupt is declared as naked, do not emit the special
2965          * wrapper segment at vector address. The user should take care for
2966          * this instead. -- VR */
2967
2968         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
2969           asym = newSymbol(asymname, 0);
2970           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
2971           pic16_addpBlock( apb );
2972
2973           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
2974           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
2975           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
2976           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
2977           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
2978
2979           /* mark the end of this tiny function */
2980           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
2981         } else {
2982           sprintf(asymname, "%s", sym->rname);
2983         }
2984
2985         {
2986           absSym *abSym;
2987
2988             abSym = Safe_calloc(1, sizeof(absSym));
2989             strcpy(abSym->name, asymname);
2990
2991             switch( FUNC_INTNO(sym->type) ) {
2992               case 0: abSym->address = 0x000000; break;
2993               case 1: abSym->address = 0x000008; break;
2994               case 2: abSym->address = 0x000018; break;
2995
2996               default:
2997 //                fprintf(stderr, "no interrupt number is given\n");
2998                 abSym->address = -1; break;
2999             }
3000
3001             /* relocate interrupt vectors if needed */
3002             if(abSym->address != -1)
3003               abSym->address += pic16_options.ivt_loc;
3004
3005             addSet(&absSymSet, abSym);
3006         }
3007     }
3008
3009     /* create the function header */
3010     pic16_emitcode(";","-----------------------------------------");
3011     pic16_emitcode(";"," function %s",sym->name);
3012     pic16_emitcode(";","-----------------------------------------");
3013
3014     /* prevent this symbol from being emitted as 'extern' */
3015     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3016
3017     pic16_emitcode("","%s:",sym->rname);
3018     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3019
3020     {
3021       absSym *ab;
3022
3023         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3024           if(!strcmp(ab->name, sym->rname)) {
3025             pic16_pBlockConvert2Absolute(pb);
3026             break;
3027           }
3028         }
3029     }
3030
3031     if(IFFUNC_ISNAKED(ftype)) {
3032       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3033       return;
3034     }
3035
3036     /* if critical function then turn interrupts off */
3037     if (IFFUNC_ISCRITICAL(ftype)) {
3038       //pic16_emitcode("clr","ea");
3039     }
3040
3041     currFunc = sym;             /* update the currFunc symbol */
3042     _G.fregsUsed = sym->regsUsed;
3043     _G.sregsAlloc = newBitVect(128);
3044
3045
3046     /* if this is an interrupt service routine then
3047      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3048     if (IFFUNC_ISISR(sym->type)) {
3049         _G.usefastretfie = 1;   /* use shadow registers by default */
3050
3051         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3052         if(!FUNC_ISSHADOWREGS(sym->type)) {
3053           /* do not save WREG,STATUS,BSR for high priority interrupts
3054            * because they are stored in the hardware shadow registers already */
3055           _G.usefastretfie = 0;
3056           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3057           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3058           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3059         }
3060
3061         /* these should really be optimized somehow, because not all
3062          * interrupt handlers modify them */
3063         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3064         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3065         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3066         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3067         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3068         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3069
3070 //        pic16_pBlockConvert2ISR(pb);
3071     }
3072
3073     /* emit code to setup stack frame if user enabled,
3074      * and function is not main() */
3075
3076 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3077     if(strcmp(sym->name, "main")) {
3078       if(0
3079         || !options.ommitFramePtr
3080 //        || sym->regsUsed
3081         || IFFUNC_ARGS(sym->type)
3082         || FUNC_HASSTACKPARM(sym->etype)
3083         ) {
3084         /* setup the stack frame */
3085         if(STACK_MODEL_LARGE)
3086           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3087         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3088
3089         if(STACK_MODEL_LARGE)
3090           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3091         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3092       }
3093     }
3094
3095     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3096           && sym->stack) {
3097
3098       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3099
3100       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3101       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3102       emitSKPC;
3103       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3104     }
3105
3106     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3107       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3108         _G.useWreg = 0;
3109       else
3110         _G.useWreg = 1;
3111     } else
3112       _G.useWreg = 0;
3113
3114     /* if callee-save to be used for this function
3115      * then save the registers being used in this function */
3116 //    if (IFFUNC_CALLEESAVES(sym->type))
3117     if(strcmp(sym->name, "main")) {
3118       int i;
3119
3120         /* if any registers used */
3121         if (sym->regsUsed) {
3122                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3123
3124           if(!pic16_options.xinst) {
3125             /* save the registers used */
3126             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3127             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3128               if (bitVectBitValue(sym->regsUsed,i)) {
3129 #if 0
3130                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3131 #endif
3132                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3133                 _G.nRegsSaved++;
3134
3135                 if(!pic16_regWithIdx(i)->wasUsed) {
3136                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3137                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3138                   pic16_regWithIdx(i)->wasUsed = 1;
3139                 }
3140               }
3141             }
3142           } else {
3143
3144             /* xinst */
3145             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3146             for(i=0;i<sym->regsUsed->size;i++) {
3147               if(bitVectBitValue(sym->regsUsed, i)) {
3148                 _G.nRegsSaved++;
3149               }
3150             }
3151
3152 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3153           }
3154
3155           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3156
3157         }
3158     }
3159
3160     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3161 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3162 }
3163
3164 /*-----------------------------------------------------------------*/
3165 /* genEndFunction - generates epilogue for functions               */
3166 /*-----------------------------------------------------------------*/
3167 static void genEndFunction (iCode *ic)
3168 {
3169   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3170
3171     FENTRY;
3172
3173     if(IFFUNC_ISNAKED(sym->type)) {
3174       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3175       return;
3176     }
3177
3178     _G.stack_lat = 0;
3179
3180     /* add code for ISCRITICAL */
3181     if(IFFUNC_ISCRITICAL(sym->type)) {
3182       /* if critical function, turn on interrupts */
3183
3184       /* TODO: add code here -- VR */
3185     }
3186
3187 //    sym->regsUsed = _G.fregsUsed;
3188
3189     /* now we need to restore the registers */
3190     /* if any registers used */
3191
3192     /* first restore registers that might be used for stack access */
3193     if(_G.sregsAllocSet) {
3194     regs *sr;
3195
3196       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3197       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3198         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3199       }
3200     }
3201
3202     if (strcmp(sym->name, "main") && sym->regsUsed) {
3203       int i;
3204
3205         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3206         /* restore registers used */
3207         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3208         for ( i = sym->regsUsed->size; i >= 0; i--) {
3209           if (bitVectBitValue(sym->regsUsed,i)) {
3210             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3211             _G.nRegsSaved--;
3212           }
3213         }
3214         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3215     }
3216
3217
3218
3219     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3220           && sym->stack) {
3221       if (sym->stack == 1) {
3222         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3223         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3224       } else {
3225         // we have to add more than one...
3226         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3227         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3228         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3229         emitSKPNC;
3230         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3231         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3232         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3233       }
3234     }
3235
3236     if(strcmp(sym->name, "main")) {
3237       if(0
3238         || !options.ommitFramePtr
3239 //        || sym->regsUsed
3240         || IFFUNC_ARGS(sym->type)
3241         || FUNC_HASSTACKPARM(sym->etype)
3242         ) {
3243         /* restore stack frame */
3244         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3245         if(STACK_MODEL_LARGE)
3246           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3247       }
3248     }
3249
3250     _G.useWreg = 0;
3251
3252     if (IFFUNC_ISISR(sym->type)) {
3253       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3254       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3255       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3256       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3257       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3258       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3259
3260       if(!FUNC_ISSHADOWREGS(sym->type)) {
3261         /* do not restore interrupt vector for WREG,STATUS,BSR
3262          * for high priority interrupt, see genFunction */
3263         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3264         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3265         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3266       }
3267 //      _G.interruptvector = 0;         /* sanity check */
3268
3269
3270       /* if debug then send end of function */
3271 /*      if (options.debug && currFunc)  */
3272       if (currFunc) {
3273         debugFile->writeEndFunction (currFunc, ic, 1);
3274       }
3275
3276       if(_G.usefastretfie)
3277         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3278       else
3279         pic16_emitpcodeNULLop(POC_RETFIE);
3280
3281       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3282
3283       _G.usefastretfie = 0;
3284       return;
3285     }
3286
3287     if (IFFUNC_ISCRITICAL(sym->type)) {
3288       pic16_emitcode("setb","ea");
3289     }
3290
3291     /* if debug then send end of function */
3292     if (currFunc) {
3293       debugFile->writeEndFunction (currFunc, ic, 1);
3294     }
3295
3296     /* insert code to restore stack frame, if user enabled it
3297      * and function is not main() */
3298
3299
3300     pic16_emitpcodeNULLop(POC_RETURN);
3301
3302     /* Mark the end of a function */
3303     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3304 }
3305
3306
3307 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3308 {
3309   unsigned long lit=1;
3310   operand *op;
3311
3312     op = IC_LEFT(ic);
3313
3314     // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE)
3315     if(AOP_TYPE(op) == AOP_LIT) {
3316       if(!IS_FLOAT(operandType( op ))) {
3317         lit = ulFromVal (AOP(op)->aopu.aop_lit);
3318       } else {
3319         union {
3320           unsigned long lit_int;
3321           float lit_float;
3322         } info;
3323
3324         /* take care if literal is a float */
3325         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3326         lit = info.lit_int;
3327       }
3328     }
3329
3330     if (AOP_TYPE(op) == AOP_LIT) {
3331       /* FIXME: broken for
3332        *   char __at(0x456) foo;
3333        *   return &foo;
3334        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
3335       pic16_movLit2f(dest, (lit >> (8ul*offset)));
3336     } else if (AOP_TYPE(op) == AOP_PCODE
3337                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3338       /* char *s= "aaa"; return s; */
3339       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
3340        *      that the generic pointer is interpreted correctly
3341        *      as referring to __code space, but this is fragile! */
3342       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
3343       /* XXX: should check that dest != WREG */
3344       pic16_emitpcode(POC_MOVWF, dest);
3345     } else {
3346       if(dest->type == PO_WREG && (offset == 0)) {
3347         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3348         return;
3349       }
3350       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3351     }
3352 }
3353
3354 /*-----------------------------------------------------------------*/
3355 /* genRet - generate code for return statement                     */
3356 /*-----------------------------------------------------------------*/
3357 static void genRet (iCode *ic)
3358 {
3359   int size;
3360   operand *left;
3361
3362     FENTRY;
3363         /* if we have no return value then
3364          * just generate the "ret" */
3365
3366         if (!IC_LEFT(ic))
3367                 goto jumpret;
3368
3369         /* we have something to return then
3370          * move the return value into place */
3371         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3372         size = AOP_SIZE(IC_LEFT(ic));
3373
3374         if(size <= 4) {
3375           if(size>3)
3376             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3377
3378           if(size>2)
3379             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3380
3381           if(size>1)
3382             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3383
3384           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3385
3386         } else {
3387                 /* >32-bits, setup stack and FSR0 */
3388                 while (size--) {
3389 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3390 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3391
3392                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3393
3394 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3395                         GpsuedoStkPtr++;
3396                 }
3397
3398                 /* setup FSR0 */
3399                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3400                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3401
3402                 if(STACK_MODEL_LARGE) {
3403                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3404                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3405                 } else {
3406                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3407                 }
3408         }
3409
3410         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3411
3412 jumpret:
3413         /* generate a jump to the return label
3414          * if the next is not the return statement */
3415         if (!(ic->next && ic->next->op == LABEL
3416                 && IC_LABEL(ic->next) == returnLabel)) {
3417
3418                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3419                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3420         }
3421 }
3422
3423 /*-----------------------------------------------------------------*/
3424 /* genLabel - generates a label                                    */
3425 /*-----------------------------------------------------------------*/
3426 static void genLabel (iCode *ic)
3427 {
3428   FENTRY;
3429
3430   /* special case never generate */
3431   if (IC_LABEL(ic) == entryLabel)
3432     return ;
3433
3434   pic16_emitpLabel(IC_LABEL(ic)->key);
3435 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3436 }
3437
3438 /*-----------------------------------------------------------------*/
3439 /* genGoto - generates a goto                                      */
3440 /*-----------------------------------------------------------------*/
3441 //tsd
3442 static void genGoto (iCode *ic)
3443 {
3444   FENTRY;
3445   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3446 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3447 }
3448
3449
3450 /*-----------------------------------------------------------------*/
3451 /* genMultbits :- multiplication of bits                           */
3452 /*-----------------------------------------------------------------*/
3453 static void genMultbits (operand *left,
3454                          operand *right,
3455                          operand *result)
3456 {
3457   FENTRY;
3458
3459   if(!pic16_sameRegs(AOP(result),AOP(right)))
3460     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3461
3462   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3463   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3464   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3465
3466 }
3467
3468
3469 /*-----------------------------------------------------------------*/
3470 /* genMultOneByte : 8 bit multiplication & division                */
3471 /*-----------------------------------------------------------------*/
3472 static void genMultOneByte (operand *left,
3473                             operand *right,
3474                             operand *result)
3475 {
3476
3477   FENTRY;
3478   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3479   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3480
3481   /* (if two literals, the value is computed before) */
3482   /* if one literal, literal on the right */
3483   if (AOP_TYPE(left) == AOP_LIT){
3484     operand *t = right;
3485     right = left;
3486     left = t;
3487   }
3488
3489         /* size is already checked in genMult == 1 */
3490 //      size = AOP_SIZE(result);
3491
3492         if (AOP_TYPE(right) == AOP_LIT){
3493                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3494                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3495                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3496                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3497         } else {
3498                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3499                                         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3500                                         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3501                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3502         }
3503
3504         pic16_genMult8X8_n (left, right,result);
3505 }
3506
3507 #if 0
3508 /*-----------------------------------------------------------------*/
3509 /* genMultOneWord : 16 bit multiplication                          */
3510 /*-----------------------------------------------------------------*/
3511 static void genMultOneWord (operand *left,
3512                             operand *right,
3513                             operand *result)
3514 {
3515   FENTRY;
3516   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3517   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3518
3519   /* (if two literals, the value is computed before)
3520    * if one literal, literal on the right */
3521   if (AOP_TYPE(left) == AOP_LIT){
3522     operand *t = right;
3523     right = left;
3524     left = t;
3525   }
3526
3527   /* size is checked already == 2 */
3528 //  size = AOP_SIZE(result);
3529
3530   if (AOP_TYPE(right) == AOP_LIT) {
3531     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3532       pic16_aopGet(AOP(right),0,FALSE,FALSE),
3533       pic16_aopGet(AOP(left),0,FALSE,FALSE),
3534       pic16_aopGet(AOP(result),0,FALSE,FALSE));
3535   } else {
3536     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3537       pic16_aopGet(AOP(right),0,FALSE,FALSE),
3538       pic16_aopGet(AOP(left),0,FALSE,FALSE),
3539       pic16_aopGet(AOP(result),0,FALSE,FALSE));
3540   }
3541
3542   pic16_genMult16X16_16(left, right,result);
3543 }
3544 #endif
3545
3546 #if 0
3547 /*-----------------------------------------------------------------*/
3548 /* genMultOneLong : 32 bit multiplication                          */
3549 /*-----------------------------------------------------------------*/
3550 static void genMultOneLong (operand *left,
3551                             operand *right,
3552                             operand *result)
3553 {
3554   FENTRY;
3555   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3556   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3557
3558   /* (if two literals, the value is computed before)
3559    * if one literal, literal on the right */
3560   if (AOP_TYPE(left) == AOP_LIT){
3561     operand *t = right;
3562     right = left;
3563     left = t;
3564   }
3565
3566   /* size is checked already == 4 */
3567 //  size = AOP_SIZE(result);
3568
3569   if (AOP_TYPE(right) == AOP_LIT) {
3570     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s",
3571         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3572         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3573         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3574   } else {
3575     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s",
3576         pic16_aopGet(AOP(right),0,FALSE,FALSE),
3577         pic16_aopGet(AOP(left),0,FALSE,FALSE),
3578         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3579   }
3580
3581   pic16_genMult32X32_32(left, right,result);
3582 }
3583 #endif
3584
3585
3586
3587 /*-----------------------------------------------------------------*/
3588 /* genMult - generates code for multiplication                     */
3589 /*-----------------------------------------------------------------*/
3590 static void genMult (iCode *ic)
3591 {
3592   operand *left = IC_LEFT(ic);
3593   operand *right = IC_RIGHT(ic);
3594   operand *result= IC_RESULT(ic);
3595
3596     FENTRY;
3597         /* assign the amsops */
3598         pic16_aopOp (left,ic,FALSE);
3599         pic16_aopOp (right,ic,FALSE);
3600         pic16_aopOp (result,ic,TRUE);
3601
3602         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3603
3604         /* special cases first *
3605         * both are bits */
3606         if (AOP_TYPE(left) == AOP_CRY
3607                 && AOP_TYPE(right)== AOP_CRY) {
3608                 genMultbits(left,right,result);
3609           goto release ;
3610         }
3611
3612         /* if both are of size == 1 */
3613         if(AOP_SIZE(left) == 1
3614                 && AOP_SIZE(right) == 1) {
3615                 genMultOneByte(left,right,result);
3616           goto release ;
3617         }
3618
3619 #if 0
3620         /* if both are of size == 2 */
3621         if(AOP_SIZE(left) == 2
3622                 && AOP_SIZE(right) == 2) {
3623                 genMultOneWord(left, right, result);
3624           goto release;
3625         }
3626
3627         /* if both are of size == 4 */
3628         if(AOP_SIZE(left) == 4
3629                 && AOP_SIZE(right) == 4) {
3630                 genMultOneLong(left, right, result);
3631           goto release;
3632         }
3633 #endif
3634
3635         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
3636         assert( !"Multiplication should have been transformed into function call!" );
3637
3638         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3639
3640
3641         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3642         /* should have been converted to function call */
3643         assert(0) ;
3644
3645 release :
3646         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3647         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3648         pic16_freeAsmop(result,NULL,ic,TRUE);
3649 }
3650
3651 #if 0
3652 /*-----------------------------------------------------------------*/
3653 /* genDivbits :- division of bits                                  */
3654 /*-----------------------------------------------------------------*/
3655 static void genDivbits (operand *left,
3656                         operand *right,
3657                         operand *result)
3658 {
3659   char *l;
3660
3661     FENTRY;
3662     /* the result must be bit */
3663     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3664     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3665
3666     MOVA(l);
3667
3668     pic16_emitcode("div","ab");
3669     pic16_emitcode("rrc","a");
3670     pic16_aopPut(AOP(result),"c",0);
3671 }
3672
3673 /*-----------------------------------------------------------------*/
3674 /* genDivOneByte : 8 bit division                                  */
3675 /*-----------------------------------------------------------------*/
3676 static void genDivOneByte (operand *left,
3677                            operand *right,
3678                            operand *result)
3679 {
3680   sym_link *opetype = operandType(result);
3681   char *l ;
3682   symbol *lbl ;
3683   int size,offset;
3684
3685         /* result = divident / divisor
3686          * - divident may be a register or a literal,
3687          * - divisor may be a register or a literal,
3688          * so there are 3 cases (literal / literal is optimized
3689          * by the front-end) to handle.
3690          * In addition we must handle signed and unsigned, which
3691          * result in 6 final different cases -- VR */
3692
3693     FENTRY;
3694
3695     size = AOP_SIZE(result) - 1;
3696     offset = 1;
3697     /* signed or unsigned */
3698     if (SPEC_USIGN(opetype)) {
3699       pCodeOp *pct1,    /* count */
3700                 *pct2,  /* reste */
3701                 *pct3;  /* temp */
3702       symbol *label1, *label2, *label3;;
3703
3704
3705         /* unsigned is easy */
3706
3707         pct1 = pic16_popGetTempReg(1);
3708         pct2 = pic16_popGetTempReg(1);
3709         pct3 = pic16_popGetTempReg(1);
3710
3711         label1 = newiTempLabel(NULL);
3712         label2 = newiTempLabel(NULL);
3713         label3 = newiTempLabel(NULL);
3714
3715         /* the following algorithm is extracted from divuint.c */
3716
3717         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
3718         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
3719
3720         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
3721
3722         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
3723
3724         pic16_emitpLabel(label1->key);
3725
3726         emitCLRC;
3727         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
3728
3729
3730         emitCLRC;
3731         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
3732
3733
3734         emitSKPNC;
3735         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
3736
3737         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
3738         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
3739
3740         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
3741         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
3742         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
3743
3744         pic16_emitpLabel( label3->key );
3745         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
3746         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
3747
3748
3749
3750         pic16_emitpLabel(label2->key);
3751         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
3752         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
3753         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
3754
3755         /* result is in wreg */
3756         if(AOP_TYPE(result) != AOP_ACC)
3757                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3758
3759         pic16_popReleaseTempReg( pct3, 1);
3760         pic16_popReleaseTempReg( pct2, 1);
3761         pic16_popReleaseTempReg( pct1, 1);
3762
3763         return ;
3764     }
3765
3766     /* signed is a little bit more difficult */
3767
3768     /* save the signs of the operands */
3769     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3770     MOVA(l);
3771     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3772     pic16_emitcode("push","acc"); /* save it on the stack */
3773
3774     /* now sign adjust for both left & right */
3775     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
3776     MOVA(l);
3777     lbl = newiTempLabel(NULL);
3778     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3779     pic16_emitcode("cpl","a");
3780     pic16_emitcode("inc","a");
3781     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3782     pic16_emitcode("mov","b,a");
3783
3784     /* sign adjust left side */
3785     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
3786     MOVA(l);
3787
3788     lbl = newiTempLabel(NULL);
3789     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3790     pic16_emitcode("cpl","a");
3791     pic16_emitcode("inc","a");
3792     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3793
3794     /* now the division */
3795     pic16_emitcode("div","ab");
3796     /* we are interested in the lower order
3797     only */
3798     pic16_emitcode("mov","b,a");
3799     lbl = newiTempLabel(NULL);
3800     pic16_emitcode("pop","acc");
3801     /* if there was an over flow we don't
3802     adjust the sign of the result */
3803     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3804     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3805     CLRC;
3806     pic16_emitcode("clr","a");
3807     pic16_emitcode("subb","a,b");
3808     pic16_emitcode("mov","b,a");
3809     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3810
3811     /* now we are done */
3812     pic16_aopPut(AOP(result),"b",0);
3813     if(size > 0){
3814         pic16_emitcode("mov","c,b.7");
3815         pic16_emitcode("subb","a,acc");
3816     }
3817     while (size--)
3818         pic16_aopPut(AOP(result),"a",offset++);
3819
3820 }
3821 #endif
3822
3823 /*-----------------------------------------------------------------*/
3824 /* genDiv - generates code for division                            */
3825 /*-----------------------------------------------------------------*/
3826 static void genDiv (iCode *ic)
3827 {
3828     operand *left = IC_LEFT(ic);
3829     operand *right = IC_RIGHT(ic);
3830     operand *result= IC_RESULT(ic);
3831     int negated = 0;
3832     int leftVal = 0, rightVal = 0;
3833     int signedLits = 0;
3834     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
3835     int op = 0;
3836
3837         /* Division is a very lengthy algorithm, so it is better
3838          * to call support routines than inlining algorithm.
3839          * Division functions written here just in case someone
3840          * wants to inline and not use the support libraries -- VR */
3841
3842     FENTRY;
3843
3844     /* assign the amsops */
3845     pic16_aopOp (left,ic,FALSE);
3846     pic16_aopOp (right,ic,FALSE);
3847     pic16_aopOp (result,ic,TRUE);
3848
3849     if (ic->op == '/')
3850       op = 0;
3851     else if (ic->op == '%')
3852       op = 1;
3853     else
3854       assert( !"invalid operation requested in genDivMod" );
3855
3856     /* get literal values */
3857     if (IS_VALOP(left)) {
3858       leftVal = (int) ulFromVal ( OP_VALUE(left) );
3859       assert( leftVal >= -128 && leftVal < 256 );
3860       if (leftVal < 0) { signedLits++; }
3861     }
3862     if (IS_VALOP(right)) {
3863       rightVal = (int) ulFromVal ( OP_VALUE(right) );
3864       assert( rightVal >= -128 && rightVal < 256 );
3865       if (rightVal < 0) { signedLits++; }
3866     }
3867
3868     /* We should only come here to convert all
3869      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
3870      * with exactly one operand being s8_t into
3871      * u8_t x u8_t -> u8_t. All other cases should have been
3872      * turned into calls to support routines beforehand... */
3873     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
3874         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
3875     {
3876       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
3877           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
3878       {
3879         /* Both operands are signed or negative, use _divschar
3880          * instead of _divuchar */
3881         pushaop(AOP(right), 0);
3882         pushaop(AOP(left), 0);
3883
3884         /* call _divschar */
3885         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
3886
3887         {
3888           symbol *sym;
3889           sym = newSymbol( functions[op][0], 0 );
3890           sym->used++;
3891           strcpy(sym->rname, functions[op][0]);
3892           checkAddSym(&externs, sym);
3893         }
3894
3895         /* assign result */
3896         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
3897         if (AOP_SIZE(result) > 1)
3898         {
3899           pic16_emitpcode(POC_MOVFF,
3900               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
3901                 pic16_popGet(AOP(result), 1)));
3902           /* sign extend */
3903           pic16_addSign(result, 2, 1);
3904         }
3905
3906         /* clean up stack */
3907         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3908         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
3909
3910         goto release;
3911       }
3912
3913       /* push right operand */
3914       if (IS_VALOP(right)) {
3915         if (rightVal < 0) {
3916           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
3917           negated++;
3918         } else {
3919           pushaop(AOP(right), 0);
3920         }
3921       } else if (!IS_UNSIGNED(operandType(right))) {
3922         pic16_mov2w(AOP(right), 0);
3923         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3924         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3925         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3926         negated++;
3927       } else {
3928         pushaop(AOP(right), 0);
3929       }
3930
3931       /* push left operand */
3932       if (IS_VALOP(left)) {
3933         if (leftVal < 0) {
3934           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
3935           negated++;
3936         } else {
3937           pushaop(AOP(left), 0);
3938         }
3939       } else if (!IS_UNSIGNED(operandType(left))) {
3940         pic16_mov2w(AOP(left),0);
3941         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3942         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3943         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
3944         negated++;
3945       } else {
3946         pushaop(AOP(left), 0);
3947       }
3948
3949       /* call _divuchar */
3950       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
3951
3952       {
3953         symbol *sym;
3954         sym = newSymbol( functions[op][1], 0 );
3955         sym->used++;
3956         strcpy(sym->rname, functions[op][1]);
3957         checkAddSym(&externs, sym);
3958       }
3959
3960       /* Revert negation(s) from above.
3961        * This is inefficient: if both operands are negative, this
3962        * should not touch WREG. However, determining that exactly
3963        * one operand was negated costs at least 3 instructions,
3964        * so there is nothing to be gained here, is there?
3965        *
3966        * I negate WREG because either operand might share registers with
3967        * result, so assigning first might destroy an operand. */
3968
3969       /* For the modulus operator, (a/b)*b == a shall hold.
3970        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
3971        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
3972        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
3973        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
3974        * Only invert the result if the left operand is negative (sigh).
3975        */
3976       if (AOP_SIZE(result) <= 1 || !negated)
3977       {
3978         if (ic->op == '/')
3979         {
3980           if (IS_VALOP(right)) {
3981             if (rightVal < 0) {
3982               /* we negated this operand above */
3983               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3984             }
3985           } else if (!IS_UNSIGNED(operandType(right))) {
3986             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
3987             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3988           }
3989         }
3990
3991         if (IS_VALOP(left)) {
3992           if (leftVal < 0) {
3993             /* we negated this operand above */
3994             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3995           }
3996         } else if (!IS_UNSIGNED(operandType(left))) {
3997           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
3998           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
3999         }
4000
4001         /* Move result to destination. */
4002         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4003
4004         /* Zero-extend:  no operand was signed (or result is just a byte). */
4005         pic16_addSign(result, 1, 0);
4006       } else {
4007         assert( AOP_SIZE(result) > 1 );
4008         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4009         if (ic->op == '/')
4010         {
4011           if (IS_VALOP(right)) {
4012             if (rightVal < 0) {
4013               /* we negated this operand above */
4014               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4015             }
4016           } else if (!IS_UNSIGNED(operandType(right))) {
4017             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4018             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4019           }
4020         }
4021
4022         if (IS_VALOP(left)) {
4023           if (leftVal < 0) {
4024             /* we negated this operand above */
4025             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4026           }
4027         } else if (!IS_UNSIGNED(operandType(left))) {
4028           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4029           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4030         }
4031
4032         /* Move result to destination. */
4033         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4034
4035         /* Negate result if required. */
4036         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4037         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4038
4039         /* Sign-extend. */
4040         pic16_addSign(result, 2, 1);
4041       }
4042
4043       /* clean up stack */
4044       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4045       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4046       goto release;
4047     }
4048
4049 #if 0
4050     /* special cases first */
4051     /* both are bits */
4052     if (AOP_TYPE(left) == AOP_CRY &&
4053         AOP_TYPE(right)== AOP_CRY) {
4054         genDivbits(left,right,result);
4055         goto release ;
4056     }
4057
4058     /* if both are of size == 1 */
4059     if (AOP_SIZE(left) == 1 &&
4060         AOP_SIZE(right) == 1 ) {
4061         genDivOneByte(left,right,result);
4062         goto release ;
4063     }
4064 #endif
4065
4066     /* should have been converted to function call */
4067     assert(0);
4068 release :
4069     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4070     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4071     pic16_freeAsmop(result,NULL,ic,TRUE);
4072 }
4073
4074 #if 0
4075 /*-----------------------------------------------------------------*/
4076 /* genModbits :- modulus of bits                                   */
4077 /*-----------------------------------------------------------------*/
4078 static void genModbits (operand *left,
4079                         operand *right,
4080                         operand *result)
4081 {
4082   char *l;
4083
4084     FENTRY;
4085
4086     werror(W_POSSBUG2, __FILE__, __LINE__);
4087     /* the result must be bit */
4088     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4089     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4090
4091     MOVA(l);
4092
4093     pic16_emitcode("div","ab");
4094     pic16_emitcode("mov","a,b");
4095     pic16_emitcode("rrc","a");
4096     pic16_aopPut(AOP(result),"c",0);
4097 }
4098
4099 /*-----------------------------------------------------------------*/
4100 /* genModOneByte : 8 bit modulus                                   */
4101 /*-----------------------------------------------------------------*/
4102 static void genModOneByte (operand *left,
4103                            operand *right,
4104                            operand *result)
4105 {
4106   sym_link *opetype = operandType(result);
4107   char *l ;
4108   symbol *lbl ;
4109
4110     FENTRY;
4111     werror(W_POSSBUG2, __FILE__, __LINE__);
4112
4113     /* signed or unsigned */
4114     if (SPEC_USIGN(opetype)) {
4115         /* unsigned is easy */
4116         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4117         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4118         MOVA(l);
4119         pic16_emitcode("div","ab");
4120         pic16_aopPut(AOP(result),"b",0);
4121         return ;
4122     }
4123
4124     /* signed is a little bit more difficult */
4125
4126     /* save the signs of the operands */
4127     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4128     MOVA(l);
4129
4130     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4131     pic16_emitcode("push","acc"); /* save it on the stack */
4132
4133     /* now sign adjust for both left & right */
4134     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);
4135     MOVA(l);
4136
4137     lbl = newiTempLabel(NULL);
4138     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4139     pic16_emitcode("cpl","a");
4140     pic16_emitcode("inc","a");
4141     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4142     pic16_emitcode("mov","b,a");
4143
4144     /* sign adjust left side */
4145     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);
4146     MOVA(l);
4147
4148     lbl = newiTempLabel(NULL);
4149     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4150     pic16_emitcode("cpl","a");
4151     pic16_emitcode("inc","a");
4152     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4153
4154     /* now the multiplication */
4155     pic16_emitcode("div","ab");
4156     /* we are interested in the lower order
4157     only */
4158     lbl = newiTempLabel(NULL);
4159     pic16_emitcode("pop","acc");
4160     /* if there was an over flow we don't
4161     adjust the sign of the result */
4162     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4163     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4164     CLRC ;
4165     pic16_emitcode("clr","a");
4166     pic16_emitcode("subb","a,b");
4167     pic16_emitcode("mov","b,a");
4168     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4169
4170     /* now we are done */
4171     pic16_aopPut(AOP(result),"b",0);
4172
4173 }
4174 #endif
4175
4176 /*-----------------------------------------------------------------*/
4177 /* genMod - generates code for division                            */
4178 /*-----------------------------------------------------------------*/
4179 static void genMod (iCode *ic)
4180 {
4181   /* Task deferred to genDiv */
4182   genDiv(ic);
4183 #if 0
4184   operand *left = IC_LEFT(ic);
4185   operand *right = IC_RIGHT(ic);
4186   operand *result= IC_RESULT(ic);
4187
4188     FENTRY;
4189
4190     /* assign the amsops */
4191     pic16_aopOp (left,ic,FALSE);
4192     pic16_aopOp (right,ic,FALSE);
4193     pic16_aopOp (result,ic,TRUE);
4194
4195     /* special cases first */
4196     /* both are bits */
4197     if (AOP_TYPE(left) == AOP_CRY &&
4198         AOP_TYPE(right)== AOP_CRY) {
4199         genModbits(left,right,result);
4200         goto release ;
4201     }
4202
4203     /* if both are of size == 1 */
4204     if (AOP_SIZE(left) == 1 &&
4205         AOP_SIZE(right) == 1 ) {
4206         genModOneByte(left,right,result);
4207         goto release ;
4208     }
4209
4210     /* should have been converted to function call */
4211     assert(0);
4212
4213 release :
4214     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4215     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4216     pic16_freeAsmop(result,NULL,ic,TRUE);
4217 #endif
4218 }
4219
4220 /*-----------------------------------------------------------------*/
4221 /* genIfxJump :- will create a jump depending on the ifx           */
4222 /*-----------------------------------------------------------------*/
4223 /*
4224   note: May need to add parameter to indicate when a variable is in bit space.
4225 */
4226 static void genIfxJump (iCode *ic, char *jval)
4227 {
4228   FENTRY;
4229
4230     /* if true label then we jump if condition
4231     supplied is true */
4232     if ( IC_TRUE(ic) ) {
4233
4234         if(strcmp(jval,"a") == 0)
4235           emitSKPZ;
4236         else if (strcmp(jval,"c") == 0)
4237           emitSKPNC;
4238         else {
4239           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4240           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4241         }
4242
4243         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4244         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4245
4246     }
4247     else {
4248         /* false label is present */
4249         if(strcmp(jval,"a") == 0)
4250           emitSKPNZ;
4251         else if (strcmp(jval,"c") == 0)
4252           emitSKPC;
4253         else {
4254           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);
4255           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4256         }
4257
4258         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4259         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4260
4261     }
4262
4263
4264     /* mark the icode as generated */
4265     ic->generated = 1;
4266 }
4267
4268 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4269 {
4270   FENTRY;
4271
4272     /* if true label then we jump if condition
4273     supplied is true */
4274     if ( IC_TRUE(ic) ) {
4275       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4276       pic16_emitpcode(POC_BTFSC, jop);
4277
4278       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4279       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4280
4281     } else {
4282       /* false label is present */
4283       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4284       pic16_emitpcode(POC_BTFSS, jop);
4285
4286       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4287       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4288     }
4289
4290
4291     /* mark the icode as generated */
4292     ic->generated = 1;
4293 }
4294
4295 #if 0
4296 // not needed ATM
4297
4298 /*-----------------------------------------------------------------*/
4299 /* genSkip                                                         */
4300 /*-----------------------------------------------------------------*/
4301 static void genSkip(iCode *ifx,int status_bit)
4302 {
4303   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4304   if(!ifx)
4305     return;
4306
4307   if ( IC_TRUE(ifx) ) {
4308     switch(status_bit) {
4309     case 'z':
4310       emitSKPNZ;
4311       break;
4312
4313     case 'c':
4314       emitSKPNC;
4315       break;
4316
4317     case 'd':
4318       emitSKPDC;
4319       break;
4320
4321     }
4322
4323     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4324     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4325
4326   } else {
4327
4328     switch(status_bit) {
4329
4330     case 'z':
4331       emitSKPZ;
4332       break;
4333
4334     case 'c':
4335       emitSKPC;
4336       break;
4337
4338     case 'd':
4339       emitSKPDC;
4340       break;
4341     }
4342     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4343     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4344
4345   }
4346
4347 }
4348 #endif
4349
4350 /*-----------------------------------------------------------------*/
4351 /* genSkipc                                                        */
4352 /*-----------------------------------------------------------------*/
4353 static void genSkipc(resolvedIfx *rifx)
4354 {
4355   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4356
4357   if(!rifx)
4358     return;
4359
4360   if(rifx->condition)
4361     emitSKPNC;
4362   else
4363     emitSKPC;
4364
4365   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4366   rifx->generated = 1;
4367 }
4368
4369 /*-----------------------------------------------------------------*/
4370 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4371 /*                  aop (if it's NOT a literal) or from lit (if    */
4372 /*                  aop is a literal)                              */
4373 /*-----------------------------------------------------------------*/
4374 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4375   if (aop->type == AOP_LIT) {
4376     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4377   } else {
4378     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4379   }
4380 }
4381
4382 /*-----------------------------------------------------------------*/
4383 /* genCmp :- greater or less than comparison                       */
4384 /*-----------------------------------------------------------------*/
4385
4386 /* genCmp performs a left < right comparison, stores
4387  * the outcome in result (if != NULL) and generates
4388  * control flow code for the ifx (if != NULL).
4389  *
4390  * This version leaves in sequences like
4391  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4392  * which should be optmized by the peephole
4393  * optimizer - RN 2005-01-01 */
4394 static void genCmp (operand *left,operand *right,
4395                     operand *result, iCode *ifx, int sign)
4396 {
4397   resolvedIfx rIfx;
4398   int size;
4399   int offs;
4400   symbol *templbl;
4401   operand *dummy;
4402   unsigned long lit;
4403   unsigned long mask;
4404   int performedLt;
4405
4406   FENTRY;
4407
4408   assert (left && right);
4409   assert (AOP_SIZE(left) == AOP_SIZE(right));
4410
4411   size = AOP_SIZE(right) - 1;
4412   mask = (0x100UL << (size*8)) - 1;
4413   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4414   performedLt = 1;
4415   templbl = NULL;
4416   lit = 0;
4417
4418   resolveIfx (&rIfx, ifx);
4419
4420   /* handle for special cases */
4421   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4422       return;
4423
4424   /**********************************************************************
4425    * handle bits - bit compares are promoted to int compares seemingly! *
4426    **********************************************************************/
4427 #if 0
4428   // THIS IS COMPLETELY UNTESTED!
4429   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4430     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4431     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4432     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4433
4434     emitSETC;
4435     // 1 < {0,1} is false --> clear C by skipping the next instruction
4436     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4437     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4438     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4439     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4440     emitCLRC; // only skipped for left=0 && right=1
4441
4442     goto correct_result_in_carry;
4443   } // if
4444 #endif
4445
4446   /*************************************************
4447    * make sure that left is register (or the like) *
4448    *************************************************/
4449   if (!isAOP_REGlike(left)) {
4450     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4451     assert (isAOP_LIT(left));
4452     assert (isAOP_REGlike(right));
4453     // swap left and right
4454     // left < right <==> right > left <==> (right >= left + 1)
4455     lit = ulFromVal (AOP(left)->aopu.aop_lit);
4456
4457     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4458       // MAXVALUE < right? always false
4459       if (performedLt) emitCLRC; else emitSETC;
4460       goto correct_result_in_carry;
4461     } // if
4462
4463     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4464     // that's why we handled it above.
4465     lit++;
4466
4467     dummy = left;
4468     left = right;
4469     right = dummy;
4470
4471     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4472   } else if (isAOP_LIT(right)) {
4473     lit = ulFromVal (AOP(right)->aopu.aop_lit);
4474   } // if
4475
4476   assert (isAOP_REGlike(left)); // left must be register or the like
4477   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4478
4479   /*************************************************
4480    * special cases go here                         *
4481    *************************************************/
4482
4483   if (isAOP_LIT(right)) {
4484     if (!sign) {
4485       // unsigned comparison to a literal
4486       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4487       if (lit == 0) {
4488         // unsigned left < 0? always false
4489         if (performedLt) emitCLRC; else emitSETC;
4490         goto correct_result_in_carry;
4491       }
4492     } else {
4493       // signed comparison to a literal
4494       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4495       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4496         // signed left < 0x80000000? always false
4497         if (performedLt) emitCLRC; else emitSETC;
4498         goto correct_result_in_carry;
4499       } else if (lit == 0) {
4500         // compare left < 0; set CARRY if SIGNBIT(left) is set
4501         if (performedLt) emitSETC; else emitCLRC;
4502         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4503         if (performedLt) emitCLRC; else emitSETC;
4504         goto correct_result_in_carry;
4505       }
4506     } // if (!sign)
4507   } // right is literal
4508
4509   /*************************************************
4510    * perform a general case comparison             *
4511    * make sure we get CARRY==1 <==> left >= right  *
4512    *************************************************/
4513   // compare most significant bytes
4514   //DEBUGpc ("comparing bytes at offset %d", size);
4515   if (!sign) {
4516     // unsigned comparison
4517     mov2w_regOrLit (AOP(right), lit, size);
4518     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
4519   } else {
4520     // signed comparison
4521     // (add 2^n to both operands then perform an unsigned comparison)
4522     if (isAOP_LIT(right)) {
4523       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4524       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4525
4526       if (litbyte == 0x80) {
4527         // left >= 0x80 -- always true, but more bytes to come
4528         pic16_mov2w (AOP(left), size);
4529         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
4530         emitSETC;
4531       } else {
4532         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4533         pic16_mov2w (AOP(left), size);
4534         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4535         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4536       } // if
4537     } else {
4538       /* using PRODL as a temporary register here */
4539       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
4540       //pCodeOp *pctemp = pic16_popGetTempReg(1);
4541       pic16_mov2w (AOP(left), size);
4542       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4543       pic16_emitpcode (POC_MOVWF, pctemp);
4544       pic16_mov2w (AOP(right), size);
4545       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
4546       pic16_emitpcode (POC_SUBFW, pctemp);
4547       //pic16_popReleaseTempReg(pctemp, 1);
4548     }
4549   } // if (!sign)
4550
4551   // compare remaining bytes (treat as unsigned case from above)
4552   templbl = newiTempLabel ( NULL );
4553   offs = size;
4554   while (offs--) {
4555     //DEBUGpc ("comparing bytes at offset %d", offs);
4556     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
4557     mov2w_regOrLit (AOP(right), lit, offs);
4558     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
4559   } // while (offs)
4560   pic16_emitpLabel (templbl->key);
4561   goto result_in_carry;
4562
4563 result_in_carry:
4564
4565   /****************************************************
4566    * now CARRY contains the result of the comparison: *
4567    * SUBWF sets CARRY iff                             *
4568    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4569    * (F=left, W=right)                                *
4570    ****************************************************/
4571
4572   if (performedLt) {
4573     if (result && AOP_TYPE(result) != AOP_CRY) {
4574       // value will be stored
4575       emitTOGC;
4576     } else {
4577       // value wil only be used in the following genSkipc()
4578       rIfx.condition ^= 1;
4579     }
4580   } // if
4581
4582 correct_result_in_carry:
4583
4584   // assign result to variable (if neccessary)
4585   if (result && AOP_TYPE(result) != AOP_CRY) {
4586     //DEBUGpc ("assign result");
4587     size = AOP_SIZE(result);
4588     while (size--) {
4589       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
4590     } // while
4591     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
4592   } // if (result)
4593
4594   // perform conditional jump
4595   if (ifx) {
4596     //DEBUGpc ("generate control flow");
4597     genSkipc (&rIfx);
4598     ifx->generated = 1;
4599   } // if
4600 }
4601
4602 /*-----------------------------------------------------------------*/
4603 /* genCmpGt :- greater than comparison                             */
4604 /*-----------------------------------------------------------------*/
4605 static void genCmpGt (iCode *ic, iCode *ifx)
4606 {
4607   operand *left, *right, *result;
4608   sym_link *letype , *retype;
4609   int sign ;
4610
4611     FENTRY;
4612
4613     left = IC_LEFT(ic);
4614     right= IC_RIGHT(ic);
4615     result = IC_RESULT(ic);
4616
4617     letype = getSpec(operandType(left));
4618     retype =getSpec(operandType(right));
4619     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4620     /* assign the amsops */
4621     pic16_aopOp (left,ic,FALSE);
4622     pic16_aopOp (right,ic,FALSE);
4623     pic16_aopOp (result,ic,TRUE);
4624
4625     genCmp(right, left, result, ifx, sign);
4626
4627     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4628     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4629     pic16_freeAsmop(result,NULL,ic,TRUE);
4630 }
4631
4632 /*-----------------------------------------------------------------*/
4633 /* genCmpLt - less than comparisons                                */
4634 /*-----------------------------------------------------------------*/
4635 static void genCmpLt (iCode *ic, iCode *ifx)
4636 {
4637   operand *left, *right, *result;
4638   sym_link *letype , *retype;
4639   int sign ;
4640
4641     FENTRY;
4642
4643     left = IC_LEFT(ic);
4644     right= IC_RIGHT(ic);
4645     result = IC_RESULT(ic);
4646
4647     letype = getSpec(operandType(left));
4648     retype =getSpec(operandType(right));
4649     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4650
4651     /* assign the amsops */
4652     pic16_aopOp (left,ic,FALSE);
4653     pic16_aopOp (right,ic,FALSE);
4654     pic16_aopOp (result,ic,TRUE);
4655
4656     genCmp(left, right, result, ifx, sign);
4657
4658     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4659     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4660     pic16_freeAsmop(result,NULL,ic,TRUE);
4661 }
4662
4663 /*-----------------------------------------------------------------*/
4664 /* pic16_isLitOp - check if operand has to be treated as literal   */
4665 /*-----------------------------------------------------------------*/
4666 bool pic16_isLitOp(operand *op)
4667 {
4668   return ((AOP_TYPE(op) == AOP_LIT)
4669       || ( (AOP_TYPE(op) == AOP_PCODE)
4670           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
4671               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
4672 }
4673
4674 /*-----------------------------------------------------------------*/
4675 /* pic16_isLitAop - check if operand has to be treated as literal  */
4676 /*-----------------------------------------------------------------*/
4677 bool pic16_isLitAop(asmop *aop)
4678 {
4679   return ((aop->type == AOP_LIT)
4680       || ( (aop->type == AOP_PCODE)
4681           && ( (aop->aopu.pcop->type == PO_LITERAL)
4682               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
4683 }
4684
4685
4686
4687 /*-----------------------------------------------------------------*/
4688 /* genCmpEq - generates code for equal to                          */
4689 /*-----------------------------------------------------------------*/
4690 static void genCmpEq (iCode *ic, iCode *ifx)
4691 {
4692   operand *left, *right, *result;
4693   symbol *falselbl = newiTempLabel(NULL);
4694   symbol *donelbl = newiTempLabel(NULL);
4695
4696   int preserve_result = 0;
4697   int generate_result = 0;
4698   int i=0;
4699   unsigned long lit = -1;
4700
4701   FENTRY;
4702
4703   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4704   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4705   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4706
4707   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4708
4709   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
4710     {
4711       werror(W_POSSBUG2, __FILE__, __LINE__);
4712       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4713       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
4714       goto release;
4715     }
4716
4717   if (pic16_isLitOp(left) || (AOP_TYPE(right) == AOP_ACC))
4718     {
4719       operand *tmp = right ;
4720       right = left;
4721       left = tmp;
4722     }
4723
4724   if (AOP_TYPE(right) == AOP_LIT) {
4725     lit = ulFromVal (AOP(right)->aopu.aop_lit);
4726   }
4727
4728   if ( regsInCommon(left, result) || regsInCommon(right, result) )
4729     preserve_result = 1;
4730
4731   if(result && AOP_SIZE(result))
4732     generate_result = 1;
4733
4734   if(generate_result && !preserve_result)
4735     {
4736       for(i = 0; i < AOP_SIZE(result); i++)
4737         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4738     }
4739
4740   assert( AOP_SIZE(left) == AOP_SIZE(right) );
4741   for(i=0; i < AOP_SIZE(left); i++)
4742     {
4743       if(AOP_TYPE(left) != AOP_ACC)
4744         {
4745           if(pic16_isLitOp(left))
4746             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
4747           else
4748             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
4749         }
4750       if(pic16_isLitOp(right)) {
4751         if (pic16_isLitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
4752           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i));
4753         }
4754       } else
4755         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i));
4756
4757       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
4758     }
4759
4760   // result == true
4761
4762   if(generate_result && preserve_result)
4763     {
4764       for(i = 0; i < AOP_SIZE(result); i++)
4765         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4766     }
4767
4768   if(generate_result)
4769     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
4770
4771   if(generate_result && preserve_result)
4772     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4773
4774   if(ifx && IC_TRUE(ifx))
4775     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4776
4777   if(ifx && IC_FALSE(ifx))
4778     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
4779
4780   pic16_emitpLabel(falselbl->key);
4781
4782   // result == false
4783
4784   if(ifx && IC_FALSE(ifx))
4785     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4786
4787   if(generate_result && preserve_result)
4788     {
4789       for(i = 0; i < AOP_SIZE(result); i++)
4790         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
4791     }
4792
4793   pic16_emitpLabel(donelbl->key);
4794
4795   if(ifx)
4796     ifx->generated = 1;
4797
4798 release:
4799   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4800   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4801   pic16_freeAsmop(result,NULL,ic,TRUE);
4802
4803 }
4804
4805
4806 #if 0
4807 // old version kept for reference
4808
4809 /*-----------------------------------------------------------------*/
4810 /* genCmpEq - generates code for equal to                          */
4811 /*-----------------------------------------------------------------*/
4812 static void genCmpEq (iCode *ic, iCode *ifx)
4813 {
4814     operand *left, *right, *result;
4815     unsigned long lit = 0L;
4816     int size,offset=0;
4817     symbol *falselbl  = newiTempLabel(NULL);
4818
4819
4820     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4821
4822     if(ifx)
4823       DEBUGpic16_emitcode ("; ifx is non-null","");
4824     else
4825       DEBUGpic16_emitcode ("; ifx is null","");
4826
4827     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4828     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4829     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4830
4831     size = max(AOP_SIZE(left),AOP_SIZE(right));
4832
4833     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4834
4835     /* if literal, literal on the right or
4836     if the right is in a pointer register and left
4837     is not */
4838     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)) {
4839       operand *tmp = right ;
4840       right = left;
4841       left = tmp;
4842     }
4843
4844
4845     if(ifx && !AOP_SIZE(result)){
4846         symbol *tlbl;
4847         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
4848         /* if they are both bit variables */
4849         if (AOP_TYPE(left) == AOP_CRY &&
4850             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4851                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
4852             if(AOP_TYPE(right) == AOP_LIT){
4853                 unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
4854                 if(lit == 0L){
4855                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4856                     pic16_emitcode("cpl","c");
4857                 } else if(lit == 1L) {
4858                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4859                 } else {
4860                     pic16_emitcode("clr","c");
4861                 }
4862                 /* AOP_TYPE(right) == AOP_CRY */
4863             } else {
4864                 symbol *lbl = newiTempLabel(NULL);
4865                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4866                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4867                 pic16_emitcode("cpl","c");
4868                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4869             }
4870             /* if true label then we jump if condition
4871             supplied is true */
4872             tlbl = newiTempLabel(NULL);
4873             if ( IC_TRUE(ifx) ) {
4874                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
4875                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4876             } else {
4877                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
4878                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4879             }
4880             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
4881
4882                 {
4883                 /* left and right are both bit variables, result is carry */
4884                         resolvedIfx rIfx;
4885
4886                         resolveIfx(&rIfx,ifx);
4887
4888                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
4889                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
4890                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4891                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
4892                         genSkipz2(&rIfx,0);
4893                 }
4894         } else {
4895
4896                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
4897
4898                         /* They're not both bit variables. Is the right a literal? */
4899                         if(AOP_TYPE(right) == AOP_LIT) {
4900                         lit = ulFromVal (AOP(right)->aopu.aop_lit);
4901
4902                         switch(size) {
4903
4904                                 case 1:
4905                                         switch(lit & 0xff) {
4906                                                 case 1:
4907                                                                 if ( IC_TRUE(ifx) ) {
4908                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
4909                                                                         emitSKPNZ;
4910                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4911                                                                 } else {
4912                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4913                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4914                                                                 }
4915                                                                 break;
4916                                                 case 0xff:
4917                                                                 if ( IC_TRUE(ifx) ) {
4918                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
4919                                                                         emitSKPNZ;
4920                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4921                                                                 } else {
4922                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4923                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4924                                                                 }
4925                                                                 break;
4926                                                 default:
4927                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4928                                                                 if(lit)
4929                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4930                                                                 genSkip(ifx,'z');
4931                                         } // switch lit
4932
4933
4934                                         /* end of size == 1 */
4935                                         break;
4936
4937                                 case 2:
4938                                         genc16bit2lit(left,lit,offset);
4939                                         genSkip(ifx,'z');
4940                                         break;
4941                                         /* end of size == 2 */
4942
4943                                 default:
4944                                         /* size is 4 */
4945                                         if(lit==0) {
4946                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
4947                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
4948                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4949                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4950                                                 genSkip(ifx,'z');
4951                                         } else {
4952                                                 /* search for patterns that can be optimized */
4953
4954                                                 genc16bit2lit(left,lit,0);
4955                                                 lit >>= 16;
4956                                                 if(lit) {
4957                                                                 if(IC_TRUE(ifx))
4958                                                                 emitSKPZ; // if hi word unequal
4959                                                                 else
4960                                                                 emitSKPNZ; // if hi word equal
4961                                                                 // fail early
4962                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
4963                                                         genc16bit2lit(left,lit,2);
4964                                                         genSkip(ifx,'z');
4965                                                 } else {
4966                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
4967                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
4968                                                         genSkip(ifx,'z');
4969                                                 }
4970                                         }
4971                                                 pic16_emitpLabel(falselbl->key);
4972                                                 break;
4973
4974                         } // switch size
4975
4976                         ifx->generated = 1;
4977                         goto release ;
4978
4979
4980           } else if(AOP_TYPE(right) == AOP_CRY ) {
4981             /* we know the left is not a bit, but that the right is */
4982             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4983             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4984                       pic16_popGet(AOP(right),offset));
4985             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
4986
4987             /* if the two are equal, then W will be 0 and the Z bit is set
4988              * we could test Z now, or go ahead and check the high order bytes if
4989              * the variable we're comparing is larger than a byte. */
4990
4991             while(--size)
4992               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
4993
4994             if ( IC_TRUE(ifx) ) {
4995               emitSKPNZ;
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             } else {
4999               emitSKPZ;
5000               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5001               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5002             }
5003
5004           } else {
5005             /* They're both variables that are larger than bits */
5006             int s = size;
5007
5008             tlbl = newiTempLabel(NULL);
5009
5010             while(size--) {
5011               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5012               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5013
5014               if ( IC_TRUE(ifx) ) {
5015                 if(size) {
5016                   emitSKPZ;
5017
5018                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5019
5020                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5021                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
5022                 } else {
5023                   emitSKPNZ;
5024
5025                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5026
5027
5028                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5029                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5030                 }
5031               } else {
5032                 emitSKPZ;
5033
5034                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5035
5036                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5037                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5038               }
5039               offset++;
5040             }
5041             if(s>1 && IC_TRUE(ifx)) {
5042               pic16_emitpLabel(tlbl->key);
5043               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5044             }
5045           }
5046         }
5047         /* mark the icode as generated */
5048         ifx->generated = 1;
5049         goto release ;
5050     }
5051
5052     /* if they are both bit variables */
5053     if (AOP_TYPE(left) == AOP_CRY &&
5054         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5055         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5056         if(AOP_TYPE(right) == AOP_LIT){
5057             unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
5058             if(lit == 0L){
5059                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5060                 pic16_emitcode("cpl","c");
5061             } else if(lit == 1L) {
5062                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5063             } else {
5064                 pic16_emitcode("clr","c");
5065             }
5066             /* AOP_TYPE(right) == AOP_CRY */
5067         } else {
5068             symbol *lbl = newiTempLabel(NULL);
5069             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5070             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5071             pic16_emitcode("cpl","c");
5072             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5073         }
5074         /* c = 1 if egal */
5075         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5076             pic16_outBitC(result);
5077             goto release ;
5078         }
5079         if (ifx) {
5080             genIfxJump (ifx,"c");
5081             goto release ;
5082         }
5083         /* if the result is used in an arithmetic operation
5084         then put the result in place */
5085         pic16_outBitC(result);
5086     } else {
5087
5088       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5089       gencjne(left,right,result,ifx);
5090 /*
5091       if(ifx)
5092         gencjne(left,right,newiTempLabel(NULL));
5093       else {
5094         if(IC_TRUE(ifx)->key)
5095           gencjne(left,right,IC_TRUE(ifx)->key);
5096         else
5097           gencjne(left,right,IC_FALSE(ifx)->key);
5098         ifx->generated = 1;
5099         goto release ;
5100       }
5101       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5102         pic16_aopPut(AOP(result),"a",0);
5103         goto release ;
5104       }
5105
5106       if (ifx) {
5107         genIfxJump (ifx,"a");
5108         goto release ;
5109       }
5110 */
5111       /* if the result is used in an arithmetic operation
5112          then put the result in place */
5113 /*
5114       if (AOP_TYPE(result) != AOP_CRY)
5115         pic16_outAcc(result);
5116 */
5117       /* leave the result in acc */
5118     }
5119
5120 release:
5121     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5122     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5123     pic16_freeAsmop(result,NULL,ic,TRUE);
5124 }
5125 #endif
5126
5127 /*-----------------------------------------------------------------*/
5128 /* ifxForOp - returns the icode containing the ifx for operand     */
5129 /*-----------------------------------------------------------------*/
5130 static iCode *ifxForOp ( operand *op, iCode *ic )
5131 {
5132   FENTRY2;
5133
5134     /* if true symbol then needs to be assigned */
5135     if (IS_TRUE_SYMOP(op))
5136         return NULL ;
5137
5138     /* if this has register type condition and
5139     the next instruction is ifx with the same operand
5140     and live to of the operand is upto the ifx only then */
5141     if (ic->next
5142         && ic->next->op == IFX
5143         && IC_COND(ic->next)->key == op->key
5144         && OP_SYMBOL(op)->liveTo <= ic->next->seq
5145         ) {
5146                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
5147           return ic->next;
5148     }
5149
5150     /*
5151     if (ic->next &&
5152         ic->next->op == IFX &&
5153         IC_COND(ic->next)->key == op->key) {
5154       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5155       return ic->next;
5156     }
5157     */
5158
5159     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5160     if (ic->next &&
5161         ic->next->op == IFX)
5162       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5163
5164     if (ic->next &&
5165         ic->next->op == IFX &&
5166         IC_COND(ic->next)->key == op->key) {
5167       DEBUGpic16_emitcode ("; "," key is okay");
5168       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5169                            OP_SYMBOL(op)->liveTo,
5170                            ic->next->seq);
5171     }
5172
5173 #if 0
5174     /* the code below is completely untested
5175      * it just allows ulong2fs.c compile -- VR */
5176
5177     ic = ic->next;
5178     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
5179                                         __FILE__, __FUNCTION__, __LINE__);
5180
5181     /* if this has register type condition and
5182     the next instruction is ifx with the same operand
5183     and live to of the operand is upto the ifx only then */
5184     if (ic->next &&
5185         ic->next->op == IFX &&
5186         IC_COND(ic->next)->key == op->key &&
5187         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5188         return ic->next;
5189
5190     if (ic->next &&
5191         ic->next->op == IFX &&
5192         IC_COND(ic->next)->key == op->key) {
5193       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5194       return ic->next;
5195     }
5196
5197     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
5198                                         __FILE__, __FUNCTION__, __LINE__);
5199
5200 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
5201 #endif
5202
5203     return NULL;
5204 }
5205 /*-----------------------------------------------------------------*/
5206 /* genAndOp - for && operation                                     */
5207 /*-----------------------------------------------------------------*/
5208 static void genAndOp (iCode *ic)
5209 {
5210   operand *left,*right, *result;
5211 /*     symbol *tlbl; */
5212
5213     FENTRY;
5214
5215     /* note here that && operations that are in an
5216     if statement are taken away by backPatchLabels
5217     only those used in arthmetic operations remain */
5218     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5219     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5220     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5221
5222     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5223
5224     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5225     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5226     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5227
5228     /* if both are bit variables */
5229 /*     if (AOP_TYPE(left) == AOP_CRY && */
5230 /*         AOP_TYPE(right) == AOP_CRY ) { */
5231 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5232 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5233 /*         pic16_outBitC(result); */
5234 /*     } else { */
5235 /*         tlbl = newiTempLabel(NULL); */
5236 /*         pic16_toBoolean(left);     */
5237 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5238 /*         pic16_toBoolean(right); */
5239 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5240 /*         pic16_outBitAcc(result); */
5241 /*     } */
5242
5243     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5244     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5245     pic16_freeAsmop(result,NULL,ic,TRUE);
5246 }
5247
5248
5249 /*-----------------------------------------------------------------*/
5250 /* genOrOp - for || operation                                      */
5251 /*-----------------------------------------------------------------*/
5252 /*
5253   tsd pic port -
5254   modified this code, but it doesn't appear to ever get called
5255 */
5256
5257 static void genOrOp (iCode *ic)
5258 {
5259   operand *left,*right, *result;
5260   symbol *tlbl;
5261
5262     FENTRY;
5263
5264   /* note here that || operations that are in an
5265     if statement are taken away by backPatchLabels
5266     only those used in arthmetic operations remain */
5267     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5268     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5269     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5270
5271     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5272
5273     /* if both are bit variables */
5274     if (AOP_TYPE(left) == AOP_CRY &&
5275         AOP_TYPE(right) == AOP_CRY ) {
5276       pic16_emitcode("clrc","");
5277       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5278                AOP(left)->aopu.aop_dir,
5279                AOP(left)->aopu.aop_dir);
5280       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5281                AOP(right)->aopu.aop_dir,
5282                AOP(right)->aopu.aop_dir);
5283       pic16_emitcode("setc","");
5284
5285     } else {
5286         tlbl = newiTempLabel(NULL);
5287         pic16_toBoolean(left);
5288         emitSKPZ;
5289         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
5290         pic16_toBoolean(right);
5291         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5292
5293         pic16_outBitAcc(result);
5294     }
5295
5296     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5297     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5298     pic16_freeAsmop(result,NULL,ic,TRUE);
5299 }
5300
5301 /*-----------------------------------------------------------------*/
5302 /* isLiteralBit - test if lit == 2^n                               */
5303 /*-----------------------------------------------------------------*/
5304 static int isLiteralBit(unsigned long lit)
5305 {
5306     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5307     0x100L,0x200L,0x400L,0x800L,
5308     0x1000L,0x2000L,0x4000L,0x8000L,
5309     0x10000L,0x20000L,0x40000L,0x80000L,
5310     0x100000L,0x200000L,0x400000L,0x800000L,
5311     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5312     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5313     int idx;
5314
5315     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5316     for(idx = 0; idx < 32; idx++)
5317         if(lit == pw[idx])
5318             return idx+1;
5319     return 0;
5320 }
5321
5322 /*-----------------------------------------------------------------*/
5323 /* continueIfTrue -                                                */
5324 /*-----------------------------------------------------------------*/
5325 static void continueIfTrue (iCode *ic)
5326 {
5327   FENTRY;
5328   if(IC_TRUE(ic))
5329     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5330   ic->generated = 1;
5331 }
5332
5333 /*-----------------------------------------------------------------*/
5334 /* jmpIfTrue -                                                     */
5335 /*-----------------------------------------------------------------*/
5336 static void jumpIfTrue (iCode *ic)
5337 {
5338   FENTRY;
5339   if(!IC_TRUE(ic))
5340     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5341   ic->generated = 1;
5342 }
5343
5344 /*-----------------------------------------------------------------*/
5345 /* jmpTrueOrFalse -                                                */
5346 /*-----------------------------------------------------------------*/
5347 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5348 {
5349   // ugly but optimized by peephole
5350   FENTRY;
5351   if(IC_TRUE(ic)){
5352     symbol *nlbl = newiTempLabel(NULL);
5353       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);
5354       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5355       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5356       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5357   } else {
5358     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5359     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5360   }
5361   ic->generated = 1;
5362 }
5363
5364 /*-----------------------------------------------------------------*/
5365 /* genAnd  - code for and                                          */
5366 /*-----------------------------------------------------------------*/
5367 static void genAnd (iCode *ic, iCode *ifx)
5368 {
5369   operand *left, *right, *result;
5370   int size, offset = 0;
5371   unsigned long lit = 0L;
5372   resolvedIfx rIfx;
5373
5374   FENTRY;
5375
5376   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5377   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5378   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5379
5380   resolveIfx (&rIfx, ifx);
5381
5382   /* if left is a literal & right is not then exchange them */
5383   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5384       AOP_NEEDSACC (left))
5385     {
5386       operand *tmp = right;
5387       right = left;
5388       left = tmp;
5389     }
5390
5391   /* if result = right then exchange them */
5392   if (pic16_sameRegs (AOP (result), AOP (right)))
5393     {
5394       operand *tmp = right;
5395       right = left;
5396       left = tmp;
5397     }
5398
5399   /* if right is bit then exchange them */
5400   if (AOP_TYPE (right) == AOP_CRY &&
5401       AOP_TYPE (left) != AOP_CRY)
5402     {
5403       operand *tmp = right;
5404       right = left;
5405       left = tmp;
5406     }
5407
5408   if (AOP_TYPE (right) == AOP_LIT)
5409     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5410
5411   size = AOP_SIZE (result);
5412
5413   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5414
5415   // if(bit & yy)
5416   // result = bit & yy;
5417   if (AOP_TYPE(left) == AOP_CRY){
5418     // c = bit & literal;
5419     if(AOP_TYPE(right) == AOP_LIT){
5420       if(lit & 1) {
5421         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5422           // no change
5423           goto release;
5424         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5425       } else {
5426         // bit(result) = 0;
5427         if(size && (AOP_TYPE(result) == AOP_CRY)){
5428           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5429           goto release;
5430         }
5431         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5432           jumpIfTrue(ifx);
5433           goto release;
5434         }
5435         pic16_emitcode("clr","c");
5436       }
5437     } else {
5438       if (AOP_TYPE(right) == AOP_CRY){
5439         // c = bit & bit;
5440         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5441         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5442       } else {
5443         // c = bit & val;
5444         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5445         // c = lsb
5446         pic16_emitcode("rrc","a");
5447         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5448       }
5449     }
5450     // bit = c
5451     // val = c
5452     if(size)
5453       pic16_outBitC(result);
5454     // if(bit & ...)
5455     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5456       genIfxJump(ifx, "c");
5457     goto release ;
5458   }
5459
5460   // if (val & 0xZZ)      - size = 0, ifx != FALSE -
5461   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5462   if ((AOP_TYPE (right) == AOP_LIT) &&
5463      (AOP_TYPE (result) == AOP_CRY) &&
5464      (AOP_TYPE (left) != AOP_CRY))
5465     {
5466       symbol *tlbl = newiTempLabel (NULL);
5467       int sizel = AOP_SIZE (left);
5468       int nonnull = 0;
5469       char emitBra;
5470
5471       if (size)
5472         emitSETC;
5473
5474       /* get number of non null bytes in literal */
5475       while (sizel--)
5476         {
5477           if (lit & (0xff << (sizel * 8)))
5478             ++nonnull;
5479         }
5480
5481       emitBra = nonnull || rIfx.condition;
5482
5483       for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8)
5484         {
5485           unsigned char bytelit = lit;
5486
5487           if (bytelit != 0)
5488             {
5489               int posbit;
5490
5491               --nonnull;
5492
5493               /* patch provided by Aaron Colwell */
5494               if ((posbit = isLiteralBit (bytelit)) != 0)
5495                 {
5496                   if (nonnull)
5497                     {
5498                       pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5499                       pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key));
5500                     }
5501                   else
5502                     {
5503                       pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER));
5504                     }
5505                 }
5506               else
5507                 {
5508                   if (bytelit == 0xff)
5509                     {
5510                       /* Aaron had a MOVF instruction here, changed to MOVFW cause
5511                        * a peephole could optimize it out -- VR */
5512                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5513                     }
5514                   else
5515                     {
5516                       pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
5517                       pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit));
5518                     }
5519                   if (nonnull)
5520                     {
5521                       if (rIfx.condition)
5522                         {
5523                           emitSKPZ;
5524                           pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5525                         }
5526                       else
5527                         {
5528                           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
5529                         }
5530                     }
5531                   else
5532                     {
5533                       /* last non null byte */
5534                       if (rIfx.condition)
5535                         emitSKPZ;
5536                       else
5537                         emitSKPNZ;
5538                     }
5539                 }
5540             }
5541         }
5542
5543       // bit = left & literal
5544       if (size)
5545         {
5546           emitCLRC;
5547           pic16_emitpLabel (tlbl->key);
5548         }
5549
5550       // if(left & literal)
5551       else
5552         {
5553           if (ifx)
5554             {
5555               if (emitBra)
5556                 pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
5557               ifx->generated = 1;
5558             }
5559           pic16_emitpLabel (tlbl->key);
5560           goto release;
5561         }
5562       pic16_outBitC (result);
5563       goto release;
5564     }
5565
5566   /* if left is same as result */
5567   if(pic16_sameRegs(AOP(result),AOP(left))){
5568     int know_W = -1;
5569     for(;size--; offset++,lit>>=8) {
5570       if(AOP_TYPE(right) == AOP_LIT){
5571         switch(lit & 0xff) {
5572         case 0x00:
5573           /*  and'ing with 0 has clears the result */
5574 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5575           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5576           break;
5577         case 0xff:
5578           /* and'ing with 0xff is a nop when the result and left are the same */
5579           break;
5580
5581         default:
5582           {
5583             int p = pic16_my_powof2( (~lit) & 0xff );
5584             if(p>=0) {
5585               /* only one bit is set in the literal, so use a bcf instruction */
5586 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5587               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5588
5589             } else {
5590               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5591               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5592               if(know_W != (lit&0xff))
5593                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5594               know_W = lit &0xff;
5595               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5596             }
5597           }
5598         }
5599       } else {
5600         if (AOP_TYPE(left) == AOP_ACC) {
5601           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5602         } else {
5603           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5604           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5605
5606         }
5607       }
5608     }
5609
5610   } else {
5611     // left & result in different registers
5612     if(AOP_TYPE(result) == AOP_CRY){
5613       // result = bit
5614       // if(size), result in bit
5615       // if(!size && ifx), conditional oper: if(left & right)
5616       symbol *tlbl = newiTempLabel(NULL);
5617       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5618       if(size)
5619         pic16_emitcode("setb","c");
5620       while(sizer--){
5621         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5622         pic16_emitcode("anl","a,%s",
5623                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5624         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5625         offset++;
5626       }
5627       if(size){
5628         CLRC;
5629         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5630         pic16_outBitC(result);
5631       } else if(ifx)
5632         jmpTrueOrFalse(ifx, tlbl);
5633     } else {
5634       for(;(size--);offset++) {
5635         // normal case
5636         // result = left & right
5637         if(AOP_TYPE(right) == AOP_LIT){
5638           int t = (lit >> (offset*8)) & 0x0FFL;
5639           switch(t) {
5640           case 0x00:
5641             pic16_emitcode("clrf","%s",
5642                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5643             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5644             break;
5645           case 0xff:
5646             pic16_emitcode("movf","%s,w",
5647                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5648             pic16_emitcode("movwf","%s",
5649                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5650             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5651             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5652             break;
5653           default:
5654             pic16_emitcode("movlw","0x%x",t);
5655             pic16_emitcode("andwf","%s,w",
5656                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5657             pic16_emitcode("movwf","%s",
5658                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5659
5660             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5661             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5662             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5663           }
5664           continue;
5665         }
5666
5667         if (AOP_TYPE(left) == AOP_ACC) {
5668           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5669           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5670         } else {
5671           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5672           pic16_emitcode("andwf","%s,w",
5673                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5674           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5675           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5676         }
5677         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5678         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5679       }
5680     }
5681   }
5682
5683 release :
5684   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5685   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5686   pic16_freeAsmop(result,NULL,ic,TRUE);
5687 }
5688
5689 /*-----------------------------------------------------------------*/
5690 /* genOr  - code for or                                            */
5691 /*-----------------------------------------------------------------*/
5692 static void genOr (iCode *ic, iCode *ifx)
5693 {
5694   operand *left, *right, *result;
5695   int size, offset = 0;
5696   unsigned long lit = 0L;
5697   resolvedIfx rIfx;
5698
5699   FENTRY;
5700
5701   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5702   pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE);
5703   pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE);
5704
5705   resolveIfx (&rIfx, ifx);
5706
5707   /* if left is a literal & right is not then exchange them */
5708   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5709       AOP_NEEDSACC (left))
5710     {
5711       operand *tmp = right;
5712       right = left;
5713       left = tmp;
5714     }
5715
5716   /* if result = right then exchange them */
5717   if (pic16_sameRegs (AOP (result), AOP (right)))
5718     {
5719       operand *tmp = right;
5720       right = left;
5721       left = tmp;
5722     }
5723
5724   /* if right is bit then exchange them */
5725   if (AOP_TYPE (right) == AOP_CRY &&
5726       AOP_TYPE (left) != AOP_CRY)
5727     {
5728       operand *tmp = right;
5729       right = left;
5730       left = tmp;
5731     }
5732
5733   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
5734
5735   if (AOP_TYPE (right) == AOP_LIT)
5736       lit = ulFromVal (AOP (right)->aopu.aop_lit);
5737
5738   size = AOP_SIZE (result);
5739
5740   // if(bit | yy)
5741   // xx = bit | yy;
5742   if (AOP_TYPE(left) == AOP_CRY){
5743       if(AOP_TYPE(right) == AOP_LIT){
5744           // c = bit & literal;
5745           if(lit){
5746               // lit != 0 => result = 1
5747               if(AOP_TYPE(result) == AOP_CRY){
5748                 if(size)
5749                   pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5750                 //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5751                 //     AOP(result)->aopu.aop_dir,
5752                 //     AOP(result)->aopu.aop_dir);
5753                   else if(ifx)
5754                       continueIfTrue(ifx);
5755                   goto release;
5756               }
5757           } else {
5758               // lit == 0 => result = left
5759               if(size && pic16_sameRegs(AOP(result),AOP(left)))
5760                   goto release;
5761               pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5762           }
5763       } else {
5764           if (AOP_TYPE(right) == AOP_CRY){
5765             if(pic16_sameRegs(AOP(result),AOP(left))){
5766               // c = bit | bit;
5767               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5768               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5769               pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5770
5771             } else {
5772               if( AOP_TYPE(result) == AOP_ACC) {
5773                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5774                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5775                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5776                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5777
5778               } else {
5779
5780                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5781                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5782                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5783                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5784
5785               }
5786             }
5787           } else {
5788               // c = bit | val;
5789               symbol *tlbl = newiTempLabel(NULL);
5790               pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5791
5792
5793               pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5794               if( AOP_TYPE(right) == AOP_ACC) {
5795                 pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5796                 emitSKPNZ;
5797                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5798                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5799               }
5800
5801
5802
5803               if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5804                   pic16_emitcode(";XXX setb","c");
5805               pic16_emitcode(";XXX jb","%s,%05d_DS_",
5806                        AOP(left)->aopu.aop_dir,tlbl->key+100);
5807               pic16_toBoolean(right);
5808               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5809               if((AOP_TYPE(result) == AOP_CRY) && ifx){
5810                   jmpTrueOrFalse(ifx, tlbl);
5811                   goto release;
5812               } else {
5813                   CLRC;
5814                   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5815               }
5816           }
5817       }
5818       // bit = c
5819       // val = c
5820       if(size)
5821           pic16_outBitC(result);
5822       // if(bit | ...)
5823       else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5824           genIfxJump(ifx, "c");
5825       goto release ;
5826   }
5827
5828   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5829   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5830   if ((AOP_TYPE (right) == AOP_LIT) &&
5831      (AOP_TYPE (result) == AOP_CRY) &&
5832      (AOP_TYPE (left) != AOP_CRY))
5833     {
5834       if (IS_OP_VOLATILE(left)) {
5835           pic16_mov2w_volatile(AOP(left));
5836       } // if
5837       if (lit)
5838         {
5839           if (rIfx.condition)
5840             pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
5841           ifx->generated = 1;
5842         }
5843       else
5844         wassert (0);
5845
5846       goto release;
5847   }
5848
5849   /* if left is same as result */
5850   if(pic16_sameRegs(AOP(result),AOP(left))){
5851     int know_W = -1;
5852     for(;size--; offset++,lit>>=8) {
5853       if(AOP_TYPE(right) == AOP_LIT){
5854         if(((lit & 0xff) == 0) && !IS_OP_VOLATILE(left)) {
5855           /*  or'ing with 0 has no effect */
5856           continue;
5857         } else {
5858           int p = pic16_my_powof2(lit & 0xff);
5859           if(p>=0) {
5860             /* only one bit is set in the literal, so use a bsf instruction */
5861             pic16_emitpcode(POC_BSF,
5862                       pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
5863           } else {
5864             if(know_W != (lit & 0xff))
5865               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5866             know_W = lit & 0xff;
5867             pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5868           }
5869
5870         }
5871       } else {
5872         if (AOP_TYPE(left) == AOP_ACC) {
5873           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5874         } else {
5875           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5876           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5877         }
5878       }
5879     }
5880   } else {
5881       // left & result in different registers
5882       if(AOP_TYPE(result) == AOP_CRY){
5883           // result = bit
5884           // if(size), result in bit
5885           // if(!size && ifx), conditional oper: if(left | right)
5886           symbol *tlbl = newiTempLabel(NULL);
5887           int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5888           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5889
5890
5891           if(size)
5892               pic16_emitcode(";XXX setb","c");
5893           while(sizer--){
5894               MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5895               pic16_emitcode(";XXX orl","a,%s",
5896                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5897               pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5898               offset++;
5899           }
5900           if(size){
5901               CLRC;
5902               pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5903               pic16_outBitC(result);
5904           } else if(ifx)
5905               jmpTrueOrFalse(ifx, tlbl);
5906       } else for(;(size--);offset++){
5907         // normal case
5908         // result = left & right
5909         if(AOP_TYPE(right) == AOP_LIT){
5910           int t = (lit >> (offset*8)) & 0x0FFL;
5911           switch(t) {
5912           case 0x00:
5913             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
5914             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5915             break;
5916           default:
5917             pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
5918             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5919             pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5920           }
5921           continue;
5922         }
5923
5924         // faster than result <- left, anl result,right
5925         // and better if result is SFR
5926         if (AOP_TYPE(left) == AOP_ACC) {
5927           pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
5928         } else {
5929           pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5930           pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
5931         }
5932         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
5933       }
5934   }
5935
5936 release :
5937   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5938   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5939   pic16_freeAsmop(result,NULL,ic,TRUE);
5940 }
5941
5942 /*-----------------------------------------------------------------*/
5943 /* genXor - code for xclusive or                                   */
5944 /*-----------------------------------------------------------------*/
5945 static void genXor (iCode *ic, iCode *ifx)
5946 {
5947   operand *left, *right, *result;
5948   int size, offset = 0;
5949   unsigned long lit = 0L;
5950   resolvedIfx rIfx;
5951
5952   FENTRY;
5953
5954   pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5955   pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5956   pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5957
5958   resolveIfx (&rIfx,ifx);
5959
5960   /* if left is a literal & right is not ||
5961      if left needs acc & right does not */
5962   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5963       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5964     {
5965       operand *tmp = right;
5966       right = left;
5967       left = tmp;
5968     }
5969
5970   /* if result = right then exchange them */
5971   if (pic16_sameRegs (AOP (result), AOP (right)))
5972     {
5973       operand *tmp = right ;
5974       right = left;
5975       left = tmp;
5976     }
5977
5978   /* if right is bit then exchange them */
5979   if (AOP_TYPE (right) == AOP_CRY &&
5980       AOP_TYPE (left) != AOP_CRY)
5981     {
5982       operand *tmp = right ;
5983       right = left;
5984       left = tmp;
5985     }
5986
5987   if (AOP_TYPE (right) == AOP_LIT)
5988     lit = ulFromVal (AOP (right)->aopu.aop_lit);
5989
5990   size = AOP_SIZE (result);
5991
5992   // if(bit ^ yy)
5993   // xx = bit ^ yy;
5994   if (AOP_TYPE(left) == AOP_CRY)
5995     {
5996       if (AOP_TYPE(right) == AOP_LIT)
5997         {
5998           // c = bit & literal;
5999           if (lit >> 1)
6000             {
6001               // lit>>1  != 0 => result = 1
6002               if (AOP_TYPE(result) == AOP_CRY)
6003                 {
6004                   if (size)
6005                     {
6006                       pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset));
6007                     }
6008                   else if (ifx)
6009                     continueIfTrue(ifx);
6010                   goto release;
6011                 }
6012               pic16_emitcode("setb", "c");
6013             }
6014           else
6015             {
6016               // lit == (0 or 1)
6017               if (lit == 0)
6018                 {
6019                   // lit == 0, result = left
6020                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
6021                     goto release;
6022                   pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6023                 }
6024               else
6025                 {
6026                   // lit == 1, result = not(left)
6027                   if (size && pic16_sameRegs(AOP(result), AOP(left)))
6028                     {
6029                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset));
6030                       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset));
6031                       pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir);
6032                       goto release;
6033                     }
6034                   else
6035                     {
6036                       pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir);
6037                       pic16_emitcode("cpl", "c");
6038                     }
6039                 }
6040             }
6041         }
6042       else
6043         {
6044           // right != literal
6045           symbol *tlbl = newiTempLabel(NULL);
6046           if (AOP_TYPE(right) == AOP_CRY)
6047             {
6048               // c = bit ^ bit;
6049               pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir);
6050             }
6051           else
6052             {
6053               int sizer = AOP_SIZE(right);
6054               // c = bit ^ val
6055               // if val>>1 != 0, result = 1
6056               pic16_emitcode("setb", "c");
6057               while (sizer)
6058                 {
6059                   MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE));
6060                   if (sizer == 1)
6061                     // test the msb of the lsb
6062                     pic16_emitcode("anl", "a,#0xfe");
6063                   pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100);
6064                   sizer--;
6065                 }
6066               // val = (0,1)
6067               pic16_emitcode("rrc", "a");
6068             }
6069           pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100));
6070           pic16_emitcode("cpl", "c");
6071           pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100));
6072         }
6073       // bit = c
6074       // val = c
6075       if (size)
6076         pic16_outBitC(result);
6077       // if(bit | ...)
6078       else if ((AOP_TYPE(result) == AOP_CRY) && ifx)
6079         genIfxJump(ifx, "c");
6080       goto release;
6081     }
6082
6083   // if(val ^ 0xZZ)       - size = 0, ifx != FALSE  -
6084   // bit = val ^ 0xZZ     - size = 1, ifx = FALSE -
6085   if ((AOP_TYPE (right) == AOP_LIT) &&
6086      (AOP_TYPE (result) == AOP_CRY) &&
6087      (AOP_TYPE (left) != AOP_CRY))
6088     {
6089       symbol *tlbl = newiTempLabel (NULL);
6090       int sizel;
6091
6092       if (size)
6093         emitSETC;
6094
6095       for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8)
6096         {
6097           unsigned char bytelit = lit;
6098
6099           switch (bytelit)
6100             {
6101             case 0xff:
6102               pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset));
6103               break;
6104
6105             case 0x00:
6106               pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset));
6107               break;
6108
6109             default:
6110               pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit));
6111               pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset));
6112               break;
6113             }
6114           if (sizel)
6115             {
6116               if (rIfx.condition)
6117                 {
6118                   /* rIfx.lbl might be far away... */
6119                   emitSKPZ;
6120                   pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */
6121                 }
6122               else
6123                 {
6124                   pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */
6125                 }
6126             }
6127           else
6128             {
6129               /* last non null byte */
6130               if (rIfx.condition)
6131                 emitSKPZ;
6132               else
6133                 emitSKPNZ;
6134             }
6135         }
6136
6137       // bit = left ^ literal
6138       if (size)
6139         {
6140           emitCLRC;
6141           pic16_emitpLabel (tlbl->key);
6142         }
6143       // if (left ^ literal)
6144       else
6145         {
6146           if (ifx)
6147             {
6148               pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key));
6149               ifx->generated = 1;
6150             }
6151           pic16_emitpLabel (tlbl->key);
6152           goto release;
6153         }
6154
6155       pic16_outBitC (result);
6156       goto release;
6157   }
6158
6159   if (pic16_sameRegs(AOP(result), AOP(left)))
6160     {
6161       /* if left is same as result */
6162       for (; size--; offset++)
6163         {
6164           if (AOP_TYPE(right) == AOP_LIT)
6165             {
6166               int t  = (lit >> (offset * 8)) & 0x0FFL;
6167               if  (t == 0x00L)
6168                 continue;
6169               else
6170                 {
6171                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6172                   pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6173                 }
6174             }
6175           else
6176             {
6177               if (AOP_TYPE(left) == AOP_ACC)
6178                 pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6179               else
6180                 {
6181                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6182                   pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset));
6183                 }
6184             }
6185         }
6186     }
6187   else
6188     {
6189     // left ^ result in different registers
6190     if (AOP_TYPE(result) == AOP_CRY)
6191       {
6192         // result = bit
6193         // if(size), result in bit
6194         // if(!size && ifx), conditional oper: if(left ^ right)
6195         symbol *tlbl = newiTempLabel(NULL);
6196         int sizer = max(AOP_SIZE(left), AOP_SIZE(right));
6197         if (size)
6198           pic16_emitcode("setb", "c");
6199         while (sizer--)
6200           {
6201             if ((AOP_TYPE(right) == AOP_LIT) &&
6202               (((lit >> (offset*8)) & 0x0FFL) == 0x00L))
6203               {
6204                 MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6205               }
6206             else
6207               {
6208                 MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE));
6209                 pic16_emitcode("xrl", "a,%s",
6210                                pic16_aopGet(AOP(left), offset, FALSE, FALSE));
6211               }
6212             pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100);
6213             offset++;
6214           }
6215         if (size)
6216           {
6217             CLRC;
6218             pic16_emitcode("", "%05d_DS_:", tlbl->key + 100);
6219             pic16_outBitC(result);
6220           }
6221         else if (ifx)
6222           jmpTrueOrFalse(ifx, tlbl);
6223       }
6224     else
6225       {
6226         for (; (size--); offset++)
6227           {
6228             // normal case
6229             // result = left ^ right
6230             if (AOP_TYPE(right) == AOP_LIT)
6231               {
6232                 int t = (lit >> (offset * 8)) & 0x0FFL;
6233                 switch(t)
6234                   {
6235                   case 0x00:
6236                     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
6237                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6238                     break;
6239
6240                   case 0xff:
6241                     pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset));
6242                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6243                     break;
6244
6245                   default:
6246                     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6247                     pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6248                     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6249                   }
6250                 continue;
6251               }
6252
6253             // faster than result <- left, anl result,right
6254             // and better if result is SFR
6255             if (AOP_TYPE(left) == AOP_ACC)
6256               {
6257                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset));
6258               }
6259             else
6260               {
6261                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
6262                 pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset));
6263               }
6264             if ( AOP_TYPE(result) != AOP_ACC)
6265               {
6266                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
6267               }
6268           }
6269       }
6270   }
6271
6272 release :
6273   pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6274   pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE));
6275   pic16_freeAsmop(result, NULL, ic, TRUE);
6276 }
6277
6278 /*-----------------------------------------------------------------*/
6279 /* genInline - write the inline code out                           */
6280 /*-----------------------------------------------------------------*/
6281 static void genInline (iCode *ic)
6282 {
6283   char *buffer, *bp, *bp1;
6284   bool inComment = FALSE;
6285
6286   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6287
6288   _G.inLine += (!options.asmpeep);
6289
6290   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
6291
6292   while((bp1=strstr(bp, "\\n"))) {
6293     *bp1++ = '\n';
6294     *bp1++ = ' ';
6295     bp = bp1;
6296   }
6297   bp = bp1 = buffer;
6298
6299 #if 0
6300   /* This is an experimental code for #pragma inline
6301      and is temporarily disabled for 2.5.0 release */
6302   if(asmInlineMap)
6303   {
6304     symbol *sym;
6305     char *s;
6306     char *cbuf;
6307     int cblen;
6308
6309       cbuf = Safe_strdup(buffer);
6310       cblen = strlen(buffer)+1;
6311       memset(cbuf, 0, cblen);
6312
6313       bp = buffer;
6314       bp1 = cbuf;
6315       while(*bp) {
6316         if(*bp != '%')*bp1++ = *bp++;
6317         else {
6318           int i;
6319
6320             bp++;
6321             i = *bp - '0';
6322             if(i>elementsInSet(asmInlineMap))break;
6323
6324             bp++;
6325             s = indexSet(asmInlineMap, i);
6326             DEBUGpc("searching symbol s = `%s'", s);
6327             sym = findSym(SymbolTab, NULL, s);
6328
6329             if(sym->reqv) {
6330               strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
6331             } else {
6332               strcat(bp1, sym->rname);
6333             }
6334
6335             while(*bp1)bp1++;
6336         }
6337
6338         if(strlen(bp1) > cblen - 16) {
6339           int i = strlen(cbuf);
6340           cblen += 50;
6341           cbuf = realloc(cbuf, cblen);
6342           memset(cbuf+i, 0, 50);
6343           bp1 = cbuf + i;
6344         }
6345       }
6346
6347       free(buffer);
6348       buffer = Safe_strdup( cbuf );
6349       free(cbuf);
6350
6351       bp = bp1 = buffer;
6352   }
6353 #endif  /* 0 */
6354
6355   /* emit each line as a code */
6356   while (*bp)
6357     {
6358       switch (*bp)
6359         {
6360         case ';':
6361           inComment = TRUE;
6362           ++bp;
6363           break;
6364
6365         case '\n':
6366           inComment = FALSE;
6367           *bp++ = '\0';
6368           if (*bp1)
6369             pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6370           bp1 = bp;
6371           break;
6372
6373         default:
6374           /* Add \n for labels, not dirs such as c:\mydir */
6375           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
6376             {
6377               ++bp;
6378               *bp = '\0';
6379               ++bp;
6380               /* print label, use this special format with NULL directive
6381                * to denote that the argument should not be indented with tab */
6382               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6383               bp1 = bp;
6384             }
6385           else
6386             ++bp;
6387           break;
6388         }
6389     }
6390
6391   if ((bp1 != bp) && *bp1)
6392     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6393
6394   Safe_free (buffer);
6395
6396   _G.inLine -= (!options.asmpeep);
6397 }
6398
6399 /*-----------------------------------------------------------------*/
6400 /* genRRC - rotate right with carry                                */
6401 /*-----------------------------------------------------------------*/
6402 static void genRRC (iCode *ic)
6403 {
6404   operand *left , *result ;
6405   int size, same;
6406
6407   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6408
6409   /* rotate right with carry */
6410   left = IC_LEFT(ic);
6411   result=IC_RESULT(ic);
6412   pic16_aopOp (left,ic,FALSE);
6413   pic16_aopOp (result,ic,TRUE);
6414
6415   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6416
6417   same = pic16_sameRegs(AOP(result),AOP(left));
6418
6419   size = AOP_SIZE(result);
6420
6421   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6422
6423   /* get the lsb and put it into the carry */
6424   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0));
6425
6426   while(size--) {
6427
6428     if(same) {
6429       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),size));
6430     } else {
6431       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size));
6432       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),size));
6433     }
6434   }
6435
6436   pic16_freeAsmop(left,NULL,ic,TRUE);
6437   pic16_freeAsmop(result,NULL,ic,TRUE);
6438 }
6439
6440 /*-----------------------------------------------------------------*/
6441 /* genRLC - generate code for rotate left with carry               */
6442 /*-----------------------------------------------------------------*/
6443 static void genRLC (iCode *ic)
6444 {
6445   operand *left , *result ;
6446   int size, offset = 0;
6447   int same;
6448
6449   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6450   /* rotate right with carry */
6451   left = IC_LEFT(ic);
6452   result=IC_RESULT(ic);
6453   pic16_aopOp (left,ic,FALSE);
6454   pic16_aopOp (result,ic,TRUE);
6455
6456   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6457
6458   same = pic16_sameRegs(AOP(result),AOP(left));
6459
6460   /* move it to the result */
6461   size = AOP_SIZE(result);
6462
6463   /* get the msb and put it into the carry */
6464   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6465
6466   offset = 0 ;
6467
6468   while(size--) {
6469
6470     if(same) {
6471       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6472     } else {
6473       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6474       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6475     }
6476
6477     offset++;
6478   }
6479
6480
6481   pic16_freeAsmop(left,NULL,ic,TRUE);
6482   pic16_freeAsmop(result,NULL,ic,TRUE);
6483 }
6484
6485
6486 /* gpasm can get the highest order bit with HIGH/UPPER
6487  * so the following probably is not needed -- VR */
6488
6489 /*-----------------------------------------------------------------*/
6490 /* genGetHbit - generates code get highest order bit               */
6491 /*-----------------------------------------------------------------*/
6492 static void genGetHbit (iCode *ic)
6493 {
6494     operand *left, *result;
6495     left = IC_LEFT(ic);
6496     result=IC_RESULT(ic);
6497     pic16_aopOp (left,ic,FALSE);
6498     pic16_aopOp (result,ic,FALSE);
6499
6500     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6501     /* get the highest order byte into a */
6502     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6503     if(AOP_TYPE(result) == AOP_CRY){
6504         pic16_emitcode("rlc","a");
6505         pic16_outBitC(result);
6506     }
6507     else{
6508         pic16_emitcode("rl","a");
6509         pic16_emitcode("anl","a,#0x01");
6510         pic16_outAcc(result);
6511     }
6512
6513
6514     pic16_freeAsmop(left,NULL,ic,TRUE);
6515     pic16_freeAsmop(result,NULL,ic,TRUE);
6516 }
6517
6518 #if 0
6519 /*-----------------------------------------------------------------*/
6520 /* AccRol - rotate left accumulator by known count                 */
6521 /*-----------------------------------------------------------------*/
6522 static void AccRol (int shCount)
6523 {
6524     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6525     shCount &= 0x0007;              // shCount : 0..7
6526     switch(shCount){
6527         case 0 :
6528             break;
6529         case 1 :
6530             pic16_emitcode("rl","a");
6531             break;
6532         case 2 :
6533             pic16_emitcode("rl","a");
6534             pic16_emitcode("rl","a");
6535             break;
6536         case 3 :
6537             pic16_emitcode("swap","a");
6538             pic16_emitcode("rr","a");
6539             break;
6540         case 4 :
6541             pic16_emitcode("swap","a");
6542             break;
6543         case 5 :
6544             pic16_emitcode("swap","a");
6545             pic16_emitcode("rl","a");
6546             break;
6547         case 6 :
6548             pic16_emitcode("rr","a");
6549             pic16_emitcode("rr","a");
6550             break;
6551         case 7 :
6552             pic16_emitcode("rr","a");
6553             break;
6554     }
6555 }
6556 #endif
6557
6558 /*-----------------------------------------------------------------*/
6559 /* AccLsh - left shift accumulator by known count                  */
6560 /*-----------------------------------------------------------------*/
6561 static void AccLsh (int shCount, int doMask)
6562 {
6563         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6564         switch(shCount){
6565                 case 0 :
6566                         return;
6567                         break;
6568                 case 1 :
6569                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6570                         break;
6571                 case 2 :
6572                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6573                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6574                         break;
6575                 case 3 :
6576                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6577                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6578                         break;
6579                 case 4 :
6580                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6581                         break;
6582                 case 5 :
6583                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6584                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6585                         break;
6586                 case 6 :
6587                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6588                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6589                         break;
6590                 case 7 :
6591                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6592                         break;
6593         }
6594         if (doMask) {
6595                 /* no masking is required in genPackBits */
6596                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6597         }
6598 }
6599
6600 /*-----------------------------------------------------------------*/
6601 /* AccRsh - right shift accumulator by known count                 */
6602 /*-----------------------------------------------------------------*/
6603 static void AccRsh (int shCount, int andmask)
6604 {
6605         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6606         assert ((shCount >= 0) && (shCount <= 8));
6607         switch (shCount) {
6608                 case 0 :
6609                         return; break;
6610                 case 1 :
6611                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6612                         break;
6613                 case 2 :
6614                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6615                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6616                         break;
6617                 case 3 :
6618                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6619                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6620                         break;
6621                 case 4 :
6622                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6623                         break;
6624                 case 5 :
6625                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6626                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6627                         break;
6628                 case 6 :
6629                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6630                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6631                         break;
6632                 case 7 :
6633                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6634                         break;
6635                 default:
6636                         // Rotating by 8 is a NOP.
6637                         break;
6638         }
6639
6640         if (andmask)
6641                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6642         else
6643                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
6644 }
6645
6646 /*-----------------------------------------------------------------*/
6647 /* shiftR1Left2Result - shift right one byte from left to result   */
6648 /*-----------------------------------------------------------------*/
6649 static void shiftR1Left2ResultSigned (operand *left, int offl,
6650                                 operand *result, int offr,
6651                                 int shCount)
6652 {
6653   int same;
6654
6655   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6656   assert ((shCount >= 0) && (shCount <= 8));
6657
6658   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6659
6660   /* Do NOT use result for intermediate results, it might be an SFR!. */
6661   switch (shCount) {
6662   case 0:
6663     if (!same) {
6664       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6665       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6666     }
6667     break;
6668
6669   case 1:
6670     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl));
6671     if (same)
6672       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6673     else {
6674       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl));
6675       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6676     }
6677     break;
6678
6679   case 2:
6680     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6681     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6682     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5>
6683     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5));
6684     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend
6685     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6686     break;
6687
6688   case 3:
6689     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6690     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6691     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4>
6692     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4));
6693     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend
6694     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6695     break;
6696
6697   case 4:
6698     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6699     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3>
6700     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3));
6701     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend
6702     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6703     break;
6704
6705   case 5:
6706     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6707     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6708     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2>
6709     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2));
6710     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend
6711     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6712     break;
6713
6714   case 6:
6715     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6716     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6717     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1>
6718     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1));
6719     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend
6720     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6721     break;
6722
6723   case 7:
6724     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6725     pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7));
6726     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6727     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6728     break;
6729
6730   default:
6731     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6732     break;
6733   }
6734 }
6735
6736 /*-----------------------------------------------------------------*/
6737 /* shiftR1Left2Result - shift right one byte from left to result   */
6738 /*-----------------------------------------------------------------*/
6739 static void shiftR1Left2Result (operand *left, int offl,
6740                                 operand *result, int offr,
6741                                 int shCount, int sign)
6742 {
6743   int same;
6744
6745   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6746   assert ((shCount >= 0) && (shCount <= 8));
6747
6748   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6749
6750   /* Copy the msb into the carry if signed. */
6751   if (sign) {
6752     shiftR1Left2ResultSigned(left, offl, result, offr, shCount);
6753     return;
6754   }
6755
6756   /* Do NOT use result for intermediate results, it might be an SFR!. */
6757   switch (shCount) {
6758   case 0:
6759     if (!same) {
6760       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6761       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6762     }
6763     break;
6764
6765   case 1:
6766     if (same) {
6767       emitCLRC;
6768       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr));
6769     } else {
6770       pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6771       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f));
6772       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6773     }
6774     break;
6775
6776   case 2:
6777     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6778     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6779     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f));
6780     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6781     break;
6782
6783   case 3:
6784     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6785     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6786     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6787     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6788     break;
6789
6790   case 4:
6791     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6792     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6793     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6794     break;
6795
6796   case 5:
6797     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6798     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6799     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07));
6800     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6801     break;
6802
6803   case 6:
6804     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6805     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6806     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03));
6807     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6808     break;
6809
6810   case 7:
6811     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6812     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01));
6813     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6814     break;
6815
6816   default:
6817     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6818     break;
6819   }
6820 }
6821
6822 /*-----------------------------------------------------------------*/
6823 /* shiftL1Left2Result - shift left one byte from left to result    */
6824 /*-----------------------------------------------------------------*/
6825 static void shiftL1Left2Result (operand *left, int offl,
6826                                 operand *result, int offr, int shCount)
6827 {
6828   int same;
6829
6830   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6831   assert ((shCount >= 0) && (shCount <= 8));
6832
6833   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6834
6835   /* Do NOT use result for intermediate results, it might be an SFR!. */
6836   switch (shCount) {
6837   case 0:
6838     if (!same) {
6839       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl));
6840       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6841     }
6842     break;
6843
6844   case 1:
6845     if (same) {
6846       emitCLRC;
6847       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl));
6848     } else {
6849       pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6850       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe));
6851       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6852     }
6853     break;
6854
6855   case 2:
6856     pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl));
6857     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6858     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc));
6859     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6860     break;
6861
6862   case 3:
6863     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6864     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6865     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8));
6866     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6867     break;
6868
6869   case 4:
6870     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6871     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6872     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6873     break;
6874
6875   case 5:
6876     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl));
6877     pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6878     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0));
6879     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6880     break;
6881
6882   case 6:
6883     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6884     pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg));
6885     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0));
6886     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6887     break;
6888
6889   case 7:
6890     pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl));
6891     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6892     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr));
6893     break;
6894
6895   default:
6896     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr));
6897     break;
6898   }
6899 }
6900
6901 /*-----------------------------------------------------------------*/
6902 /* movLeft2Result - move byte from left to result                  */
6903 /*-----------------------------------------------------------------*/
6904 static void movLeft2Result (operand *left, int offl,
6905                             operand *result, int offr)
6906 {
6907   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6908   if (!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)) {
6909     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6910     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6911   }
6912 }
6913
6914 /*-----------------------------------------------------------------*/
6915 /* shiftL2Left2Result - shift left two bytes from left to result   */
6916 /*-----------------------------------------------------------------*/
6917 static void shiftL2Left2Result (operand *left, int offl,
6918                                 operand *result, int offr, int shCount)
6919 {
6920   int same = pic16_sameRegs(AOP(result), AOP(left));
6921   int i;
6922
6923   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6924
6925   if (same && (offl != offr)) { // shift bytes
6926     if (offr > offl) {
6927        for(i=1;i>-1;i--) {
6928          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6929          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6930        }
6931     } else { // just treat as different later on
6932                 same = 0;
6933     }
6934   }
6935
6936   if(same) {
6937     switch(shCount) {
6938     case 0:
6939       break;
6940     case 1:
6941     case 2:
6942     case 3:
6943
6944       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6945       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6946       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6947
6948       while(--shCount) {
6949                 emitCLRC;
6950                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6951                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6952       }
6953
6954       break;
6955     case 4:
6956     case 5:
6957       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6958       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6959       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6960       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6961       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6962       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6963       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6964       if(shCount >=5) {
6965                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6966                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6967       }
6968       break;
6969     case 6:
6970       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6971       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6972       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6973       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6974       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6975       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6976       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6977       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6978       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6979       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6980       break;
6981     case 7:
6982       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6983       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6984       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6985       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6986       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6987     }
6988
6989   } else {
6990     switch(shCount) {
6991     case 0:
6992       break;
6993     case 1:
6994     case 2:
6995     case 3:
6996       /* note, use a mov/add for the shift since the mov has a
6997          chance of getting optimized out */
6998       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6999       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7000       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7001       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7002       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7003
7004       while(--shCount) {
7005                 emitCLRC;
7006                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7007                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7008       }
7009       break;
7010
7011     case 4:
7012     case 5:
7013       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7014       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7015       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7016       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7017       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7018       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
7019       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7020       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7021
7022
7023       if(shCount == 5) {
7024                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7025                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7026       }
7027       break;
7028     case 6:
7029       pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl));
7030       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7031       pic16_emitpcode(POC_RRNCF,  pic16_popGet(AOP(result),offr));
7032       pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl+MSB16));
7033       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr+MSB16));
7034       pic16_emitpcode(POC_RRNCF,  pic16_popGet(AOP(result),offr+MSB16));
7035       pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(0xc0));
7036       pic16_emitpcode(POC_ANDWF,  pic16_popGet(AOP(result),offr+MSB16));
7037       pic16_emitpcode(POC_ANDFW,  pic16_popGet(AOP(result),offr));
7038       pic16_emitpcode(POC_XORFW,  pic16_popGet(AOP(result),offr));
7039       pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(result),offr+MSB16));
7040       pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offr));
7041       break;
7042     case 7:
7043       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7044       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7045       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7046       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7047       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7048     }
7049   }
7050
7051 }
7052 /*-----------------------------------------------------------------*/
7053 /* shiftR2Left2Result - shift right two bytes from left to result  */
7054 /*-----------------------------------------------------------------*/
7055 static void shiftR2Left2Result (operand *left, int offl,
7056                                 operand *result, int offr,
7057                                 int shCount, int sign)
7058 {
7059   int same = pic16_sameRegs(AOP(result), AOP(left));
7060   int i;
7061   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7062
7063   if (same && (offl != offr)) { // shift right bytes
7064     if (offr < offl) {
7065        for(i=0;i<2;i++) {
7066          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7067          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7068        }
7069     } else { // just treat as different later on
7070                 same = 0;
7071     }
7072   }
7073
7074   switch(shCount) {
7075   case 0:
7076     break;
7077   case 1:
7078   case 2:
7079   case 3:
7080     /* obtain sign from left operand */
7081     if(sign)
7082       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
7083     else
7084       emitCLRC;
7085
7086     if(same) {
7087       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7088       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7089     } else {
7090       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7091       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7092       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7093       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7094     }
7095
7096     while(--shCount) {
7097       if(sign)
7098         /* now get sign from already assigned result (avoid BANKSEL) */
7099         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7100       else
7101         emitCLRC;
7102       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7103       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7104     }
7105     break;
7106   case 4:
7107   case 5:
7108     if(same) {
7109
7110       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7111       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7112       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7113
7114       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7115       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7116       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7117       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7118     } else {
7119       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7120       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7121       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7122
7123       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7124       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7125       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7126       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7127       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7128     }
7129
7130     if(shCount >=5) {
7131       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7132       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7133     }
7134
7135     if(sign) {
7136       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7137       pic16_emitpcode(POC_BTFSC,
7138                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
7139       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7140     }
7141
7142     break;
7143
7144   case 6:
7145     if(same) {
7146
7147       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7148       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7149
7150       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7151       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7152       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7153       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7154       if(sign) {
7155         pic16_emitpcode(POC_BTFSC,
7156                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7157         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7158       }
7159       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7160       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7161       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7162       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7163     } else {
7164       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7165       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7166       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7167       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7168       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7169       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7170       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7171       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7172       if(sign) {
7173         pic16_emitpcode(POC_BTFSC,
7174                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7175         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7176       }
7177       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7178       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7179
7180
7181     }
7182
7183     break;
7184   case 7:
7185     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7186     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7187     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7188     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7189     if(sign) {
7190       emitSKPNC;
7191       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7192     } else
7193       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7194   }
7195 }
7196
7197
7198 /*-----------------------------------------------------------------*/
7199 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7200 /*-----------------------------------------------------------------*/
7201 static void shiftLLeftOrResult (operand *left, int offl,
7202                                 operand *result, int offr, int shCount)
7203 {
7204     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7205
7206     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7207     /* shift left accumulator */
7208     AccLsh(shCount, 1);
7209     /* or with result */
7210     /* back to result */
7211     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7212 }
7213
7214 /*-----------------------------------------------------------------*/
7215 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7216 /*-----------------------------------------------------------------*/
7217 static void shiftRLeftOrResult (operand *left, int offl,
7218                                 operand *result, int offr, int shCount)
7219 {
7220     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7221
7222     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7223     /* shift right accumulator */
7224     AccRsh(shCount, 1);
7225     /* or with result */
7226     /* back to result */
7227     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7228 }
7229
7230 /*-----------------------------------------------------------------*/
7231 /* genlshOne - left shift a one byte quantity by known count       */
7232 /*-----------------------------------------------------------------*/
7233 static void genlshOne (operand *result, operand *left, int shCount)
7234 {
7235     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7236     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7237 }
7238
7239 /*-----------------------------------------------------------------*/
7240 /* genlshTwo - left shift two bytes by known amount != 0           */
7241 /*-----------------------------------------------------------------*/
7242 static void genlshTwo (operand *result,operand *left, int shCount)
7243 {
7244     int size;
7245
7246     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7247     size = pic16_getDataSize(result);
7248
7249     /* if shCount >= 8 */
7250     if (shCount >= 8) {
7251         shCount -= 8 ;
7252
7253         if (size > 1){
7254             if (shCount)
7255                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7256             else
7257                 movLeft2Result(left, LSB, result, MSB16);
7258         }
7259         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7260     }
7261
7262     /*  1 <= shCount <= 7 */
7263     else {
7264         if(size == 1)
7265             shiftL1Left2Result(left, LSB, result, LSB, shCount);
7266         else
7267             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7268     }
7269 }
7270
7271 /*-----------------------------------------------------------------*/
7272 /* shiftLLong - shift left one long from left to result            */
7273 /* offr = LSB or MSB16                                             */
7274 /*-----------------------------------------------------------------*/
7275 static void shiftLLong (operand *left, operand *result, int offr )
7276 {
7277     int size = AOP_SIZE(result);
7278     int same = pic16_sameRegs(AOP(left),AOP(result));
7279         int i;
7280
7281     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7282
7283         if (same && (offr == MSB16)) { //shift one byte
7284                 for(i=size-1;i>=MSB16;i--) {
7285                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7286                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7287                 }
7288         } else {
7289                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB));
7290         }
7291
7292     if (size > LSB+offr ){
7293                 if (same) {
7294                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7295                 } else {
7296                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7297                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7298                 }
7299          }
7300
7301     if(size > MSB16+offr){
7302                 if (same) {
7303                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7304                 } else {
7305                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7306                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7307                 }
7308     }
7309
7310     if(size > MSB24+offr){
7311                 if (same) {
7312                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7313                 } else {
7314                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7315                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7316                 }
7317     }
7318
7319     if(size > MSB32+offr){
7320                 if (same) {
7321                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7322                 } else {
7323                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7324                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7325                 }
7326     }
7327     if(offr != LSB)
7328                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7329
7330 }
7331
7332 /*-----------------------------------------------------------------*/
7333 /* genlshFour - shift four byte by a known amount != 0             */
7334 /*-----------------------------------------------------------------*/
7335 static void genlshFour (operand *result, operand *left, int shCount)
7336 {
7337     int size;
7338
7339     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7340     size = AOP_SIZE(result);
7341
7342     /* if shifting more that 3 bytes */
7343     if (shCount >= 24 ) {
7344         shCount -= 24;
7345         if (shCount)
7346             /* lowest order of left goes to the highest
7347             order of the destination */
7348             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7349         else
7350             movLeft2Result(left, LSB, result, MSB32);
7351
7352                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7353                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7354                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7355
7356         return;
7357     }
7358
7359     /* more than two bytes */
7360     else if ( shCount >= 16 ) {
7361         /* lower order two bytes goes to higher order two bytes */
7362         shCount -= 16;
7363         /* if some more remaining */
7364         if (shCount)
7365             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7366         else {
7367             movLeft2Result(left, MSB16, result, MSB32);
7368             movLeft2Result(left, LSB, result, MSB24);
7369         }
7370                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7371                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7372         return;
7373     }
7374
7375     /* if more than 1 byte */
7376     else if ( shCount >= 8 ) {
7377         /* lower order three bytes goes to higher order  three bytes */
7378         shCount -= 8;
7379         if(size == 2){
7380             if(shCount)
7381                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7382             else
7383                 movLeft2Result(left, LSB, result, MSB16);
7384         }
7385         else{   /* size = 4 */
7386             if(shCount == 0){
7387                 movLeft2Result(left, MSB24, result, MSB32);
7388                 movLeft2Result(left, MSB16, result, MSB24);
7389                 movLeft2Result(left, LSB, result, MSB16);
7390                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7391             }
7392             else if(shCount == 1)
7393                 shiftLLong(left, result, MSB16);
7394             else{
7395                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7396                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7397                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7398                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7399             }
7400         }
7401     }
7402
7403     /* 1 <= shCount <= 7 */
7404     else if(shCount <= 3)
7405     {
7406         shiftLLong(left, result, LSB);
7407         while(--shCount >= 1)
7408             shiftLLong(result, result, LSB);
7409     }
7410     /* 3 <= shCount <= 7, optimize */
7411     else{
7412         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7413         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7414         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7415     }
7416 }
7417
7418 /*-----------------------------------------------------------------*/
7419 /* genLeftShiftLiteral - left shifting by known count              */
7420 /*-----------------------------------------------------------------*/
7421 void pic16_genLeftShiftLiteral (operand *left,
7422                                  operand *right,
7423                                  operand *result,
7424                                  iCode *ic)
7425 {
7426     int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7427     int size;
7428
7429     FENTRY;
7430     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
7431     pic16_freeAsmop(right,NULL,ic,TRUE);
7432
7433     pic16_aopOp(left,ic,FALSE);
7434     pic16_aopOp(result,ic,TRUE);
7435
7436     size = getSize(operandType(result));
7437
7438 #if VIEW_SIZE
7439     pic16_emitcode("; shift left ","result %d, left %d",size,
7440              AOP_SIZE(left));
7441 #endif
7442
7443     /* I suppose that the left size >= result size */
7444     if(shCount == 0){
7445         while(size--){
7446             movLeft2Result(left, size, result, size);
7447         }
7448     }
7449
7450     else if(shCount >= (size * 8))
7451         while(size--)
7452             pic16_aopPut(AOP(result),zero,size);
7453     else{
7454         switch (size) {
7455             case 1:
7456                 genlshOne (result,left,shCount);
7457                 break;
7458
7459             case 2:
7460             case 3:
7461                 genlshTwo (result,left,shCount);
7462                 break;
7463
7464             case 4:
7465                 genlshFour (result,left,shCount);
7466                 break;
7467         }
7468     }
7469     pic16_freeAsmop(left,NULL,ic,TRUE);
7470     pic16_freeAsmop(result,NULL,ic,TRUE);
7471 }
7472
7473 /*-----------------------------------------------------------------*
7474  * genMultiAsm - repeat assembly instruction for size of register.
7475  * if endian == 1, then the high byte (i.e base address + size of
7476  * register) is used first else the low byte is used first;
7477  *-----------------------------------------------------------------*/
7478 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7479 {
7480
7481   int offset = 0;
7482
7483   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7484
7485   if(!reg)
7486     return;
7487
7488   if(!endian) {
7489     endian = 1;
7490   } else {
7491     endian = -1;
7492     offset = size-1;
7493   }
7494
7495   while(size--) {
7496     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7497     offset += endian;
7498   }
7499
7500 }
7501
7502 /*-----------------------------------------------------------------*/
7503 /* genrshOne - right shift a one byte quantity by known count      */
7504 /*-----------------------------------------------------------------*/
7505 static void genrshOne (operand *result, operand *left,
7506                        int shCount, int sign)
7507 {
7508     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7509     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7510 }
7511
7512 /*-----------------------------------------------------------------*/
7513 /* genrshTwo - right shift two bytes by known amount != 0          */
7514 /*-----------------------------------------------------------------*/
7515 static void genrshTwo (operand *result,operand *left,
7516                        int shCount, int sign)
7517 {
7518   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7519   /* if shCount >= 8 */
7520   if (shCount >= 8) {
7521     shCount -= 8 ;
7522     if (shCount)
7523       shiftR1Left2Result(left, MSB16, result, LSB,
7524                          shCount, sign);
7525     else
7526       movLeft2Result(left, MSB16, result, LSB);
7527
7528     pic16_addSign (result, 1, sign);
7529   }
7530
7531   /*  1 <= shCount <= 7 */
7532   else
7533     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
7534 }
7535
7536 /*-----------------------------------------------------------------*/
7537 /* shiftRLong - shift right one long from left to result           */
7538 /* offl = LSB or MSB16                                             */
7539 /*-----------------------------------------------------------------*/
7540 static void shiftRLong (operand *left, int offl,
7541                         operand *result, int sign)
7542 {
7543     int size = AOP_SIZE(result);
7544     int same = pic16_sameRegs(AOP(left),AOP(result));
7545     int i;
7546     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7547
7548         if (same && (offl == MSB16)) { //shift one byte right
7549                 for(i=MSB16;i<size;i++) {
7550                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7551                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7552                 }
7553         }
7554
7555     if(sign)
7556                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7557         else
7558                 emitCLRC;
7559
7560         if (same) {
7561                 if (offl == LSB)
7562                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7563         } else {
7564         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7565         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7566         }
7567
7568     if(offl == MSB16) {
7569         /* add sign of "a" */
7570         pic16_addSign(result, MSB32, sign);
7571         }
7572
7573         if (same) {
7574         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7575         } else {
7576         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7577         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7578         }
7579
7580         if (same) {
7581         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7582         } else {
7583         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7584         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7585         }
7586
7587         if (same) {
7588         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7589         } else {
7590         if(offl == LSB){
7591                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7592                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7593         }
7594         }
7595 }
7596
7597 /*-----------------------------------------------------------------*/
7598 /* genrshFour - shift four byte by a known amount != 0             */
7599 /*-----------------------------------------------------------------*/
7600 static void genrshFour (operand *result, operand *left,
7601                         int shCount, int sign)
7602 {
7603   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7604   /* if shifting more that 3 bytes */
7605   if(shCount >= 24 ) {
7606     shCount -= 24;
7607     if(shCount)
7608       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7609     else
7610       movLeft2Result(left, MSB32, result, LSB);
7611
7612     pic16_addSign(result, MSB16, sign);
7613   }
7614   else if(shCount >= 16){
7615     shCount -= 16;
7616     if(shCount)
7617       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7618     else{
7619       movLeft2Result(left, MSB24, result, LSB);
7620       movLeft2Result(left, MSB32, result, MSB16);
7621     }
7622     pic16_addSign(result, MSB24, sign);
7623   }
7624   else if(shCount >= 8){
7625     shCount -= 8;
7626     if(shCount == 1)
7627       shiftRLong(left, MSB16, result, sign);
7628     else if(shCount == 0){
7629       movLeft2Result(left, MSB16, result, LSB);
7630       movLeft2Result(left, MSB24, result, MSB16);
7631       movLeft2Result(left, MSB32, result, MSB24);
7632       pic16_addSign(result, MSB32, sign);
7633     }
7634     else{ //shcount >= 2
7635       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7636       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7637       /* the last shift is signed */
7638       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7639       pic16_addSign(result, MSB32, sign);
7640     }
7641   }
7642   else{   /* 1 <= shCount <= 7 */
7643     if(shCount <= 2){
7644       shiftRLong(left, LSB, result, sign);
7645       if(shCount == 2)
7646         shiftRLong(result, LSB, result, sign);
7647     }
7648     else{
7649       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7650       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7651       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7652     }
7653   }
7654 }
7655
7656 /*-----------------------------------------------------------------*/
7657 /* genRightShiftLiteral - right shifting by known count            */
7658 /*-----------------------------------------------------------------*/
7659 static void genRightShiftLiteral (operand *left,
7660                                   operand *right,
7661                                   operand *result,
7662                                   iCode *ic,
7663                                   int sign)
7664 {
7665   int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit));
7666   int lsize,res_size;
7667
7668   pic16_freeAsmop(right,NULL,ic,TRUE);
7669
7670   pic16_aopOp(left,ic,FALSE);
7671   pic16_aopOp(result,ic,TRUE);
7672
7673   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7674
7675 #if VIEW_SIZE
7676   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7677                  AOP_SIZE(left));
7678 #endif
7679
7680   lsize = pic16_getDataSize(left);
7681   res_size = pic16_getDataSize(result);
7682   /* test the LEFT size !!! */
7683
7684   /* I suppose that the left size >= result size */
7685   if (shCount == 0) {
7686     assert (res_size <= lsize);
7687     while (res_size--) {
7688       pic16_mov2f (AOP(result), AOP(left), res_size);
7689     } // for
7690   } else if (shCount >= (lsize * 8)) {
7691     if (sign) {
7692       /*
7693        * Do NOT use
7694        *    CLRF    result
7695        *    BTFSC   left, 7
7696        *    SETF    result
7697        * even for 8-bit operands; result might be an SFR.
7698        */
7699       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7700       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7));
7701       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7702       while (res_size--) {
7703         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size));
7704       }
7705     } else { // unsigned
7706       while (res_size--) {
7707         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size));
7708       }
7709     }
7710   } else { // 0 < shCount < 8*lsize
7711     switch (res_size) {
7712     case 1:
7713       genrshOne (result,left,shCount,sign);
7714       break;
7715
7716     case 2:
7717       genrshTwo (result,left,shCount,sign);
7718       break;
7719
7720     case 4:
7721       genrshFour (result,left,shCount,sign);
7722       break;
7723     default :
7724       break;
7725     }
7726   }
7727
7728   pic16_freeAsmop(left,NULL,ic,TRUE);
7729   pic16_freeAsmop(result,NULL,ic,TRUE);
7730 }
7731
7732 /*-----------------------------------------------------------------*/
7733 /* genGenericShift - generates code for left or right shifting     */
7734 /*-----------------------------------------------------------------*/
7735 static void genGenericShift (iCode *ic, int isShiftLeft)
7736 {
7737   operand *left,*right, *result;
7738   int offset;
7739   int sign, signedCount;
7740   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
7741   PIC_OPCODE pos_shift, neg_shift;
7742
7743   FENTRY;
7744
7745   right = IC_RIGHT(ic);
7746   left  = IC_LEFT(ic);
7747   result = IC_RESULT(ic);
7748
7749   pic16_aopOp(right,ic,FALSE);
7750   pic16_aopOp(left,ic,FALSE);
7751   pic16_aopOp(result,ic,TRUE);
7752
7753   sign = !SPEC_USIGN(operandType (left));
7754   signedCount = !SPEC_USIGN(operandType (right));
7755
7756   /* if the shift count is known then do it
7757      as efficiently as possible */
7758   if (AOP_TYPE(right) == AOP_LIT) {
7759     long lit = (long) ulFromVal (AOP(right)->aopu.aop_lit);
7760     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
7761     // we should modify right->aopu.aop_lit here!
7762     // Instead we use abs(shCount) in genXXXShiftLiteral()...
7763     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
7764     if (isShiftLeft)
7765       pic16_genLeftShiftLiteral (left,right,result,ic);
7766     else
7767       genRightShiftLiteral (left,right,result,ic, sign);
7768
7769     goto release;
7770   } // if (right is literal)
7771
7772   /* shift count is unknown then we have to form a loop.
7773    * Note: we take only the lower order byte since shifting
7774    * more than 32 bits make no sense anyway, ( the
7775    * largest size of an object can be only 32 bits )
7776    * Note: we perform arithmetic shifts if the left operand is
7777    * signed and we do an (effective) right shift, i. e. we
7778    * shift in the sign bit from the left. */
7779
7780   label_complete = newiTempLabel ( NULL );
7781   label_loop_pos = newiTempLabel ( NULL );
7782   label_loop_neg = NULL;
7783   label_negative = NULL;
7784   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
7785   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
7786
7787   if (signedCount) {
7788     // additional labels needed
7789     label_loop_neg = newiTempLabel ( NULL );
7790     label_negative = newiTempLabel ( NULL );
7791   } // if
7792
7793   // copy source to result -- this will effectively truncate the left operand to the size of result!
7794   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
7795   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
7796   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
7797     pic16_mov2f (AOP(result),AOP(left), offset);
7798   } // for
7799
7800   // if result is longer than left, fill with zeros (or sign)
7801   if (AOP_SIZE(left) < AOP_SIZE(result)) {
7802     if (sign && AOP_SIZE(left) > 0) {
7803       // shift signed operand -- fill with sign
7804       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
7805       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
7806       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
7807       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7808         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
7809       } // for
7810     } else {
7811       // shift unsigned operand -- fill result with zeros
7812       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
7813         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
7814       } // for
7815     }
7816   } // if (size mismatch)
7817
7818   pic16_mov2w (AOP(right), 0);
7819   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
7820   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
7821
7822 #if 0
7823   // perform a shift by one (shift count is positive)
7824   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7825   // 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])
7826   pic16_emitpLabel (label_loop_pos->key);
7827   emitCLRC;
7828   if (sign && (pos_shift == POC_RRCF)) {
7829     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7830     emitSETC;
7831   } // if
7832   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7833   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
7834   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
7835 #else
7836   // perform a shift by one (shift count is positive)
7837   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
7838   // 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])
7839   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
7840   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
7841   emitCLRC;
7842   pic16_emitpLabel (label_loop_pos->key);
7843   if (sign && (pos_shift == POC_RRCF)) {
7844     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7845     emitSETC;
7846   } // if
7847   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
7848   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7849   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7850   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
7851 #endif
7852
7853   if (signedCount) {
7854     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
7855
7856     pic16_emitpLabel (label_negative->key);
7857     // perform a shift by -1 (shift count is negative)
7858     // 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)
7859     emitCLRC;
7860     pic16_emitpLabel (label_loop_neg->key);
7861     if (sign && (neg_shift == POC_RRCF)) {
7862       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
7863       emitSETC;
7864     } // if
7865     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
7866     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
7867     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
7868     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
7869   } // if (signedCount)
7870
7871   pic16_emitpLabel (label_complete->key);
7872
7873 release:
7874   pic16_freeAsmop (right,NULL,ic,TRUE);
7875   pic16_freeAsmop(left,NULL,ic,TRUE);
7876   pic16_freeAsmop(result,NULL,ic,TRUE);
7877 }
7878
7879 static void genLeftShift (iCode *ic) {
7880   genGenericShift (ic, 1);
7881 }
7882
7883 static void genRightShift (iCode *ic) {
7884   genGenericShift (ic, 0);
7885 }
7886
7887
7888 /* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */
7889 void pic16_loadFSR0(operand *op, int lit)
7890 {
7891   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || pic16_isLitOp( op )) {
7892     if (AOP_TYPE(op) == AOP_LIT) {
7893       /* handle 12 bit integers correctly */
7894       unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit);
7895       if ((val & 0x0fff) != val) {
7896         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
7897                 val, (val & 0x0fff) );
7898         val &= 0x0fff;
7899       }
7900       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
7901     } else {
7902       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
7903     }
7904   } else {
7905     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
7906     // set up FSR0 with address of result
7907     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
7908     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
7909   }
7910 }
7911
7912 /*----------------------------------------------------------------*/
7913 /* pic16_derefPtr - move one byte from the location ptr points to */
7914 /*                  to WREG (doWrite == 0) or one byte from WREG   */
7915 /*                  to the location ptr points to (doWrite != 0)   */
7916 /*----------------------------------------------------------------*/
7917 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
7918 {
7919   if (!IS_PTR(operandType(ptr)))
7920   {
7921     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
7922     else pic16_mov2w (AOP(ptr), 0);
7923     return;
7924   }
7925
7926   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
7927   /* We might determine pointer type right here: */
7928   p_type = DCL_TYPE(operandType(ptr));
7929
7930   switch (p_type) {
7931     case POINTER:
7932     case FPOINTER:
7933     case IPOINTER:
7934     case PPOINTER:
7935       if (!fsr0_setup || !*fsr0_setup)
7936       {
7937         pic16_loadFSR0( ptr, 0 );
7938         if (fsr0_setup) *fsr0_setup = 1;
7939       }
7940       if (doWrite)
7941         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7942       else
7943         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7944       break;
7945
7946     case GPOINTER:
7947       if (AOP(ptr)->aopu.aop_reg[2]) {
7948         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
7949         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
7950         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
7951         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
7952         pic16_mov2w(AOP(ptr), 2);
7953         pic16_callGenericPointerRW(doWrite, 1);
7954       } else {
7955         // data pointer (just 2 byte given)
7956         if (!fsr0_setup || !*fsr0_setup)
7957         {
7958           pic16_loadFSR0( ptr, 0 );
7959           if (fsr0_setup) *fsr0_setup = 1;
7960         }
7961         if (doWrite)
7962           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
7963         else
7964           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
7965       }
7966       break;
7967
7968     case CPOINTER:
7969       /* XXX: Writing to CPOINTERs not (yet) implemented. */
7970       assert ( !doWrite && "Cannot write into __code space!" );
7971       if( (AOP_TYPE(ptr) == AOP_PCODE)
7972               && ((AOP(ptr)->aopu.pcop->type == PO_IMMEDIATE)
7973                   || (AOP(ptr)->aopu.pcop->type == PO_DIR)))
7974       {
7975           pic16_emitpcode(POC_MOVLW, pic16_popGet     (AOP (ptr), 0));
7976           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptrl));
7977           pic16_emitpcode(POC_MOVLW, pic16_popGet     (AOP (ptr), 1));
7978           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptrh));
7979           pic16_emitpcode(POC_MOVLW, pic16_popGet     (AOP (ptr), 2));
7980           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptru));
7981       } else {
7982           mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(ptr), 0);
7983           mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(ptr), 1);
7984           mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(ptr), 2);
7985       } // if
7986
7987       pic16_emitpcodeNULLop (POC_TBLRD_POSTINC);
7988       pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (&pic16_pc_tablat));
7989       break;
7990
7991     default:
7992       assert (0 && "invalid pointer type specified");
7993       break;
7994   }
7995 }
7996
7997 /*-----------------------------------------------------------------*/
7998 /* genUnpackBits - generates code for unpacking bits               */
7999 /*-----------------------------------------------------------------*/
8000 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
8001 {
8002   int shCnt ;
8003   sym_link *etype, *letype;
8004   int blen=0, bstr=0;
8005   int lbstr;
8006   int same;
8007   pCodeOp *op;
8008
8009   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8010   etype = getSpec(operandType(result));
8011   letype = getSpec(operandType(left));
8012
8013   //    if(IS_BITFIELD(etype)) {
8014   blen = SPEC_BLEN(etype);
8015   bstr = SPEC_BSTR(etype);
8016   //    }
8017
8018   lbstr = SPEC_BSTR( letype );
8019
8020   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
8021       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
8022
8023 #if 1
8024   if((blen == 1) && (bstr < 8)
8025       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
8026     /* it is a single bit, so use the appropriate bit instructions */
8027     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
8028
8029     same = pic16_sameRegs(AOP(left),AOP(result));
8030     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
8031     pic16_emitpcode(POC_CLRF, op);
8032
8033     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8034       /* workaround to reduce the extra lfsr instruction */
8035       pic16_emitpcode(POC_BTFSC,
8036           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
8037     } else {
8038       assert (PIC_IS_DATA_PTR (operandType(left)));
8039       pic16_loadFSR0 (left, 0);
8040       pic16_emitpcode(POC_BTFSC,
8041           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8042     }
8043
8044     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8045       /* unsigned bitfields result in either 0 or 1 */
8046       pic16_emitpcode(POC_INCF, op);
8047     } else {
8048       /* signed bitfields result in either 0 or -1 */
8049       pic16_emitpcode(POC_DECF, op);
8050     }
8051     if (same) {
8052       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
8053     }
8054
8055     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8056     return;
8057   }
8058
8059 #endif
8060
8061   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
8062     // access symbol directly
8063     pic16_mov2w (AOP(left), 0);
8064   } else {
8065     pic16_derefPtr (left, ptype, 0, NULL);
8066   }
8067
8068   /* if we have bitdisplacement then it fits   */
8069   /* into this byte completely or if length is */
8070   /* less than a byte                          */
8071   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
8072
8073     /* shift right acc */
8074     AccRsh(shCnt, 0);
8075
8076     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8077           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8078
8079     /* VR -- normally I would use the following, but since we use the hack,
8080      * to avoid the masking from AccRsh, why not mask it right now? */
8081
8082     /*
8083        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8084      */
8085
8086     /* extend signed bitfields to 8 bits */
8087     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
8088     {
8089       assert (blen + bstr > 0);
8090       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
8091       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
8092     }
8093
8094     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8095
8096     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
8097     return ;
8098   }
8099
8100   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
8101   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8102   exit(EXIT_FAILURE);
8103
8104   return ;
8105 }
8106
8107
8108 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
8109 {
8110   int size, offset = 0, leoffset=0 ;
8111
8112         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8113         pic16_aopOp(result, ic, TRUE);
8114
8115         FENTRY;
8116
8117         size = AOP_SIZE(result);
8118 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8119
8120
8121 #if 1
8122         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
8123                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
8124                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
8125                 goto release;
8126         }
8127 #endif
8128
8129         if(AOP(left)->aopu.pcop->type == PO_DIR)
8130                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
8131
8132         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8133
8134         while (size--) {
8135                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
8136
8137 //              pic16_DumpOp("(result)",result);
8138                 if(pic16_isLitAop(AOP(result))) {
8139                         pic16_mov2w(AOP(left), offset); // patch 8
8140                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
8141                 } else {
8142                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
8143                                 pic16_popGet(AOP(left), offset), //patch 8
8144                                 pic16_popGet(AOP(result), offset)));
8145                 }
8146
8147                 offset++;
8148                 leoffset++;
8149         }
8150
8151 release:
8152     pic16_freeAsmop(result,NULL,ic,TRUE);
8153 }
8154
8155
8156
8157 /*-----------------------------------------------------------------*/
8158 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8159 /*-----------------------------------------------------------------*/
8160 static void genNearPointerGet (operand *left,
8161                                operand *result,
8162                                iCode *ic)
8163 {
8164 //  asmop *aop = NULL;
8165   //regs *preg = NULL ;
8166   sym_link *rtype, *retype;
8167   sym_link *ltype, *letype;
8168
8169     FENTRY;
8170
8171     rtype = operandType(result);
8172     retype= getSpec(rtype);
8173     ltype = operandType(left);
8174     letype= getSpec(ltype);
8175
8176     pic16_aopOp(left,ic,FALSE);
8177
8178 //    pic16_DumpOp("(left)",left);
8179 //    pic16_DumpOp("(result)",result);
8180
8181     /* if left is rematerialisable and
8182      * result is not bit variable type and
8183      * the left is pointer to data space i.e
8184      * lower 128 bytes of space */
8185
8186     if (AOP_TYPE(left) == AOP_PCODE
8187       && !IS_BITFIELD(retype)
8188       && DCL_TYPE(ltype) == POINTER) {
8189
8190         genDataPointerGet (left,result,ic);
8191         pic16_freeAsmop(left, NULL, ic, TRUE);
8192         return ;
8193     }
8194
8195     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8196     pic16_aopOp (result,ic,TRUE);
8197
8198     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
8199
8200 #if 1
8201     if(IS_BITFIELD( retype )
8202       && (SPEC_BLEN(retype)==1)
8203     ) {
8204       iCode *nextic;
8205       pCodeOp *jop;
8206       int bitstrt, bytestrt;
8207
8208         /* if this is bitfield of size 1, see if we are checking the value
8209          * of a single bit in an if-statement,
8210          * if yes, then don't generate usual code, but execute the
8211          * genIfx directly -- VR */
8212
8213         nextic = ic->next;
8214
8215         /* CHECK: if next iCode is IFX
8216          * and current result operand is nextic's conditional operand
8217          * and current result operand live ranges ends at nextic's key number
8218          */
8219         if((nextic->op == IFX)
8220           && (result == IC_COND(nextic))
8221           && (OP_LIVETO(result) == nextic->seq)
8222           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
8223           ) {
8224             /* everything is ok then */
8225             /* find a way to optimize the genIfx iCode */
8226
8227             bytestrt = SPEC_BSTR(retype)/8;
8228             bitstrt = SPEC_BSTR(retype)%8;
8229
8230             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
8231
8232             genIfxpCOpJump(nextic, jop);
8233
8234             pic16_freeAsmop(left, NULL, ic, TRUE);
8235             pic16_freeAsmop(result, NULL, ic, TRUE);
8236             return;
8237         }
8238     }
8239 #endif
8240
8241     /* if bitfield then unpack the bits */
8242     if (IS_BITFIELD(letype))
8243       genUnpackBits (result, left, NULL, POINTER);
8244     else {
8245       /* we have can just get the values */
8246       int size = AOP_SIZE(result);
8247       int offset = 0;
8248
8249       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8250
8251       pic16_loadFSR0( left, 0 );
8252
8253       while(size--) {
8254         if(size) {
8255           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
8256                 pic16_popGet(AOP(result), offset++)));
8257         } else {
8258           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
8259                 pic16_popGet(AOP(result), offset++)));
8260         }
8261       }
8262     }
8263
8264 #if 0
8265     /* now some housekeeping stuff */
8266     if (aop) {
8267       /* we had to allocate for this iCode */
8268       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8269       pic16_freeAsmop(NULL,aop,ic,TRUE);
8270     } else {
8271       /* we did not allocate which means left
8272        * already in a pointer register, then
8273        * if size > 0 && this could be used again
8274        * we have to point it back to where it
8275        * belongs */
8276       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8277       if (AOP_SIZE(result) > 1
8278         && !OP_SYMBOL(left)->remat
8279         && ( OP_SYMBOL(left)->liveTo > ic->seq
8280             || ic->depth )) {
8281 //        int size = AOP_SIZE(result) - 1;
8282 //        while (size--)
8283 //          pic16_emitcode("dec","%s",rname);
8284         }
8285     }
8286 #endif
8287
8288     /* done */
8289     pic16_freeAsmop(left,NULL,ic,TRUE);
8290     pic16_freeAsmop(result,NULL,ic,TRUE);
8291 }
8292
8293 /*-----------------------------------------------------------------*/
8294 /* genGenPointerGet - gget value from generic pointer space        */
8295 /*-----------------------------------------------------------------*/
8296 static void genGenPointerGet (operand *left,
8297                               operand *result, iCode *ic)
8298 {
8299   int size;
8300   sym_link *letype = getSpec(operandType(left));
8301
8302   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8303   pic16_aopOp(left,ic,FALSE);
8304   pic16_aopOp(result,ic,TRUE);
8305   size = AOP_SIZE(result);
8306
8307   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8308
8309   /* if bit then unpack */
8310   if (IS_BITFIELD(letype)) {
8311     genUnpackBits(result,left,"BAD",GPOINTER);
8312     goto release;
8313   }
8314
8315   /* set up WREG:PRODL:FSR0L with address from left */
8316   mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
8317   mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
8318   pic16_mov2w(AOP(left), 2);
8319   pic16_callGenericPointerRW(0, size);
8320
8321   assignResultValue(result, size, 1);
8322
8323 release:
8324   pic16_freeAsmop(left,NULL,ic,TRUE);
8325   pic16_freeAsmop(result,NULL,ic,TRUE);
8326 }
8327
8328 /*-----------------------------------------------------------------*/
8329 /* genConstPointerGet - get value from const generic pointer space */
8330 /*-----------------------------------------------------------------*/
8331 static void genConstPointerGet (operand *left,
8332                                 operand *result, iCode *ic)
8333 {
8334   //sym_link *retype = getSpec(operandType(result));
8335   // symbol *albl = newiTempLabel(NULL);        // patch 15
8336   // symbol *blbl = newiTempLabel(NULL);        //
8337   // PIC_OPCODE poc;                            // patch 15
8338   int size;
8339   int offset = 0;
8340
8341   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8342   pic16_aopOp(left,ic,FALSE);
8343   pic16_aopOp(result,ic,TRUE);
8344   size = AOP_SIZE(result);
8345
8346   /* if bit then unpack */
8347   if (IS_BITFIELD(getSpec (operandType (left)))) {
8348     genUnpackBits(result,left,"BAD",GPOINTER);
8349     goto release;
8350   } // if
8351
8352   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8353
8354   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8355
8356   // set up table pointer
8357   if( (AOP_TYPE(left) == AOP_PCODE)
8358       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
8359           || (AOP(left)->aopu.pcop->type == PO_DIR)))
8360     {
8361       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
8362       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
8363       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
8364       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
8365       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
8366       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
8367   } else {
8368     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
8369     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
8370     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
8371   }
8372
8373   while(size--) {
8374     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
8375     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
8376     offset++;
8377   }
8378
8379 release:
8380   pic16_freeAsmop(left,NULL,ic,TRUE);
8381   pic16_freeAsmop(result,NULL,ic,TRUE);
8382 }
8383
8384
8385 /*-----------------------------------------------------------------*/
8386 /* genPointerGet - generate code for pointer get                   */
8387 /*-----------------------------------------------------------------*/
8388 static void genPointerGet (iCode *ic)
8389 {
8390   operand *left, *result ;
8391   sym_link *type, *etype;
8392   int p_type;
8393
8394     FENTRY;
8395
8396     left = IC_LEFT(ic);
8397     result = IC_RESULT(ic) ;
8398
8399     /* depending on the type of pointer we need to
8400     move it to the correct pointer register */
8401     type = operandType(left);
8402     etype = getSpec(type);
8403
8404 #if 0
8405     if (IS_PTR_CONST(type))
8406 #else
8407     if (IS_CODEPTR(type))
8408 #endif
8409       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8410
8411     /* if left is of type of pointer then it is simple */
8412     if (IS_PTR(type) && !IS_FUNC(type->next))
8413       p_type = DCL_TYPE(type);
8414     else {
8415       /* we have to go by the storage class */
8416       p_type = PTR_TYPE(SPEC_OCLS(etype));
8417
8418       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8419
8420       if (SPEC_OCLS(etype)->codesp ) {
8421         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8422         //p_type = CPOINTER ;
8423       } else
8424       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
8425         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8426         /*p_type = FPOINTER ;*/
8427       } else
8428       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
8429         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8430         /* p_type = PPOINTER; */
8431       } else
8432       if (SPEC_OCLS(etype) == idata ) {
8433         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8434         /* p_type = IPOINTER; */
8435       } else {
8436         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8437         /* p_type = POINTER ; */
8438       }
8439     }
8440
8441     /* now that we have the pointer type we assign
8442     the pointer values */
8443     switch (p_type) {
8444       case POINTER:
8445       case FPOINTER:
8446       case IPOINTER:
8447       case PPOINTER:
8448         genNearPointerGet (left,result,ic);
8449         break;
8450
8451       case CPOINTER:
8452         genConstPointerGet (left,result,ic);
8453         //pic16_emitcodePointerGet (left,result,ic);
8454         break;
8455
8456       case GPOINTER:
8457 #if 0
8458       if (IS_PTR_CONST(type))
8459         genConstPointerGet (left,result,ic);
8460       else
8461 #endif
8462         genGenPointerGet (left,result,ic);
8463       break;
8464
8465     default:
8466       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8467               "genPointerGet: illegal pointer type");
8468
8469     }
8470 }
8471
8472 /*-----------------------------------------------------------------*/
8473 /* genPackBits - generates code for packed bit storage             */
8474 /*-----------------------------------------------------------------*/
8475 static void genPackBits (sym_link    *etype , operand *result,
8476                          operand *right ,
8477                          char *rname, int p_type)
8478 {
8479   int shCnt = 0 ;
8480   int offset = 0  ;
8481   int rLen = 0 ;
8482   int blen, bstr ;
8483   int shifted_and_masked = 0;
8484   unsigned long lit = (unsigned long)-1;
8485   sym_link *retype;
8486
8487   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8488   blen = SPEC_BLEN(etype);
8489   bstr = SPEC_BSTR(etype);
8490
8491   retype = getSpec(operandType(right));
8492
8493   if(AOP_TYPE(right) == AOP_LIT) {
8494     lit = ulFromVal (AOP(right)->aopu.aop_lit);
8495
8496     if((blen == 1) && (bstr < 8)) {
8497       /* it is a single bit, so use the appropriate bit instructions */
8498
8499       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
8500
8501       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
8502         /* workaround to reduce the extra lfsr instruction */
8503         if(lit) {
8504           pic16_emitpcode(POC_BSF,
8505               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8506         } else {
8507           pic16_emitpcode(POC_BCF,
8508               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
8509         }
8510       } else {
8511         if (PIC_IS_DATA_PTR(operandType(result))) {
8512           pic16_loadFSR0(result, 0);
8513           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8514               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
8515         } else {
8516           /* get old value */
8517           pic16_derefPtr (result, p_type, 0, NULL);
8518           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
8519               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8520           /* write back new value */
8521           pic16_derefPtr (result, p_type, 1, NULL);
8522         }
8523       }
8524
8525       return;
8526     }
8527     /* IORLW below is more efficient */
8528     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
8529     lit = (lit & ((1UL << blen) - 1)) << bstr;
8530     shifted_and_masked = 1;
8531     offset++;
8532   } else
8533     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
8534         && IS_BITFIELD(retype)
8535         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
8536         && (blen == 1)) {
8537       int rblen, rbstr;
8538
8539       rblen = SPEC_BLEN( retype );
8540       rbstr = SPEC_BSTR( retype );
8541
8542       if(IS_BITFIELD(etype)) {
8543         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
8544         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8545       } else {
8546         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
8547       }
8548
8549       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
8550
8551       if(IS_BITFIELD(etype)) {
8552         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
8553       } else {
8554         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
8555       }
8556
8557       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
8558
8559       return;
8560     } else {
8561       /* move right to W */
8562       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
8563     }
8564
8565   /* if the bit length is less than or   */
8566   /* it exactly fits a byte then         */
8567   if((shCnt=SPEC_BSTR(etype))
8568       || SPEC_BLEN(etype) <= 8 )  {
8569     int fsr0_setup = 0;
8570
8571     if (blen != 8 || (bstr % 8) != 0) {
8572       // we need to combine the value with the old value
8573       if(!shifted_and_masked)
8574       {
8575         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
8576
8577         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
8578             SPEC_BSTR(etype), SPEC_BLEN(etype));
8579
8580         /* shift left acc, do NOT mask the result again */
8581         AccLsh(shCnt, 0);
8582
8583         /* using PRODH as a temporary register here */
8584         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
8585       }
8586
8587       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
8588         || IS_DIRECT(result)) {
8589         /* access symbol directly */
8590         pic16_mov2w (AOP(result), 0);
8591       } else {
8592         /* get old value */
8593         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
8594       }
8595 #if 1
8596       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8597             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
8598                             (unsigned char)(0xff >> (8-bstr))) ));
8599       if (!shifted_and_masked) {
8600         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8601       } else {
8602         /* We have the shifted and masked (literal) right value in `lit' */
8603         if (lit != 0)
8604           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
8605       }
8606     } else { // if (blen == 8 && (bstr % 8) == 0)
8607         if (shifted_and_masked) {
8608             // move right (literal) to WREG (only case where right is not yet in WREG)
8609             pic16_mov2w(AOP(right), (bstr / 8));
8610         }
8611     }
8612
8613     /* write new value back */
8614     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
8615         || IS_DIRECT(result)) {
8616       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
8617     } else {
8618       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
8619     }
8620 #endif
8621
8622     return;
8623   }
8624
8625
8626 #if 0
8627   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8628   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8629   exit(EXIT_FAILURE);
8630 #endif
8631
8632
8633   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
8634   rLen = SPEC_BLEN(etype)-8;
8635
8636   /* now generate for lengths greater than one byte */
8637   while (1) {
8638     rLen -= 8 ;
8639     if (rLen <= 0 ) {
8640       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
8641       break ;
8642     }
8643
8644     switch (p_type) {
8645       case POINTER:
8646         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
8647         break;
8648
8649         /*
8650            case FPOINTER:
8651            MOVA(l);
8652            pic16_emitcode("movx","@dptr,a");
8653            break;
8654
8655            case GPOINTER:
8656            MOVA(l);
8657            DEBUGpic16_emitcode(";lcall","__gptrput");
8658            break;
8659          */
8660       default:
8661         assert(0);
8662     }
8663
8664
8665     pic16_mov2w(AOP(right), offset++);
8666   }
8667
8668   /* last last was not complete */
8669   if (rLen)   {
8670     /* save the byte & read byte */
8671     switch (p_type) {
8672       case POINTER:
8673         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
8674         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8675         break;
8676
8677         /*
8678            case FPOINTER:
8679            pic16_emitcode ("mov","b,a");
8680            pic16_emitcode("movx","a,@dptr");
8681            break;
8682
8683            case GPOINTER:
8684            pic16_emitcode ("push","b");
8685            pic16_emitcode ("push","acc");
8686            pic16_emitcode ("lcall","__gptrget");
8687            pic16_emitcode ("pop","b");
8688            break;
8689          */
8690       default:
8691         assert(0);
8692     }
8693     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
8694     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
8695     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
8696     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8697     //        pic16_emitcode ("orl","a,b");
8698   }
8699
8700   //    if (p_type == GPOINTER)
8701   //        pic16_emitcode("pop","b");
8702
8703   switch (p_type) {
8704
8705     case POINTER:
8706       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
8707       //        pic16_emitcode("mov","@%s,a",rname);
8708       break;
8709       /*
8710          case FPOINTER:
8711          pic16_emitcode("movx","@dptr,a");
8712          break;
8713
8714          case GPOINTER:
8715          DEBUGpic16_emitcode(";lcall","__gptrput");
8716          break;
8717        */
8718     default:
8719       assert(0);
8720   }
8721
8722   //    pic16_freeAsmop(right, NULL, ic, TRUE);
8723 }
8724
8725 /*-----------------------------------------------------------------*/
8726 /* genDataPointerSet - remat pointer to data space                 */
8727 /*-----------------------------------------------------------------*/
8728 static void genDataPointerSet(operand *right,
8729                               operand *result,
8730                               iCode *ic)
8731 {
8732   int size, offset = 0, resoffset=0 ;
8733
8734     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8735     pic16_aopOp(right,ic,FALSE);
8736
8737     size = AOP_SIZE(right);
8738
8739 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
8740
8741 #if 0
8742     if ( AOP_TYPE(result) == AOP_PCODE) {
8743       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8744               AOP(result)->aopu.pcop->name,
8745                 (AOP(result)->aopu.pcop->type == PO_DIR)?
8746               PCOR(AOP(result)->aopu.pcop)->instance:
8747               PCOI(AOP(result)->aopu.pcop)->offset);
8748     }
8749 #endif
8750
8751     if(AOP(result)->aopu.pcop->type == PO_DIR)
8752       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
8753
8754     while (size--) {
8755       if (AOP_TYPE(right) == AOP_LIT) {
8756         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
8757         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
8758       } else {
8759         pic16_mov2w(AOP(right), offset);
8760         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
8761       }
8762       offset++;
8763       resoffset++;
8764     }
8765
8766     pic16_freeAsmop(right,NULL,ic,TRUE);
8767 }
8768
8769
8770
8771 /*-----------------------------------------------------------------*/
8772 /* genNearPointerSet - pic16_emitcode for near pointer put         */
8773 /*-----------------------------------------------------------------*/
8774 static void genNearPointerSet (operand *right,
8775                                operand *result,
8776                                iCode *ic)
8777 {
8778   asmop *aop = NULL;
8779   sym_link *retype;
8780   sym_link *ptype = operandType(result);
8781   sym_link *resetype;
8782
8783     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8784     retype= getSpec(operandType(right));
8785     resetype = getSpec(operandType(result));
8786
8787     pic16_aopOp(result,ic,FALSE);
8788
8789     /* if the result is rematerializable &
8790      * in data space & not a bit variable */
8791
8792     /* and result is not a bit variable */
8793     if (AOP_TYPE(result) == AOP_PCODE
8794       && DCL_TYPE(ptype) == POINTER
8795       && !IS_BITFIELD(retype)
8796       && !IS_BITFIELD(resetype)) {
8797
8798         genDataPointerSet (right,result,ic);
8799         pic16_freeAsmop(result,NULL,ic,TRUE);
8800       return;
8801     }
8802
8803     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8804     pic16_aopOp(right,ic,FALSE);
8805     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8806
8807     /* if bitfield then unpack the bits */
8808     if (IS_BITFIELD(resetype)) {
8809       genPackBits (resetype, result, right, NULL, POINTER);
8810     } else {
8811       /* we have can just get the values */
8812       int size = AOP_SIZE(right);
8813       int offset = 0 ;
8814
8815         pic16_loadFSR0(result, 0);
8816
8817         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8818         while (size--) {
8819           if (pic16_isLitOp(right)) {
8820             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
8821             if (size) {
8822               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
8823             } else {
8824               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
8825             }
8826           } else { // no literal
8827             if(size) {
8828               pic16_emitpcode(POC_MOVFF,
8829                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
8830                   pic16_popCopyReg(&pic16_pc_postinc0)));
8831             } else {
8832               pic16_emitpcode(POC_MOVFF,
8833                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
8834                   pic16_popCopyReg(&pic16_pc_indf0)));
8835             }
8836           }
8837
8838           offset++;
8839         }
8840     }
8841
8842     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8843     /* now some housekeeping stuff */
8844     if (aop) {
8845       /* we had to allocate for this iCode */
8846       pic16_freeAsmop(NULL,aop,ic,TRUE);
8847     } else {
8848       /* we did not allocate which means left
8849        * already in a pointer register, then
8850        * if size > 0 && this could be used again
8851        * we have to point it back to where it
8852        * belongs */
8853       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8854       if (AOP_SIZE(right) > 1
8855         && !OP_SYMBOL(result)->remat
8856         && ( OP_SYMBOL(result)->liveTo > ic->seq
8857         || ic->depth )) {
8858
8859           int size = AOP_SIZE(right) - 1;
8860
8861             while (size--)
8862               pic16_emitcode("decf","fsr0,f");
8863               //pic16_emitcode("dec","%s",rname);
8864       }
8865     }
8866
8867     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8868     /* done */
8869 //release:
8870     pic16_freeAsmop(right,NULL,ic,TRUE);
8871     pic16_freeAsmop(result,NULL,ic,TRUE);
8872 }
8873
8874 /*-----------------------------------------------------------------*/
8875 /* genGenPointerSet - set value from generic pointer space         */
8876 /*-----------------------------------------------------------------*/
8877 static void genGenPointerSet (operand *right,
8878                               operand *result, iCode *ic)
8879 {
8880   int size;
8881   sym_link *retype = getSpec(operandType(result));
8882
8883     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8884
8885     pic16_aopOp(result,ic,FALSE);
8886     pic16_aopOp(right,ic,FALSE);
8887     size = AOP_SIZE(right);
8888
8889     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
8890
8891
8892     /* if bit then unpack */
8893     if (IS_BITFIELD(retype)) {
8894 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8895       genPackBits(retype,result,right,"dptr",GPOINTER);
8896       goto release;
8897     }
8898
8899     size = AOP_SIZE(right);
8900
8901     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
8902
8903
8904     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
8905
8906     /* value of right+0 is placed on stack, which will be retrieved
8907      * by the support function thus restoring the stack. The important
8908      * thing is that there is no need to manually restore stack pointer
8909      * here */
8910     pushaop(AOP(right), 0);
8911 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
8912     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
8913     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
8914     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
8915
8916     /* load address to write to in WREG:FSR0H:FSR0L */
8917     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
8918                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
8919     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
8920                                 pic16_popCopyReg(&pic16_pc_prodl)));
8921     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
8922
8923     pic16_callGenericPointerRW(1, size);
8924
8925 release:
8926     pic16_freeAsmop(right,NULL,ic,TRUE);
8927     pic16_freeAsmop(result,NULL,ic,TRUE);
8928 }
8929
8930 /*-----------------------------------------------------------------*/
8931 /* genPointerSet - stores the value into a pointer location        */
8932 /*-----------------------------------------------------------------*/
8933 static void genPointerSet (iCode *ic)
8934 {
8935   operand *right, *result ;
8936   sym_link *type, *etype;
8937   int p_type;
8938
8939     FENTRY;
8940
8941     right = IC_RIGHT(ic);
8942     result = IC_RESULT(ic) ;
8943
8944     /* depending on the type of pointer we need to
8945     move it to the correct pointer register */
8946     type = operandType(result);
8947     etype = getSpec(type);
8948
8949     /* if left is of type of pointer then it is simple */
8950     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8951         p_type = DCL_TYPE(type);
8952     }
8953     else {
8954         /* we have to go by the storage class */
8955         p_type = PTR_TYPE(SPEC_OCLS(etype));
8956
8957 /*      if (SPEC_OCLS(etype)->codesp ) { */
8958 /*          p_type = CPOINTER ;  */
8959 /*      } */
8960 /*      else */
8961 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8962 /*              p_type = FPOINTER ; */
8963 /*          else */
8964 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8965 /*                  p_type = PPOINTER ; */
8966 /*              else */
8967 /*                  if (SPEC_OCLS(etype) == idata ) */
8968 /*                      p_type = IPOINTER ; */
8969 /*                  else */
8970 /*                      p_type = POINTER ; */
8971     }
8972
8973     /* now that we have the pointer type we assign
8974     the pointer values */
8975     switch (p_type) {
8976       case POINTER:
8977       case FPOINTER:
8978       case IPOINTER:
8979       case PPOINTER:
8980         genNearPointerSet (right,result,ic);
8981         break;
8982
8983       case GPOINTER:
8984         genGenPointerSet (right,result,ic);
8985         break;
8986
8987       default:
8988         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8989           "genPointerSet: illegal pointer type");
8990     }
8991 }
8992
8993 /*-----------------------------------------------------------------*/
8994 /* genIfx - generate code for Ifx statement                        */
8995 /*-----------------------------------------------------------------*/
8996 static void genIfx (iCode *ic, iCode *popIc)
8997 {
8998   operand *cond = IC_COND(ic);
8999   int isbit =0;
9000
9001     FENTRY;
9002
9003     pic16_aopOp(cond,ic,FALSE);
9004
9005     /* get the value into acc */
9006     if (AOP_TYPE(cond) != AOP_CRY)
9007       pic16_toBoolean(cond);
9008     else
9009       isbit = 1;
9010     /* the result is now in the accumulator */
9011     pic16_freeAsmop(cond,NULL,ic,TRUE);
9012
9013     /* if there was something to be popped then do it */
9014     if (popIc)
9015       genIpop(popIc);
9016
9017     /* if the condition is  a bit variable */
9018     if (isbit && IS_ITEMP(cond) &&
9019         SPIL_LOC(cond)) {
9020       genIfxJump(ic,"c");
9021       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9022     } else {
9023       if (isbit && !IS_ITEMP(cond))
9024         genIfxJump(ic,OP_SYMBOL(cond)->rname);
9025         else
9026         genIfxJump(ic,"a");
9027     }
9028     ic->generated = 1;
9029 }
9030
9031 /*-----------------------------------------------------------------*/
9032 /* genAddrOf - generates code for address of                       */
9033 /*-----------------------------------------------------------------*/
9034 static void genAddrOf (iCode *ic)
9035 {
9036   operand *result, *left;
9037   int size;
9038   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9039   pCodeOp *pcop0, *pcop1, *pcop2;
9040
9041     FENTRY;
9042
9043     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9044
9045     sym = OP_SYMBOL( IC_LEFT(ic) );
9046
9047     if(sym->onStack) {
9048       /* get address of symbol on stack */
9049       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
9050 #if 0
9051       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
9052                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
9053 #endif
9054
9055       // operands on stack are accessible via "FSR2 + index" with index
9056       // starting at 2 for arguments and growing from 0 downwards for
9057       // local variables (index == 0 is not assigned so we add one here)
9058       {
9059         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
9060
9061           if (soffs <= 0) {
9062             assert (soffs < 0);
9063             soffs++;
9064           } // if
9065
9066           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
9067           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
9068           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
9069           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
9070           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
9071           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
9072           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
9073       }
9074
9075       goto release;
9076     }
9077
9078 //      if(pic16_debug_verbose) {
9079 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9080 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9081 //      }
9082
9083     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9084     size = AOP_SIZE(IC_RESULT(ic));
9085
9086     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9087     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9088     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9089
9090     if (size == 3) {
9091       pic16_emitpcode(POC_MOVLW, pcop0);
9092       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9093       pic16_emitpcode(POC_MOVLW, pcop1);
9094       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9095       pic16_emitpcode(POC_MOVLW, pcop2);
9096       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9097     } else
9098     if (size == 2) {
9099       pic16_emitpcode(POC_MOVLW, pcop0);
9100       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9101       pic16_emitpcode(POC_MOVLW, pcop1);
9102     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9103     } else {
9104       pic16_emitpcode(POC_MOVLW, pcop0);
9105       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9106     }
9107
9108     pic16_freeAsmop(left, NULL, ic, FALSE);
9109 release:
9110     pic16_freeAsmop(result,NULL,ic,TRUE);
9111 }
9112
9113
9114 /*-----------------------------------------------------------------*/
9115 /* genAssign - generate code for assignment                        */
9116 /*-----------------------------------------------------------------*/
9117 static void genAssign (iCode *ic)
9118 {
9119   operand *result, *right;
9120   sym_link *restype, *rtype;
9121   int size, offset,know_W;
9122   unsigned long lit = 0L;
9123
9124     result = IC_RESULT(ic);
9125     right  = IC_RIGHT(ic) ;
9126
9127     FENTRY;
9128
9129     /* if they are the same */
9130     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9131       return ;
9132
9133     /* reversed order operands are aopOp'ed so that result operand
9134      * is effective in case right is a stack symbol. This maneauver
9135      * allows to use the _G.resDirect flag later */
9136      pic16_aopOp(result,ic,TRUE);
9137     pic16_aopOp(right,ic,FALSE);
9138
9139     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9140
9141     /* if they are the same registers */
9142     if (pic16_sameRegs(AOP(right),AOP(result)))
9143       goto release;
9144
9145     /* if the result is a bit */
9146     if (AOP_TYPE(result) == AOP_CRY) {
9147       /* if the right size is a literal then
9148          we know what the value is */
9149       if (AOP_TYPE(right) == AOP_LIT) {
9150
9151         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9152             pic16_popGet(AOP(result),0));
9153
9154         if (((int) operandLitValue(right)))
9155           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9156               AOP(result)->aopu.aop_dir,
9157               AOP(result)->aopu.aop_dir);
9158         else
9159           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9160               AOP(result)->aopu.aop_dir,
9161               AOP(result)->aopu.aop_dir);
9162
9163         goto release;
9164       }
9165
9166       /* the right is also a bit variable */
9167       if (AOP_TYPE(right) == AOP_CRY) {
9168         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9169         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9170         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9171
9172         goto release ;
9173       }
9174
9175       /* we need to or */
9176       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9177       pic16_toBoolean(right);
9178       emitSKPZ;
9179       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9180       //pic16_aopPut(AOP(result),"a",0);
9181       goto release ;
9182     }
9183
9184     /* bit variables done */
9185     /* general case */
9186     size = AOP_SIZE(result);
9187     offset = 0 ;
9188
9189   /* bit variables done */
9190   /* general case */
9191   size = AOP_SIZE(result);
9192   restype = operandType(result);
9193   rtype = operandType(right);
9194   offset = 0 ;
9195
9196   if(AOP_TYPE(right) == AOP_LIT) {
9197     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
9198     {
9199       lit = ulFromVal (AOP(right)->aopu.aop_lit);
9200
9201       /* patch tag for literals that are cast to pointers */
9202       if (IS_CODEPTR(restype)) {
9203         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
9204         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9205       } else {
9206         if (IS_GENPTR(restype))
9207         {
9208           if (IS_CODEPTR(rtype)) {
9209             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
9210             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
9211           } else if (PIC_IS_DATA_PTR(rtype)) {
9212             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
9213             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9214           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
9215             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
9216           } else if (IS_PTR(rtype)) {
9217             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
9218             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
9219           }
9220         }
9221       }
9222     } else {
9223       union {
9224         unsigned long lit_int;
9225         float lit_float;
9226       } info;
9227
9228
9229       if(IS_FIXED16X16(operandType(right))) {
9230         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
9231       } else {
9232         /* take care if literal is a float */
9233         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
9234         lit = info.lit_int;
9235       }
9236     }
9237   }
9238
9239 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
9240 //                      sizeof(unsigned long int), sizeof(float));
9241
9242
9243     if (AOP_TYPE(right) == AOP_REG) {
9244       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
9245       while (size--) {
9246         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
9247       } // while
9248       goto release;
9249     }
9250
9251     /* when do we have to read the program memory?
9252      * - if right itself is a symbol in code space
9253      *   (we don't care what it points to if it's a pointer)
9254      * - AND right is not a function (we would want its address)
9255      */
9256     if(AOP_TYPE(right) != AOP_LIT
9257       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
9258       && !IS_FUNC(OP_SYM_TYPE(right))
9259       && !IS_ITEMP(right)) {
9260
9261       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
9262       //fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
9263
9264       // set up table pointer
9265       if(pic16_isLitOp(right)) {
9266 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
9267         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
9268         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9269         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
9270         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9271         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
9272         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9273       } else {
9274 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
9275         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
9276             pic16_popCopyReg(&pic16_pc_tblptrl)));
9277         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
9278             pic16_popCopyReg(&pic16_pc_tblptrh)));
9279         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
9280             pic16_popCopyReg(&pic16_pc_tblptru)));
9281       }
9282
9283       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
9284       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
9285       while(size--) {
9286         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9287         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
9288             pic16_popGet(AOP(result),offset)));
9289         offset++;
9290       }
9291
9292       /* FIXME: for pointers we need to extend differently (according
9293        * to pointer type DATA/CODE/EEPROM/... :*/
9294       size = getSize(OP_SYM_TYPE(right));
9295       if(AOP_SIZE(result) > size) {
9296         size = AOP_SIZE(result) - size;
9297         while(size--) {
9298           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
9299           offset++;
9300         }
9301       }
9302       goto release;
9303     }
9304
9305 #if 0
9306     /* VR - What is this?! */
9307     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9308       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9309
9310       if(aopIdx(AOP(result),0) == 4) {
9311         /* this is a workaround to save value of right into wreg too,
9312          * value of wreg is going to be used later */
9313         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9314         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9315         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9316         goto release;
9317       } else
9318 //      assert(0);
9319       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9320     }
9321 #endif
9322
9323     size = AOP_SIZE(right);
9324     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
9325     know_W=-1;
9326     while (size--) {
9327       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
9328       if(AOP_TYPE(right) == AOP_LIT) {
9329         if(lit&0xff) {
9330           if(know_W != (lit&0xff))
9331             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9332           know_W = lit&0xff;
9333           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9334         } else
9335           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9336
9337         lit >>= 8;
9338
9339       } else if (AOP_TYPE(right) == AOP_CRY) {
9340         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9341         if(offset == 0) {
9342           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
9343           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
9344           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9345         }
9346       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
9347         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9348         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9349       } else {
9350         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9351
9352         if(!_G.resDirect) {                                             /* use this aopForSym feature */
9353           if(AOP_TYPE(result) == AOP_ACC) {
9354             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
9355           } else
9356             if(AOP_TYPE(right) == AOP_ACC) {
9357               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9358             } else {
9359               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9360             }
9361         }
9362       }
9363
9364       offset++;
9365     }
9366     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
9367
9368 release:
9369   pic16_freeAsmop (result,NULL,ic,TRUE);
9370   pic16_freeAsmop (right,NULL,ic,FALSE);
9371 }
9372
9373 /*-----------------------------------------------------------------*/
9374 /* genJumpTab - generates code for jump table                       */
9375 /*-----------------------------------------------------------------*/
9376 static void genJumpTab (iCode *ic)
9377 {
9378   symbol *jtab;
9379   char *l;
9380   pCodeOp *jt_offs;
9381   pCodeOp *jt_offs_hi;
9382   pCodeOp *jt_label;
9383
9384     FENTRY;
9385
9386     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9387     /* get the condition into accumulator */
9388     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9389     MOVA(l);
9390     /* multiply by three */
9391     pic16_emitcode("add","a,acc");
9392     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9393
9394     jtab = newiTempLabel(NULL);
9395     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9396     pic16_emitcode("jmp","@a+dptr");
9397     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9398
9399 #if 0
9400     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9401     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9402     emitSKPNC;
9403     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9404     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9405     pic16_emitpLabel(jtab->key);
9406
9407 #else
9408
9409     jt_offs = pic16_popGetTempReg(0);
9410     jt_offs_hi = pic16_popGetTempReg(1);
9411     jt_label = pic16_popGetLabel (jtab->key);
9412     //fprintf (stderr, "Creating jump table...\n");
9413
9414     // calculate offset into jump table (idx * sizeof (GOTO))
9415     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
9416     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
9417     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
9418     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
9419     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
9420     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
9421     pic16_emitpcode(POC_MOVWF , jt_offs);
9422
9423     // prepare PCLATx (set to first entry in jump table)
9424     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
9425     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
9426     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
9427     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
9428     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
9429
9430     // set PCLATx to selected entry (new PCL is stored in jt_offs)
9431     pic16_emitpcode(POC_ADDWF , jt_offs);
9432     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
9433     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
9434     emitSKPNC;
9435     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
9436
9437     // release temporaries and prepare jump into table (new PCL --> WREG)
9438     pic16_emitpcode(POC_MOVFW , jt_offs);
9439     pic16_popReleaseTempReg (jt_offs_hi, 1);
9440     pic16_popReleaseTempReg (jt_offs, 0);
9441
9442     // jump into the table
9443     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
9444
9445     pic16_emitpLabelFORCE(jtab->key);
9446 #endif
9447
9448     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9449 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
9450
9451     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
9452     /* now generate the jump labels */
9453     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9454          jtab = setNextItem(IC_JTLABELS(ic))) {
9455 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9456         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9457
9458     }
9459     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
9460
9461 }
9462
9463 /*-----------------------------------------------------------------*/
9464 /* genMixedOperation - gen code for operators between mixed types  */
9465 /*-----------------------------------------------------------------*/
9466 /*
9467   TSD - Written for the PIC port - but this unfortunately is buggy.
9468   This routine is good in that it is able to efficiently promote
9469   types to different (larger) sizes. Unfortunately, the temporary
9470   variables that are optimized out by this routine are sometimes
9471   used in other places. So until I know how to really parse the
9472   iCode tree, I'm going to not be using this routine :(.
9473 */
9474 static int genMixedOperation (iCode *ic)
9475 {
9476 #if 0
9477   operand *result = IC_RESULT(ic);
9478   sym_link *ctype = operandType(IC_LEFT(ic));
9479   operand *right = IC_RIGHT(ic);
9480   int ret = 0;
9481   int big,small;
9482   int offset;
9483
9484   iCode *nextic;
9485   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9486
9487   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9488
9489   nextic = ic->next;
9490   if(!nextic)
9491     return 0;
9492
9493   nextright = IC_RIGHT(nextic);
9494   nextleft  = IC_LEFT(nextic);
9495   nextresult = IC_RESULT(nextic);
9496
9497   pic16_aopOp(right,ic,FALSE);
9498   pic16_aopOp(result,ic,FALSE);
9499   pic16_aopOp(nextright,  nextic, FALSE);
9500   pic16_aopOp(nextleft,   nextic, FALSE);
9501   pic16_aopOp(nextresult, nextic, FALSE);
9502
9503   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9504
9505     operand *t = right;
9506     right = nextright;
9507     nextright = t;
9508
9509     pic16_emitcode(";remove right +","");
9510
9511   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9512 /*
9513     operand *t = right;
9514     right = nextleft;
9515     nextleft = t;
9516 */
9517     pic16_emitcode(";remove left +","");
9518   } else
9519     return 0;
9520
9521   big = AOP_SIZE(nextleft);
9522   small = AOP_SIZE(nextright);
9523
9524   switch(nextic->op) {
9525
9526   case '+':
9527     pic16_emitcode(";optimize a +","");
9528     /* if unsigned or not an integral type */
9529     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9530       pic16_emitcode(";add a bit to something","");
9531     } else {
9532
9533       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9534
9535       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9536         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9537         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9538       } else
9539         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9540
9541       offset = 0;
9542       while(--big) {
9543
9544         offset++;
9545
9546         if(--small) {
9547           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9548             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9549             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9550           }
9551
9552           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9553           emitSKPNC;
9554           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9555                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9556                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9557           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9558           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9559
9560         } else {
9561           pic16_emitcode("rlf","known_zero,w");
9562
9563           /*
9564             if right is signed
9565               btfsc  right,7
9566                addlw ff
9567           */
9568           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9569             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9570             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9571           } else {
9572             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9573           }
9574         }
9575       }
9576       ret = 1;
9577     }
9578   }
9579   ret = 1;
9580
9581 release:
9582   pic16_freeAsmop(right,NULL,ic,TRUE);
9583   pic16_freeAsmop(result,NULL,ic,TRUE);
9584   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9585   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9586   if(ret)
9587     nextic->generated = 1;
9588
9589   return ret;
9590 #else
9591   return 0;
9592 #endif
9593 }
9594 /*-----------------------------------------------------------------*/
9595 /* genCast - gen code for casting                                  */
9596 /*-----------------------------------------------------------------*/
9597 static void genCast (iCode *ic)
9598 {
9599   operand *result = IC_RESULT(ic);
9600   sym_link *ctype = operandType(IC_LEFT(ic));
9601   sym_link *rtype = operandType(IC_RIGHT(ic));
9602   sym_link *restype = operandType(IC_RESULT(ic));
9603   operand *right = IC_RIGHT(ic);
9604   int size, offset ;
9605
9606
9607     FENTRY;
9608
9609         /* if they are equivalent then do nothing */
9610 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9611 //              return ;
9612
9613         pic16_aopOp(result,ic,FALSE);
9614         pic16_aopOp(right,ic,FALSE) ;
9615
9616         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9617
9618
9619         /* if the result is a bit */
9620         if (AOP_TYPE(result) == AOP_CRY) {
9621
9622                 /* if the right size is a literal then
9623                  * we know what the value is */
9624                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9625
9626                 if (AOP_TYPE(right) == AOP_LIT) {
9627                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9628                                 pic16_popGet(AOP(result),0));
9629
9630                         if (((int) operandLitValue(right)))
9631                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9632                                         AOP(result)->aopu.aop_dir,
9633                                         AOP(result)->aopu.aop_dir);
9634                         else
9635                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9636                                         AOP(result)->aopu.aop_dir,
9637                                         AOP(result)->aopu.aop_dir);
9638                         goto release;
9639                 }
9640
9641                 /* the right is also a bit variable */
9642                 if (AOP_TYPE(right) == AOP_CRY) {
9643                         emitCLRC;
9644                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9645
9646                         pic16_emitcode("clrc","");
9647                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9648                                 AOP(right)->aopu.aop_dir,
9649                                 AOP(right)->aopu.aop_dir);
9650                         pic16_aopPut(AOP(result),"c",0);
9651                         goto release ;
9652                 }
9653
9654                 /* we need to or */
9655                 if (AOP_TYPE(right) == AOP_REG) {
9656                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9657                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9658                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9659                 }
9660                 pic16_toBoolean(right);
9661                 pic16_aopPut(AOP(result),"a",0);
9662                 goto release ;
9663         }
9664
9665         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9666           int offset = 1;
9667
9668                 size = AOP_SIZE(result);
9669
9670                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9671
9672                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
9673                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9674                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
9675
9676                 while (size--)
9677                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9678
9679                 goto release;
9680         }
9681
9682         if(IS_BITFIELD(getSpec(restype))
9683           && IS_BITFIELD(getSpec(rtype))) {
9684           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
9685         }
9686
9687         /* port from pic14 to cope with generic pointers */
9688         if (PIC_IS_TAGGED(restype))
9689         {
9690           operand *result = IC_RESULT(ic);
9691           //operand *left = IC_LEFT(ic);
9692           operand *right = IC_RIGHT(ic);
9693           int tag = 0xff;
9694
9695           /* copy common part */
9696           int max, size = AOP_SIZE(result);
9697           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
9698           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9699
9700           max = size;
9701           while (size--)
9702           {
9703             pic16_mov2w (AOP(right), size);
9704             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
9705           } // while
9706
9707           /* upcast into generic pointer type? */
9708           if (IS_GENPTR(restype)
9709               && !PIC_IS_TAGGED(rtype)
9710               && (AOP_SIZE(result) > max))
9711           {
9712             /* determine appropriate tag for right */
9713             if (PIC_IS_DATA_PTR(rtype))
9714               tag = GPTR_TAG_DATA;
9715             else if (IS_CODEPTR(rtype))
9716               tag = GPTR_TAG_CODE;
9717             else if (PIC_IS_DATA_PTR(ctype)) {
9718               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
9719               tag = GPTR_TAG_DATA;
9720             } else if (IS_CODEPTR(ctype)) {
9721               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
9722               tag = GPTR_TAG_CODE;
9723             } else if (IS_PTR(rtype)) {
9724               PERFORM_ONCE(weirdcast,
9725               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
9726               );
9727               tag = GPTR_TAG_DATA;
9728             } else {
9729               PERFORM_ONCE(weirdcast,
9730               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
9731               );
9732               tag = GPTR_TAG_DATA;
9733             }
9734
9735             assert (AOP_SIZE(result) == 3);
9736             /* zero-extend address... */
9737             for (size = max; size < AOP_SIZE(result)-1; size++)
9738               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
9739             /* ...and add tag */
9740             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
9741           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
9742             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
9743             for (size = max; size < AOP_SIZE(result)-1; size++)
9744               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
9745             /* add __code tag */
9746             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
9747           } else if (AOP_SIZE(result) > max) {
9748             /* extend non-pointers */
9749             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
9750             pic16_addSign(result, max, 0);
9751           } // if
9752           goto release;
9753         }
9754
9755         /* if they are the same size : or less */
9756         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9757
9758                 /* if they are in the same place */
9759                 if (pic16_sameRegs(AOP(right),AOP(result)))
9760                         goto release;
9761
9762                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9763 #if 0
9764                 if (IS_PTR_CONST(rtype))
9765 #else
9766                 if (IS_CODEPTR(rtype))
9767 #endif
9768                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
9769
9770 #if 0
9771                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9772 #else
9773                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9774 #endif
9775                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
9776
9777                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9778                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
9779                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9780
9781                         if(AOP_SIZE(result) < 2) {
9782                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
9783                         } else {
9784                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
9785                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9786                         }
9787                 } else {
9788                         /* if they in different places then copy */
9789                         size = AOP_SIZE(result);
9790                         offset = 0 ;
9791                         while (size--) {
9792                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9793                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9794                                 offset++;
9795                         }
9796                 }
9797                 goto release;
9798         }
9799
9800         /* if the result is of type pointer */
9801         if (IS_PTR(ctype)) {
9802           int p_type;
9803           sym_link *type = operandType(right);
9804           sym_link *etype = getSpec(type);
9805
9806                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9807
9808                 /* pointer to generic pointer */
9809                 if (IS_GENPTR(ctype)) {
9810
9811                         if (IS_PTR(type))
9812                                 p_type = DCL_TYPE(type);
9813                         else {
9814                 /* we have to go by the storage class */
9815                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9816
9817 /*              if (SPEC_OCLS(etype)->codesp )  */
9818 /*                  p_type = CPOINTER ;  */
9819 /*              else */
9820 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9821 /*                      p_type = FPOINTER ; */
9822 /*                  else */
9823 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9824 /*                          p_type = PPOINTER; */
9825 /*                      else */
9826 /*                          if (SPEC_OCLS(etype) == idata ) */
9827 /*                              p_type = IPOINTER ; */
9828 /*                          else */
9829 /*                              p_type = POINTER ; */
9830             }
9831
9832             /* the first two bytes are known */
9833       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9834             size = GPTRSIZE - 1;
9835             offset = 0 ;
9836             while (size--) {
9837               if(offset < AOP_SIZE(right)) {
9838                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
9839                 pic16_mov2f(AOP(result), AOP(right), offset);
9840 /*
9841                 if ((AOP_TYPE(right) == AOP_PCODE) &&
9842                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9843                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9844                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9845                 } else {
9846
9847                   pic16_aopPut(AOP(result),
9848                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9849                          offset);
9850                 }
9851 */
9852               } else
9853                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
9854               offset++;
9855             }
9856             /* the last byte depending on type */
9857             switch (p_type) {
9858             case POINTER:
9859             case FPOINTER:
9860             case IPOINTER:
9861             case PPOINTER:
9862                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9863                 break;
9864
9865             case CPOINTER:
9866                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9867                 break;
9868
9869             case GPOINTER:
9870                 if (GPTRSIZE > AOP_SIZE(right)) {
9871                   // assume __data pointer... THIS MIGHT BE WRONG!
9872                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
9873                 } else {
9874                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
9875                 }
9876               break;
9877
9878             default:
9879                 /* this should never happen */
9880                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9881                        "got unknown pointer type");
9882                 exit(1);
9883             }
9884             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);
9885             goto release ;
9886         }
9887
9888
9889         assert( 0 );
9890         /* just copy the pointers */
9891         size = AOP_SIZE(result);
9892         offset = 0 ;
9893         while (size--) {
9894             pic16_aopPut(AOP(result),
9895                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
9896                    offset);
9897             offset++;
9898         }
9899         goto release ;
9900     }
9901
9902
9903
9904     /* so we now know that the size of destination is greater
9905     than the size of the source.
9906     Now, if the next iCode is an operator then we might be
9907     able to optimize the operation without performing a cast.
9908     */
9909     if(genMixedOperation(ic))
9910       goto release;
9911
9912     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9913
9914     /* we move to result for the size of source */
9915     size = AOP_SIZE(right);
9916     offset = 0 ;
9917
9918     while (size--) {
9919       if(!_G.resDirect)
9920         pic16_mov2f(AOP(result), AOP(right), offset);
9921       offset++;
9922     }
9923
9924     /* now depending on the sign of the destination */
9925     size = AOP_SIZE(result) - AOP_SIZE(right);
9926     /* if unsigned or not an integral type */
9927     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
9928       while (size--)
9929         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
9930     } else {
9931       /* we need to extend the sign :( */
9932
9933       if(size == 1) {
9934         /* Save one instruction of casting char to int */
9935         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
9936         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9937         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
9938       } else {
9939         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
9940
9941         if(offset)
9942           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9943         else
9944           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9945
9946         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
9947
9948         while (size--)
9949           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
9950       }
9951     }
9952
9953 release:
9954     pic16_freeAsmop(right,NULL,ic,TRUE);
9955     pic16_freeAsmop(result,NULL,ic,TRUE);
9956
9957 }
9958
9959 /*-----------------------------------------------------------------*/
9960 /* genDjnz - generate decrement & jump if not zero instrucion      */
9961 /*-----------------------------------------------------------------*/
9962 static int genDjnz (iCode *ic, iCode *ifx)
9963 {
9964     symbol *lbl, *lbl1;
9965     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9966
9967     if (!ifx)
9968         return 0;
9969
9970     /* if the if condition has a false label
9971        then we cannot save */
9972     if (IC_FALSE(ifx))
9973         return 0;
9974
9975     /* if the minus is not of the form
9976        a = a - 1 */
9977     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9978         !IS_OP_LITERAL(IC_RIGHT(ic)))
9979         return 0;
9980
9981     if (operandLitValue(IC_RIGHT(ic)) != 1)
9982         return 0;
9983
9984     /* if the size of this greater than one then no
9985        saving */
9986     if (getSize(operandType(IC_RESULT(ic))) > 1)
9987         return 0;
9988
9989     /* otherwise we can save BIG */
9990     lbl = newiTempLabel(NULL);
9991     lbl1= newiTempLabel(NULL);
9992
9993     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9994
9995     pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
9996     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
9997
9998     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9999     ifx->generated = 1;
10000     return 1;
10001 }
10002
10003 /*-----------------------------------------------------------------*/
10004 /* genReceive - generate code for a receive iCode                  */
10005 /*-----------------------------------------------------------------*/
10006 static void genReceive (iCode *ic)
10007 {
10008
10009   FENTRY;
10010
10011 #if 0
10012   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
10013         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
10014 #endif
10015 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
10016
10017   if (isOperandInFarSpace(IC_RESULT(ic))
10018       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
10019           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10020
10021     int size = getSize(operandType(IC_RESULT(ic)));
10022     int offset =  pic16_fReturnSizePic - size;
10023
10024       assert( 0 );
10025       while (size--) {
10026         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10027                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10028                       offset++;
10029         }
10030
10031       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10032
10033       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10034       size = AOP_SIZE(IC_RESULT(ic));
10035       offset = 0;
10036       while (size--) {
10037         pic16_emitcode ("pop","acc");
10038         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10039       }
10040   } else {
10041     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
10042     _G.accInUse++;
10043     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10044     _G.accInUse--;
10045
10046     /* set pseudo stack pointer to where it should be - dw*/
10047     GpsuedoStkPtr = ic->parmBytes;
10048
10049     /* setting GpsuedoStkPtr has side effects here: */
10050     /* FIXME: What's the correct size of the return(ed) value?
10051      *        For now, assuming '4' as before... */
10052     assignResultValue(IC_RESULT(ic), 4, 0);
10053   }
10054
10055   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10056 }
10057
10058 /*-----------------------------------------------------------------*/
10059 /* genDummyRead - generate code for dummy read of volatiles        */
10060 /*-----------------------------------------------------------------*/
10061 static void
10062 genDummyRead (iCode * ic)
10063 {
10064   operand *op;
10065
10066   op = IC_RIGHT(ic);
10067   if (op && IS_SYMOP(op)) {
10068     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
10069       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
10070       return;
10071     }
10072     pic16_aopOp (op, ic, FALSE);
10073     pic16_mov2w_volatile(AOP(op));
10074     pic16_freeAsmop (op, NULL, ic, TRUE);
10075   } else if (op) {
10076     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
10077   } // if
10078 }
10079
10080 /*-----------------------------------------------------------------*/
10081 /* genpic16Code - generate code for pic16 based controllers        */
10082 /*-----------------------------------------------------------------*/
10083 /*
10084  * At this point, ralloc.c has gone through the iCode and attempted
10085  * to optimize in a way suitable for a PIC. Now we've got to generate
10086  * PIC instructions that correspond to the iCode.
10087  *
10088  * Once the instructions are generated, we'll pass through both the
10089  * peep hole optimizer and the pCode optimizer.
10090  *-----------------------------------------------------------------*/
10091
10092 void genpic16Code (iCode *lic)
10093 {
10094   iCode *ic;
10095   int cln = 0;
10096
10097     lineHead = lineCurr = NULL;
10098
10099     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10100     pic16_addpBlock(pb);
10101
10102 #if 0
10103     /* if debug information required */
10104     if (options.debug && currFunc) {
10105       if (currFunc) {
10106         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10107       }
10108     }
10109 #endif
10110
10111     for (ic = lic ; ic ; ic = ic->next ) {
10112
10113       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
10114       if ( cln != ic->lineno ) {
10115         if ( options.debug ) {
10116           debugFile->writeCLine (ic);
10117         }
10118
10119         if(!options.noCcodeInAsm) {
10120           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename,
10121               printCLine(ic->filename, ic->lineno)));
10122         }
10123
10124         cln = ic->lineno ;
10125       }
10126
10127       if(options.iCodeInAsm) {
10128         const char *iLine;
10129
10130         /* insert here code to print iCode as comment */
10131         iLine = printILine(ic);
10132         pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
10133         dbuf_free(iLine);
10134       }
10135
10136       /* if the result is marked as
10137        * spilt and rematerializable or code for
10138        * this has already been generated then
10139        * do nothing */
10140       if (resultRemat(ic) || ic->generated )
10141         continue ;
10142
10143       /* depending on the operation */
10144       switch (ic->op) {
10145         case '!' :
10146           pic16_genNot(ic);
10147           break;
10148
10149         case '~' :
10150           pic16_genCpl(ic);
10151           break;
10152
10153         case UNARYMINUS:
10154           genUminus (ic);
10155           break;
10156
10157         case IPUSH:
10158           genIpush (ic);
10159           break;
10160
10161         case IPOP:
10162           /* IPOP happens only when trying to restore a
10163            * spilt live range, if there is an ifx statement
10164            * following this pop then the if statement might
10165            * be using some of the registers being popped which
10166            * would destroy the contents of the register so
10167            * we need to check for this condition and handle it */
10168            if (ic->next
10169              && ic->next->op == IFX
10170              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
10171                genIfx (ic->next,ic);
10172           else
10173             genIpop (ic);
10174           break;
10175
10176         case CALL:
10177           genCall (ic);
10178           break;
10179
10180         case PCALL:
10181           genPcall (ic);
10182           break;
10183
10184         case FUNCTION:
10185           genFunction (ic);
10186           break;
10187
10188         case ENDFUNCTION:
10189           genEndFunction (ic);
10190           break;
10191
10192         case RETURN:
10193           genRet (ic);
10194           break;
10195
10196         case LABEL:
10197           genLabel (ic);
10198           break;
10199
10200         case GOTO:
10201           genGoto (ic);
10202           break;
10203
10204         case '+' :
10205           pic16_genPlus (ic) ;
10206           break;
10207
10208         case '-' :
10209           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10210             pic16_genMinus (ic);
10211           break;
10212
10213         case '*' :
10214           genMult (ic);
10215           break;
10216
10217         case '/' :
10218           genDiv (ic) ;
10219           break;
10220
10221         case '%' :
10222           genMod (ic);
10223           break;
10224
10225         case '>' :
10226           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
10227           break;
10228
10229         case '<' :
10230           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10231           break;
10232
10233         case LE_OP:
10234         case GE_OP:
10235         case NE_OP:
10236           /* note these two are xlated by algebraic equivalence
10237            * during parsing SDCC.y */
10238           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10239             "got '>=' or '<=' shouldn't have come here");
10240           break;
10241
10242         case EQ_OP:
10243           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10244           break;
10245
10246         case AND_OP:
10247           genAndOp (ic);
10248           break;
10249
10250         case OR_OP:
10251           genOrOp (ic);
10252           break;
10253
10254         case '^' :
10255           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10256           break;
10257
10258         case '|' :
10259           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10260           break;
10261
10262         case BITWISEAND:
10263           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10264           break;
10265
10266         case INLINEASM:
10267           genInline (ic);
10268           break;
10269
10270         case RRC:
10271           genRRC (ic);
10272           break;
10273
10274         case RLC:
10275           genRLC (ic);
10276           break;
10277
10278         case GETHBIT:
10279           genGetHbit (ic);
10280           break;
10281
10282         case LEFT_OP:
10283           genLeftShift (ic);
10284           break;
10285
10286         case RIGHT_OP:
10287           genRightShift (ic);
10288           break;
10289
10290         case GET_VALUE_AT_ADDRESS:
10291           genPointerGet(ic);
10292           break;
10293
10294         case '=' :
10295           if (POINTER_SET(ic))
10296             genPointerSet(ic);
10297           else
10298             genAssign(ic);
10299           break;
10300
10301         case IFX:
10302           genIfx (ic,NULL);
10303           break;
10304
10305         case ADDRESS_OF:
10306           genAddrOf (ic);
10307           break;
10308
10309         case JUMPTABLE:
10310           genJumpTab (ic);
10311           break;
10312
10313         case CAST:
10314           genCast (ic);
10315           break;
10316
10317         case RECEIVE:
10318           genReceive(ic);
10319           break;
10320
10321         case SEND:
10322           addSet(&_G.sendSet,ic);
10323           break;
10324
10325         case DUMMY_READ_VOLATILE:
10326           genDummyRead (ic);
10327           break;
10328
10329         default :
10330           ic = ic;
10331       }
10332     }
10333
10334
10335     /* now we are ready to call the
10336        peep hole optimizer */
10337     if (!options.nopeep)
10338       peepHole (&lineHead);
10339
10340     /* now do the actual printing */
10341     printLine (lineHead, codeOutBuf);
10342
10343 #ifdef PCODE_DEBUG
10344     DFPRINTF((stderr,"printing pBlock\n\n"));
10345     pic16_printpBlock(stdout,pb);
10346 #endif
10347
10348     return;
10349 }