49dbd23523e7531fc4b57b26b0bbce1cbfdf5e87
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas vrokas@otenet.gr (2003,2004)
10   
11   This program is free software; you can redistribute it and/or modify it
12   under the terms of the GNU General Public License as published by the
13   Free Software Foundation; either version 2, or (at your option) any
14   later version.
15   
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20   
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24   
25   In other words, you are welcome to use, share and improve this program.
26   You are forbidden to forbid anyone else to use, share and improve
27   what you give them.   Help stamp out software-hoarding!
28   
29   Notes:
30   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
31                 Made everything static
32 -------------------------------------------------------------------------*/
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.h"
46 #include "genutils.h"
47 #include "device.h"
48 #include "main.h"
49
50 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
52 void pic16_genMult8X8_8 (operand *, operand *,operand *);
53 void pic16_genMult16X16_16(operand *, operand *, operand *);
54 void pic16_genMult32X32_32(operand *, operand *, operand *);
55 pCode *pic16_AssembleLine(char *line, int peeps);
56 extern void pic16_printpBlock(FILE *of, pBlock *pb);
57 static asmop *newAsmop (short type);
58 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
59 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
60 static void mov2w (asmop *aop, int offset);
61 static int aopIdx (asmop *aop, int offset);
62
63 int pic16_labelOffset=0;
64 extern int pic16_debug_verbose;
65 static int optimized_for_speed = 0;
66 /*
67   hack hack
68
69 */
70
71 /* max_key keeps track of the largest label number used in 
72    a function. This is then used to adjust the label offset
73    for the next function.
74 */
75 static int max_key=0;
76 static int GpsuedoStkPtr=0;
77
78 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
79 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
80
81 unsigned int pic16aopLiteral (value *val, int offset);
82 const char *pic16_AopType(short type);
83 static iCode *ifxForOp ( operand *op, iCode *ic );
84
85 void pic16_pushpCodeOp(pCodeOp *pcop);
86 void pic16_poppCodeOp(pCodeOp *pcop);
87
88 static bool is_LitOp(operand *op);
89 static bool is_LitAOp(asmop *aop);
90
91
92 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
93
94 /* this is the down and dirty file with all kinds of 
95    kludgy & hacky stuff. This is what it is all about
96    CODE GENERATION for a specific MCU . some of the
97    routines may be reusable, will have to see */
98
99 static char *zero = "#0x00";
100 static char *one  = "#0x01";
101 static char *spname = "sp";
102
103
104 /*
105  * Function return value policy (MSB-->LSB):
106  *  8 bits      -> WREG
107  * 16 bits      -> PRODL:WREG
108  * 24 bits      -> PRODH:PRODL:WREG
109  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
110  * >32 bits     -> on stack, and FSR0 points to the beginning
111  *
112  */
113  
114
115 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
116 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
117 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
118 static char **fReturn = fReturnpic16;
119
120 static char *accUse[] = {"WREG"};
121
122 //static short rbank = -1;
123
124 static struct {
125     short r0Pushed;
126     short r1Pushed;
127     short fsr0Pushed;
128     short accInUse;
129     short inLine;
130     short debugLine;
131     short nRegsSaved;
132     short ipushRegs;
133     set *sendSet;
134     int interruptvector;
135 } _G;
136
137 /* Resolved ifx structure. This structure stores information
138    about an iCode ifx that makes it easier to generate code.
139 */
140 typedef struct resolvedIfx {
141   symbol *lbl;     /* pointer to a label */
142   int condition;   /* true or false ifx */
143   int generated;   /* set true when the code associated with the ifx
144                     * is generated */
145 } resolvedIfx;
146
147 extern int pic16_ptrRegReq ;
148 extern int pic16_nRegs;
149 extern FILE *codeOutFile;
150 static void saverbank (int, iCode *,bool);
151
152 static lineNode *lineHead = NULL;
153 static lineNode *lineCurr = NULL;
154
155 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
156 0xE0, 0xC0, 0x80, 0x00};
157 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
158 0x07, 0x03, 0x01, 0x00};
159
160 static  pBlock *pb;
161
162 /*-----------------------------------------------------------------*/
163 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
164 /*                 exponent of 2 is returned, otherwise -1 is      */
165 /*                 returned.                                       */
166 /* note that this is similar to the function `powof2' in SDCCsymt  */
167 /* if(n == 2^y)                                                    */
168 /*   return y;                                                     */
169 /* return -1;                                                      */
170 /*-----------------------------------------------------------------*/
171 static int my_powof2 (unsigned long num)
172 {
173   if(num) {
174     if( (num & (num-1)) == 0) {
175       int nshifts = -1;
176       while(num) {
177         num>>=1;
178         nshifts++;
179       }
180       return nshifts;
181     }
182   }
183
184   return -1;
185 }
186
187 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
188 {
189   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
190                        line_no,
191                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
192                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
193                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
194                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
195                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
196                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
197                        ((result) ? AOP_SIZE(result) : 0));
198 }
199
200 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
201 {
202
203   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
204                        line_no,
205                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
206                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
207                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
208                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
209                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
210                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
211
212 }
213
214 void pic16_emitpcomment (char *fmt, ...)
215 {
216     va_list ap;
217     char lb[INITIAL_INLINEASM];  
218     char *lbp = lb;
219
220     va_start(ap,fmt);   
221
222     lb[0] = ';';
223     vsprintf(lb+1,fmt,ap);
224
225     while (isspace(*lbp)) lbp++;
226
227     if (lbp && *lbp) 
228         lineCurr = (lineCurr ?
229                     connectLine(lineCurr,newLineNode(lb)) :
230                     (lineHead = newLineNode(lb)));
231     lineCurr->isInline = _G.inLine;
232     lineCurr->isDebug  = _G.debugLine;
233
234     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
235     va_end(ap);
236
237 //      fprintf(stderr, "%s\n", lb);
238 }
239
240 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
241 {
242     va_list ap;
243     char lb[INITIAL_INLINEASM];  
244     char *lbp = lb;
245
246     if(!pic16_debug_verbose)
247       return;
248
249     va_start(ap,fmt);   
250
251     if (inst && *inst) {
252         if (fmt && *fmt)
253             sprintf(lb,"%s\t",inst);
254         else
255             sprintf(lb,"%s",inst);
256         vsprintf(lb+(strlen(lb)),fmt,ap);
257     }  else
258         vsprintf(lb,fmt,ap);
259
260     while (isspace(*lbp)) lbp++;
261
262     if (lbp && *lbp) 
263         lineCurr = (lineCurr ?
264                     connectLine(lineCurr,newLineNode(lb)) :
265                     (lineHead = newLineNode(lb)));
266     lineCurr->isInline = _G.inLine;
267     lineCurr->isDebug  = _G.debugLine;
268
269     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
270     va_end(ap);
271
272 //      fprintf(stderr, "%s\n", lb);
273 }
274
275 void pic16_emitpLabel(int key)
276 {
277   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
278 }
279
280 void pic16_emitpLabelFORCE(int key)
281 {
282   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
283 }
284
285 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
286 {
287
288   if(pcop)
289     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
290   else
291     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
292     
293 //    fprintf(stderr, "%s\n", pcop->name);
294 }
295
296 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
297 {
298
299   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
300
301 }
302
303
304 #if 1
305 #define pic16_emitcode  DEBUGpic16_emitcode
306 #else
307 /*-----------------------------------------------------------------*/
308 /* pic16_emitcode - writes the code into a file : for now it is simple    */
309 /*-----------------------------------------------------------------*/
310 void pic16_emitcode (char *inst,char *fmt, ...)
311 {
312     va_list ap;
313     char lb[INITIAL_INLINEASM];  
314     char *lbp = lb;
315
316     va_start(ap,fmt);   
317
318     if (inst && *inst) {
319         if (fmt && *fmt)
320             sprintf(lb,"%s\t",inst);
321         else
322             sprintf(lb,"%s",inst);
323         vsprintf(lb+(strlen(lb)),fmt,ap);
324     }  else
325         vsprintf(lb,fmt,ap);
326
327     while (isspace(*lbp)) lbp++;
328
329     if (lbp && *lbp) 
330         lineCurr = (lineCurr ?
331                     connectLine(lineCurr,newLineNode(lb)) :
332                     (lineHead = newLineNode(lb)));
333     lineCurr->isInline = _G.inLine;
334     lineCurr->isDebug  = _G.debugLine;
335
336 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
337
338 //    if(pic16_debug_verbose)
339 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
340
341     va_end(ap);
342 }
343 #endif
344
345
346 /*-----------------------------------------------------------------*/
347 /* pic16_emitDebuggerSymbol - associate the current code location  */
348 /*   with a debugger symbol                                        */
349 /*-----------------------------------------------------------------*/
350 void
351 pic16_emitDebuggerSymbol (char * debugSym)
352 {
353   _G.debugLine = 1;
354   pic16_emitcode (";", "%s ==.", debugSym);
355   _G.debugLine = 0;
356 }
357
358
359 /*-----------------------------------------------------------------*/
360 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
361 /*-----------------------------------------------------------------*/
362 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
363 {
364 //    bool r0iu = FALSE , r1iu = FALSE;
365 //    bool r0ou = FALSE , r1ou = FALSE;
366     bool fsr0iu = FALSE, fsr0ou;
367     bool fsr2iu = FALSE, fsr2ou;
368     
369     fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result);
370
371     
372     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
373     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
374     
375     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
376     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
377
378     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
379         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
380         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
381     }
382
383     /* no usage of FSR2 */
384     if(!fsr2iu && !fsr2ou) {
385         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
386         (*aopp)->type = AOP_FSR2;
387
388       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
389     }
390         
391     if(!fsr0iu && !fsr0ou) {
392         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
393         (*aopp)->type = AOP_FSR0;
394         
395       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
396     }
397
398     /* now we know they both have usage */
399     /* if fsr0 not used in this instruction */
400     if (!fsr0iu) {
401         if (!_G.fsr0Pushed) {
402                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
403                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
404                 _G.fsr0Pushed++;
405         }
406
407         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
408         (*aopp)->type = AOP_FSR0;
409
410       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
411     }
412         
413
414     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
415     assert( 0 );
416
417 #if 0
418     /* the logic: if r0 & r1 used in the instruction
419     then we are in trouble otherwise */
420
421     /* first check if r0 & r1 are used by this
422     instruction, in which case we are in trouble */
423     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
424         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
425     {
426         goto endOfWorld;      
427     }
428
429     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
430     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
431
432     /* if no usage of r0 then return it */
433     if (!r0iu && !r0ou) {
434         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
435         (*aopp)->type = AOP_R0;
436         
437         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
438     }
439
440     /* if no usage of r1 then return it */
441     if (!r1iu && !r1ou) {
442         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
443         (*aopp)->type = AOP_R1;
444
445         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
446     }    
447
448     /* now we know they both have usage */
449     /* if r0 not used in this instruction */
450     if (!r0iu) {
451         /* push it if not already pushed */
452         if (!_G.r0Pushed) {
453           //pic16_emitcode ("push","%s",
454           //          pic16_regWithIdx(R0_IDX)->dname);
455             _G.r0Pushed++ ;
456         }
457         
458         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
459         (*aopp)->type = AOP_R0;
460
461         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
462     }
463
464     /* if r1 not used then */
465
466     if (!r1iu) {
467         /* push it if not already pushed */
468         if (!_G.r1Pushed) {
469           //pic16_emitcode ("push","%s",
470           //          pic16_regWithIdx(R1_IDX)->dname);
471             _G.r1Pushed++ ;
472         }
473         
474         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
475         (*aopp)->type = AOP_R1;
476         return pic16_regWithIdx(R1_IDX);
477     }
478
479 endOfWorld :
480     /* I said end of world but not quite end of world yet */
481     /* if this is a result then we can push it on the stack*/
482     if (result) {
483         (*aopp)->type = AOP_STK;    
484         return NULL;
485     }
486
487     /* other wise this is true end of the world */
488     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
489            "getFreePtr should never reach here");
490     exit(0);
491 #endif
492 }
493
494 /*-----------------------------------------------------------------*/
495 /* newAsmop - creates a new asmOp                                  */
496 /*-----------------------------------------------------------------*/
497 static asmop *newAsmop (short type)
498 {
499     asmop *aop;
500
501     aop = Safe_calloc(1,sizeof(asmop));
502     aop->type = type;
503     return aop;
504 }
505
506 static void genSetDPTR(int n)
507 {
508     if (!n)
509     {
510         pic16_emitcode(";", "Select standard DPTR");
511         pic16_emitcode("mov", "dps, #0x00");
512     }
513     else
514     {
515         pic16_emitcode(";", "Select alternate DPTR");
516         pic16_emitcode("mov", "dps, #0x01");
517     }
518 }
519
520 /*-----------------------------------------------------------------*/
521 /* resolveIfx - converts an iCode ifx into a form more useful for  */
522 /*              generating code                                    */
523 /*-----------------------------------------------------------------*/
524 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
525 {
526
527   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
528
529   if(!resIfx) 
530     return;
531
532
533   resIfx->condition = 1;    /* assume that the ifx is true */
534   resIfx->generated = 0;    /* indicate that the ifx has not been used */
535
536   if(!ifx) {
537     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
538
539 #if 1
540     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
541                         __FUNCTION__,__LINE__,resIfx->lbl->key);
542 #endif
543
544   } else {
545     if(IC_TRUE(ifx)) {
546       resIfx->lbl = IC_TRUE(ifx);
547     } else {
548       resIfx->lbl = IC_FALSE(ifx);
549       resIfx->condition = 0;
550     }
551
552 #if 1
553     if(IC_TRUE(ifx)) 
554       DEBUGpic16_emitcode("; ***","ifx true is non-null");
555     if(IC_FALSE(ifx)) 
556       DEBUGpic16_emitcode("; ***","ifx false is non-null");
557 #endif
558   }
559
560   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
561
562 }
563 #if 0
564 /*-----------------------------------------------------------------*/
565 /* pointerCode - returns the code for a pointer type               */
566 /*-----------------------------------------------------------------*/
567 static int pointerCode (sym_link *etype)
568 {
569
570     return PTR_TYPE(SPEC_OCLS(etype));
571
572 }
573 #endif
574
575 /*-----------------------------------------------------------------*/
576 /* aopForSym - for a true symbol                                   */
577 /*-----------------------------------------------------------------*/
578 static asmop *aopForSym (iCode *ic, operand *op, bool result)
579 {
580     symbol *sym=OP_SYMBOL(op);
581     asmop *aop;
582     memmap *space= SPEC_OCLS(sym->etype);
583
584     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
585
586 //    sym = OP_SYMBOL(op);
587
588     /* if already has one */
589     if (sym->aop) {
590             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
591         return sym->aop;
592     }
593
594     /* if symbol was initially placed onStack then we must re-place it
595      * to direct memory, since pic16 does not have a specific stack */
596     if(sym->onStack) {
597         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
598     }
599
600
601 #if 1
602     /* assign depending on the storage class */
603     /* if it is on the stack or indirectly addressable */
604     /* space we need to assign either r0 or r1 to it   */    
605     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
606
607         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
608                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
609         
610         sym->aop = aop = newAsmop(0);
611         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
612         aop->size = getSize(sym->type);
613
614         fprintf(stderr, "%s:%d\t%s\n", __FILE__, __LINE__, __FUNCTION__);
615
616 #if 1
617 //        sym->aop = aop = newAsmop (AOP_REG);
618 //        aop->aopu.aop_dir = sym->name;        //sym->rname ;
619 //      aop->aopu.aop_reg[0] = pic16_regWithIdx(IDX_PLUSW0);    //pic16_pc_plusw2.r;
620 //        aop->size = getSize(sym->type);
621         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
622         
623 //      if(_G.accInUse) {
624 //              pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
625 //      }
626         
627 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_fsr2l), pic16_popCopyReg(&pic16_pc_fsr0l)));
628 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popCopyReg(&pic16_pc_fsr2h), pic16_popCopyReg(&pic16_pc_fsr0h)));
629         
630         
631         /* initialise for stack access via frame pointer */
632         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
633
634 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
635 //              pic16_popCopyReg(&pic16_pc_plusw2), pic16_popCopyReg(&pic16_pc_kzero)));
636         
637 //      if(_G.accInUse) {
638 //              pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
639 //      }
640         
641         return (aop);
642 #endif
643
644 #if 0
645         /* now assign the address of the variable to 
646         the pointer register */
647         if (aop->type != AOP_STK) {
648
649             if (sym->onStack) {
650                     if ( _G.accInUse )
651                         pic16_emitcode("push","acc");
652
653                     pic16_emitcode("mov","a,_bp");
654                     pic16_emitcode("add","a,#0x%02x",
655                              ((sym->stack < 0) ?
656                               ((char)(sym->stack - _G.nRegsSaved )) :
657                               ((char)sym->stack)) & 0xff);
658                     pic16_emitcode("mov","%s,a",
659                              aop->aopu.aop_ptr->name);
660
661                     if ( _G.accInUse )
662                         pic16_emitcode("pop","acc");
663             } else
664                 pic16_emitcode("mov","%s,#%s",
665                          aop->aopu.aop_ptr->name,
666                          sym->rname);
667             aop->paged = space->paged;
668         } else
669             aop->aopu.aop_stk = sym->stack;
670         return aop;
671 #endif
672
673     }
674 #endif
675
676 #if 0
677     if (sym->onStack && options.stack10bit)
678     {
679         /* It's on the 10 bit stack, which is located in
680          * far data space.
681          */
682          
683       //DEBUGpic16_emitcode(";","%d",__LINE__);
684
685         if ( _G.accInUse )
686                 pic16_emitcode("push","acc");
687
688         pic16_emitcode("mov","a,_bp");
689         pic16_emitcode("add","a,#0x%02x",
690                  ((sym->stack < 0) ?
691                    ((char)(sym->stack - _G.nRegsSaved )) :
692                    ((char)sym->stack)) & 0xff);
693         
694         genSetDPTR(1);
695         pic16_emitcode ("mov","dpx1,#0x40");
696         pic16_emitcode ("mov","dph1,#0x00");
697         pic16_emitcode ("mov","dpl1, a");
698         genSetDPTR(0);
699         
700         if ( _G.accInUse )
701             pic16_emitcode("pop","acc");
702             
703         sym->aop = aop = newAsmop(AOP_DPTR2);
704         aop->size = getSize(sym->type); 
705         return aop;
706     }
707 #endif
708     //DEBUGpic16_emitcode(";","%d",__LINE__);
709     /* if in bit space */
710     if (IN_BITSPACE(space)) {
711         sym->aop = aop = newAsmop (AOP_CRY);
712         aop->aopu.aop_dir = sym->rname ;
713         aop->size = getSize(sym->type);
714         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
715         return aop;
716     }
717     /* if it is in direct space */
718     if (IN_DIRSPACE(space)) {
719         sym->aop = aop = newAsmop (AOP_DIR);
720         aop->aopu.aop_dir = sym->rname ;
721         aop->size = getSize(sym->type);
722         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
723         pic16_allocDirReg( IC_LEFT(ic) );
724         return aop;
725     }
726
727     if (IN_FARSPACE(space)) {
728         sym->aop = aop = newAsmop (AOP_DIR);
729         aop->aopu.aop_dir = sym->rname ;
730         aop->size = getSize(sym->type);
731         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
732         pic16_allocDirReg( IC_LEFT(ic) );
733         return aop;
734     }
735
736 #if 0                                                                                           // patch 14
737     /* special case for a function */
738     if (IS_FUNC(sym->type)) {   
739         sym->aop = aop = newAsmop(AOP_IMMD);    
740         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
741         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
742         strcpy(aop->aopu.aop_immd,sym->rname);
743         aop->size = FPTRSIZE; 
744         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
745         return aop;
746     }
747 #endif                                                                                          // patch 14
748
749
750     /* only remaining is far space */
751     /* in which case DPTR gets the address */
752     sym->aop = aop = newAsmop(AOP_PCODE);
753
754 /* change the next if to 1 to revert to good old immediate code */
755         if(IN_CODESPACE(space)) {
756                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
757                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
758                 PCOI(aop->aopu.pcop)->index = 0;
759         } else {
760                 /* try to allocate via direct register */
761                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
762 //              aop->size = getSize( sym->type );
763         }
764
765         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
766                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
767
768 #if 0
769         if(!pic16_allocDirReg (IC_LEFT(ic)))
770                 return NULL;
771 #endif
772
773         if(IN_DIRSPACE( space ))
774                 aop->size = PTRSIZE;
775         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
776                 aop->size = FPTRSIZE;
777         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
778         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
779         else {
780                 assert( 0 );
781         }
782
783     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
784
785     /* if it is in code space */
786     if (IN_CODESPACE(space))
787         aop->code = 1;
788
789     return aop;     
790 }
791
792 /*-----------------------------------------------------------------*/
793 /* aopForRemat - rematerialzes an object                           */
794 /*-----------------------------------------------------------------*/
795 static asmop *aopForRemat (operand *op) // x symbol *sym)
796 {
797   symbol *sym = OP_SYMBOL(op);
798   iCode *ic = NULL, *oldic;
799   asmop *aop = newAsmop(AOP_PCODE);
800   int val = 0;
801   int offset = 0;
802   int viaimmd=0;
803
804
805         ic = sym->rematiCode;
806
807         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
808         
809         if(IS_OP_POINTER(op)) {
810                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
811         }
812
813         for (;;) {
814                 oldic = ic;
815
816 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
817         
818                 if (ic->op == '+') {
819                         val += (int) operandLitValue(IC_RIGHT(ic));
820                 } else if (ic->op == '-') {
821                         val -= (int) operandLitValue(IC_RIGHT(ic));
822                 } else
823                         break;
824                 
825                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
826         }
827
828         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
829
830         if(!op->isaddr)viaimmd++; else viaimmd=0;
831                 
832 /* set the following if to 1 to revert to good old immediate code */
833         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
834                 || viaimmd) {
835
836                 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
837
838                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
839
840 #if 0
841                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
842 #else
843                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
844 #endif
845
846                 PCOI(aop->aopu.pcop)->index = val;
847         } else {
848                 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
849
850                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
851                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
852 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
853         }
854
855
856         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
857                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
858 #if 0
859                 val, IS_PTR_CONST(operandType(op)));
860 #else
861                 val, IS_CODEPTR(operandType(op)));
862 #endif
863
864 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
865
866         pic16_allocDirReg (IC_LEFT(ic));
867
868         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
869                 aop->code = 1;
870
871   return aop;        
872 }
873
874 static int aopIdx (asmop *aop, int offset)
875 {
876   if(!aop)
877     return -1;
878
879   if(aop->type !=  AOP_REG)
880     return -2;
881         
882   return aop->aopu.aop_reg[offset]->rIdx;
883
884 }
885 /*-----------------------------------------------------------------*/
886 /* regsInCommon - two operands have some registers in common       */
887 /*-----------------------------------------------------------------*/
888 static bool regsInCommon (operand *op1, operand *op2)
889 {
890     symbol *sym1, *sym2;
891     int i;
892
893     /* if they have registers in common */
894     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
895         return FALSE ;
896
897     sym1 = OP_SYMBOL(op1);
898     sym2 = OP_SYMBOL(op2);
899
900     if (sym1->nRegs == 0 || sym2->nRegs == 0)
901         return FALSE ;
902
903     for (i = 0 ; i < sym1->nRegs ; i++) {
904         int j;
905         if (!sym1->regs[i])
906             continue ;
907
908         for (j = 0 ; j < sym2->nRegs ;j++ ) {
909             if (!sym2->regs[j])
910                 continue ;
911
912             if (sym2->regs[j] == sym1->regs[i])
913                 return TRUE ;
914         }
915     }
916
917     return FALSE ;
918 }
919
920 /*-----------------------------------------------------------------*/
921 /* operandsEqu - equivalent                                        */
922 /*-----------------------------------------------------------------*/
923 static bool operandsEqu ( operand *op1, operand *op2)
924 {
925     symbol *sym1, *sym2;
926
927     /* if they not symbols */
928     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
929         return FALSE;
930
931     sym1 = OP_SYMBOL(op1);
932     sym2 = OP_SYMBOL(op2);
933
934     /* if both are itemps & one is spilt
935        and the other is not then false */
936     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
937         sym1->isspilt != sym2->isspilt )
938         return FALSE ;
939
940     /* if they are the same */
941     if (sym1 == sym2)
942         return TRUE ;
943
944     if (sym1->rname[0] && sym2->rname[0]
945         && strcmp (sym1->rname, sym2->rname) == 0)
946         return TRUE;
947
948
949     /* if left is a tmp & right is not */
950     if (IS_ITEMP(op1)  && 
951         !IS_ITEMP(op2) &&
952         sym1->isspilt  &&
953         (sym1->usl.spillLoc == sym2))
954         return TRUE;
955
956     if (IS_ITEMP(op2)  && 
957         !IS_ITEMP(op1) &&
958         sym2->isspilt  &&
959         sym1->level > 0 &&
960         (sym2->usl.spillLoc == sym1))
961         return TRUE ;
962
963     return FALSE ;
964 }
965
966 /*-----------------------------------------------------------------*/
967 /* pic16_sameRegs - two asmops have the same registers                   */
968 /*-----------------------------------------------------------------*/
969 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
970 {
971     int i;
972
973     if (aop1 == aop2)
974         return TRUE ;
975
976     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
977                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
978
979     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
980
981     if (aop1->type != AOP_REG ||
982         aop2->type != AOP_REG )
983         return FALSE ;
984
985     if (aop1->size != aop2->size )
986         return FALSE ;
987
988     for (i = 0 ; i < aop1->size ; i++ )
989         if (aop1->aopu.aop_reg[i] !=
990             aop2->aopu.aop_reg[i] )
991             return FALSE ;
992
993     return TRUE ;
994 }
995
996 /*-----------------------------------------------------------------*/
997 /* pic16_aopOp - allocates an asmop for an operand  :                    */
998 /*-----------------------------------------------------------------*/
999 void pic16_aopOp (operand *op, iCode *ic, bool result)
1000 {
1001     asmop *aop;
1002     symbol *sym;
1003     int i;
1004
1005     if (!op)
1006         return ;
1007
1008 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1009
1010     /* if this a literal */
1011     if (IS_OP_LITERAL(op)) {
1012         op->aop = aop = newAsmop(AOP_LIT);
1013         aop->aopu.aop_lit = op->operand.valOperand;
1014         aop->size = getSize(operandType(op));
1015         return;
1016     }
1017
1018     {
1019       sym_link *type = operandType(op);
1020 #if 0
1021       if(IS_PTR_CONST(type))
1022 #else
1023       if(IS_CODEPTR(type))
1024 #endif
1025         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1026     }
1027
1028     /* if already has a asmop then continue */
1029     if (op->aop)
1030         return ;
1031
1032     /* if the underlying symbol has a aop */
1033     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1034       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1035         op->aop = OP_SYMBOL(op)->aop;
1036         return;
1037     }
1038
1039     /* if this is a true symbol */
1040     if (IS_TRUE_SYMOP(op)) {    
1041         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1042       op->aop = aopForSym(ic, op, result);
1043       return ;
1044     }
1045
1046     /* this is a temporary : this has
1047     only four choices :
1048     a) register
1049     b) spillocation
1050     c) rematerialize 
1051     d) conditional   
1052     e) can be a return use only */
1053
1054     sym = OP_SYMBOL(op);
1055
1056         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
1057     /* if the type is a conditional */
1058     if (sym->regType == REG_CND) {
1059         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1060         aop->size = 0;
1061         return;
1062     }
1063
1064     /* if it is spilt then two situations
1065     a) is rematerialize 
1066     b) has a spill location */
1067     if (sym->isspilt || sym->nRegs == 0) {
1068
1069       DEBUGpic16_emitcode(";","%d",__LINE__);
1070         /* rematerialize it NOW */
1071         if (sym->remat) {
1072
1073             sym->aop = op->aop = aop =
1074                                       aopForRemat (op);
1075             aop->size = getSize(sym->type);
1076             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1077             return;
1078         }
1079
1080 #if 1
1081         if (sym->accuse) {
1082             int i;
1083             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1084             aop->size = getSize(sym->type);
1085             for ( i = 0 ; i < 1 ; i++ ) {
1086                 aop->aopu.aop_str[i] = accUse[i];
1087 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1088             }
1089             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1090             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1091             return;  
1092         }
1093 #endif
1094
1095 #if 1
1096         if (sym->ruonly ) {
1097           /*
1098           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1099           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1100           //pic16_allocDirReg (IC_LEFT(ic));
1101           aop->size = getSize(sym->type);
1102           */
1103
1104           unsigned i;
1105
1106           aop = op->aop = sym->aop = newAsmop(AOP_STR);
1107           aop->size = getSize(sym->type);
1108           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1109             aop->aopu.aop_str[i] = fReturn[i];
1110
1111           DEBUGpic16_emitcode(";","%d",__LINE__);
1112           return;
1113         }
1114 #endif
1115         /* else spill location  */
1116         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1117             /* force a new aop if sizes differ */
1118             sym->usl.spillLoc->aop = NULL;
1119         }
1120         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1121                             __FUNCTION__,__LINE__,
1122                             sym->usl.spillLoc->rname,
1123                             sym->rname, sym->usl.spillLoc->offset);
1124
1125         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1126         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1127         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1128                                           getSize(sym->type), 
1129                                           sym->usl.spillLoc->offset, op);
1130         aop->size = getSize(sym->type);
1131
1132         return;
1133     }
1134
1135     {
1136       sym_link *type = operandType(op);
1137 #if 0
1138       if(IS_PTR_CONST(type)) 
1139 #else
1140       if(IS_CODEPTR(type)) 
1141 #endif
1142         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1143     }
1144
1145     /* must be in a register */
1146     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1147     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1148     aop->size = sym->nRegs;
1149     for ( i = 0 ; i < sym->nRegs ;i++)
1150         aop->aopu.aop_reg[i] = sym->regs[i];
1151 }
1152
1153 /*-----------------------------------------------------------------*/
1154 /* pic16_freeAsmop - free up the asmop given to an operand               */
1155 /*----------------------------------------------------------------*/
1156 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1157 {   
1158     asmop *aop ;
1159
1160     if (!op)
1161         aop = aaop;
1162     else 
1163         aop = op->aop;
1164
1165     if (!aop)
1166         return ;
1167
1168     if (aop->freed)
1169         goto dealloc; 
1170
1171     aop->freed = 1;
1172
1173     /* depending on the asmop type only three cases need work AOP_RO
1174        , AOP_R1 && AOP_STK */
1175 #if 1
1176     switch (aop->type) {
1177         case AOP_FSR0 :
1178             if (_G.fsr0Pushed ) {
1179                 if (pop) {
1180                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1181                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1182 //                    pic16_emitcode ("pop","ar0");
1183                     _G.fsr0Pushed--;
1184                 }
1185             }
1186             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1187             break;
1188
1189         case AOP_FSR2 :
1190             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1191             break;
1192
1193         case AOP_R0 :
1194             if (_G.r0Pushed ) {
1195                 if (pop) {
1196                     pic16_emitcode ("pop","ar0");     
1197                     _G.r0Pushed--;
1198                 }
1199             }
1200             bitVectUnSetBit(ic->rUsed,R0_IDX);
1201             break;
1202
1203         case AOP_R1 :
1204             if (_G.r1Pushed ) {
1205                 if (pop) {
1206                     pic16_emitcode ("pop","ar1");
1207                     _G.r1Pushed--;
1208                 }
1209             }
1210             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1211             break;
1212
1213         case AOP_STK :
1214         {
1215             int sz = aop->size;    
1216             int stk = aop->aopu.aop_stk + aop->size;
1217             bitVectUnSetBit(ic->rUsed,R0_IDX);
1218             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1219
1220             getFreePtr(ic,&aop,FALSE);
1221             
1222             if (options.stack10bit)
1223             {
1224                 /* I'm not sure what to do here yet... */
1225                 /* #STUB */
1226                 fprintf(stderr, 
1227                         "*** Warning: probably generating bad code for "
1228                         "10 bit stack mode.\n");
1229             }
1230             
1231             if (stk) {
1232                 pic16_emitcode ("mov","a,_bp");
1233                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1234                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1235             } else {
1236                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1237             }
1238
1239             while (sz--) {
1240                 pic16_emitcode("pop","acc");
1241                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1242                 if (!sz) break;
1243                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1244             }
1245             op->aop = aop;
1246             pic16_freeAsmop(op,NULL,ic,TRUE);
1247             if (_G.r0Pushed) {
1248                 pic16_emitcode("pop","ar0");
1249                 _G.r0Pushed--;
1250             }
1251
1252             if (_G.r1Pushed) {
1253                 pic16_emitcode("pop","ar1");
1254                 _G.r1Pushed--;
1255             }       
1256         }
1257     }
1258 #endif
1259
1260 dealloc:
1261     /* all other cases just dealloc */
1262     if (op ) {
1263         op->aop = NULL;
1264         if (IS_SYMOP(op)) {
1265             OP_SYMBOL(op)->aop = NULL;    
1266             /* if the symbol has a spill */
1267             if (SPIL_LOC(op))
1268                 SPIL_LOC(op)->aop = NULL;
1269         }
1270     }
1271 }
1272
1273 /*-----------------------------------------------------------------*/
1274 /* pic16_aopGet - for fetching value of the aop                          */
1275 /*-----------------------------------------------------------------*/
1276 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1277 {
1278     char *s = buffer ;
1279     char *rs;
1280
1281     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1282
1283     /* offset is greater than size then zero */
1284     if (offset > (aop->size - 1) &&
1285         aop->type != AOP_LIT)
1286         return zero;
1287
1288     /* depending on type */
1289     switch (aop->type) {
1290
1291     case AOP_FSR0:
1292     case AOP_FSR2:
1293       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1294       rs = Safe_calloc(1, strlen(s)+1);
1295       strcpy(rs, s);
1296       return (rs);
1297       
1298 #if 0
1299       /* if we need to increment it */
1300       while (offset > aop->coff)
1301         {
1302           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1303           aop->coff++;
1304         }
1305
1306       while (offset < aop->coff)
1307         {
1308           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1309           aop->coff--;
1310         }
1311       aop->coff = offset;
1312       if (aop->paged)
1313         {
1314           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1315           return (dname ? "acc" : "a");
1316         }
1317       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1318       rs = Safe_calloc (1, strlen (s) + 1);
1319       strcpy (rs, s);
1320       return rs;
1321 #endif
1322
1323         
1324     case AOP_IMMD:
1325         if (bit16) 
1326             sprintf (s,"%s",aop->aopu.aop_immd);
1327         else
1328             if (offset) 
1329                 sprintf(s,"(%s >> %d)",
1330                         aop->aopu.aop_immd,
1331                         offset*8);
1332             else
1333                 sprintf(s,"%s",
1334                         aop->aopu.aop_immd);
1335         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1336         rs = Safe_calloc(1,strlen(s)+1);
1337         strcpy(rs,s);   
1338         return rs;
1339         
1340     case AOP_DIR:
1341       if (offset) {
1342         sprintf(s,"(%s + %d)",
1343                 aop->aopu.aop_dir,
1344                 offset);
1345         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1346       } else
1347             sprintf(s,"%s",aop->aopu.aop_dir);
1348         rs = Safe_calloc(1,strlen(s)+1);
1349         strcpy(rs,s);   
1350         return rs;
1351         
1352     case AOP_REG:
1353       //if (dname) 
1354       //    return aop->aopu.aop_reg[offset]->dname;
1355       //else
1356             return aop->aopu.aop_reg[offset]->name;
1357         
1358     case AOP_CRY:
1359       //pic16_emitcode(";","%d",__LINE__);
1360       return aop->aopu.aop_dir;
1361         
1362     case AOP_ACC:
1363         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1364 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1365 //        assert( 0 );
1366 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1367         rs = Safe_strdup("WREG");
1368         return (rs);
1369
1370     case AOP_LIT:
1371         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1372         rs = Safe_calloc(1,strlen(s)+1);
1373         strcpy(rs,s);   
1374         return rs;
1375         
1376     case AOP_STR:
1377         aop->coff = offset ;
1378         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1379             dname)
1380             return "acc";
1381         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1382         
1383         return aop->aopu.aop_str[offset];
1384         
1385     case AOP_PCODE:
1386       {
1387         pCodeOp *pcop = aop->aopu.pcop;
1388         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1389         if(pcop->name) {
1390           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1391           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1392           sprintf(s,"%s", pcop->name);
1393         } else
1394           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1395
1396       }
1397       rs = Safe_calloc(1,strlen(s)+1);
1398       strcpy(rs,s);   
1399       return rs;
1400
1401       case AOP_STK:
1402 //        pCodeOp *pcop = aop->aop
1403         break;
1404
1405     }
1406
1407     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1408     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1409            "aopget got unsupported aop->type");
1410     exit(0);
1411 }
1412
1413
1414 /*-----------------------------------------------------------------*/
1415 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1416 /*-----------------------------------------------------------------*/
1417 pCodeOp *pic16_popGetTempReg(void)
1418 {
1419   pCodeOp *pcop;
1420   symbol *cfunc;
1421
1422 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1423
1424         cfunc = currFunc;
1425         currFunc = NULL;
1426
1427         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1428         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1429                 PCOR(pcop)->r->wasUsed=1;
1430                 PCOR(pcop)->r->isFree=0;
1431
1432                 /* push value on stack */
1433                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1434         }
1435
1436         currFunc = cfunc;
1437
1438   return pcop;
1439 }
1440
1441 /*-----------------------------------------------------------------*/
1442 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1443 /*-----------------------------------------------------------------*/
1444 void pic16_popReleaseTempReg(pCodeOp *pcop)
1445 {
1446         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1447
1448         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1449                 PCOR(pcop)->r->isFree = 1;
1450                 
1451                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1452         }
1453 }
1454 /*-----------------------------------------------------------------*/
1455 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1456 /*-----------------------------------------------------------------*/
1457 pCodeOp *pic16_popGetLabel(unsigned int key)
1458 {
1459
1460   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1461
1462   if(key>max_key)
1463     max_key = key;
1464
1465   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1466 }
1467
1468 /*-----------------------------------------------------------------*/
1469 /* pic16_popCopyReg - copy a pcode operator                              */
1470 /*-----------------------------------------------------------------*/
1471 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1472 {
1473   pCodeOpReg *pcor;
1474
1475   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1476   pcor->pcop.type = pc->pcop.type;
1477   if(pc->pcop.name) {
1478     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1479       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1480   } else
1481     pcor->pcop.name = NULL;
1482
1483   pcor->r = pc->r;
1484   pcor->rIdx = pc->rIdx;
1485   pcor->r->wasUsed=1;
1486
1487 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1488
1489   return PCOP(pcor);
1490 }
1491
1492 /*-----------------------------------------------------------------*/
1493 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1494 /*-----------------------------------------------------------------*/
1495 pCodeOp *pic16_popGetLit(unsigned int lit)
1496 {
1497   return pic16_newpCodeOpLit(lit);
1498 }
1499
1500 /*-----------------------------------------------------------------*/
1501 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1502 /*-----------------------------------------------------------------*/
1503 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1504 {
1505   return pic16_newpCodeOpLit2(lit, arg2);
1506 }
1507
1508
1509 /*-----------------------------------------------------------------*/
1510 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1511 /*-----------------------------------------------------------------*/
1512 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1513 {
1514   return pic16_newpCodeOpImmd(name, offset,index, 0);
1515 }
1516
1517
1518 /*-----------------------------------------------------------------*/
1519 /* pic16_popGet - asm operator to pcode operator conversion              */
1520 /*-----------------------------------------------------------------*/
1521 pCodeOp *pic16_popGetWithString(char *str)
1522 {
1523   pCodeOp *pcop;
1524
1525
1526   if(!str) {
1527     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1528     exit (1);
1529   }
1530
1531   pcop = pic16_newpCodeOp(str,PO_STR);
1532
1533   return pcop;
1534 }
1535
1536 /*-----------------------------------------------------------------*/
1537 /* pic16_popRegFromString -                                        */
1538 /*-----------------------------------------------------------------*/
1539 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1540 {
1541
1542   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1543   pcop->type = PO_DIR;
1544
1545   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1546   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1547
1548   if(!str)
1549     str = "BAD_STRING";
1550
1551   pcop->name = Safe_calloc(1,strlen(str)+1);
1552   strcpy(pcop->name,str);
1553
1554   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1555
1556   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1557   if(PCOR(pcop)->r == NULL) {
1558 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1559 //              __FUNCTION__, __LINE__, str, size, offset);
1560
1561
1562 //    PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1563         fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1564
1565 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1566   } else {
1567 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1568   }
1569   PCOR(pcop)->instance = offset;
1570
1571   return pcop;
1572 }
1573
1574 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1575 {
1576   pCodeOp *pcop;
1577
1578 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1579
1580         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1581         PCOR(pcop)->rIdx = rIdx;
1582         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1583
1584         PCOR(pcop)->r->isFree = 0;
1585         PCOR(pcop)->r->wasUsed = 1;
1586
1587         pcop->type = PCOR(pcop)->r->pc_type;
1588
1589   return pcop;
1590 }
1591
1592 /*---------------------------------------------------------------------------------*/
1593 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1594 /*                 VR 030601                                                       */
1595 /*---------------------------------------------------------------------------------*/
1596 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1597 {
1598   pCodeOpReg2 *pcop2;
1599   pCodeOp *temp;
1600   
1601         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1602
1603         /* comment the following check, so errors to throw up */
1604 //      if(!pcop2)return NULL;
1605
1606         temp = pic16_popGet(aop_dst, offset);
1607         pcop2->pcop2 = temp;
1608         
1609   return PCOP(pcop2);
1610 }
1611
1612
1613
1614 /*--------------------------------------------------------------------------------.-*/
1615 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1616 /*                  VR 030601 , adapted by Hans Dorn                                */
1617 /*--------------------------------------------------------------------------------.-*/
1618 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1619 {
1620   pCodeOpReg2 *pcop2;
1621  
1622         pcop2 = (pCodeOpReg2 *)src;
1623         pcop2->pcop2 = dst;
1624         
1625         return PCOP(pcop2);
1626 }
1627
1628
1629
1630 /*---------------------------------------------------------------------------------*/
1631 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1632 /*                     movff instruction                                           */
1633 /*---------------------------------------------------------------------------------*/
1634 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1635 {
1636   pCodeOpReg2 *pcop2;
1637
1638         if(!noalloc) {
1639                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1640                 pcop2->pcop2 = pic16_popCopyReg(dst);
1641         } else {
1642                 /* the pCodeOp may be already allocated */
1643                 pcop2 = (pCodeOpReg2 *)(src);
1644                 pcop2->pcop2 = (pCodeOp *)(dst);
1645         }
1646
1647   return PCOP(pcop2);
1648 }
1649
1650
1651 /*-----------------------------------------------------------------*/
1652 /* pic16_popGet - asm operator to pcode operator conversion              */
1653 /*-----------------------------------------------------------------*/
1654 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1655 {
1656   //char *s = buffer ;
1657   char *rs;
1658   pCodeOp *pcop;
1659
1660     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1661     /* offset is greater than
1662     size then zero */
1663
1664 //    if (offset > (aop->size - 1) &&
1665 //        aop->type != AOP_LIT)
1666 //      return NULL;  //zero;
1667
1668     /* depending on type */
1669     switch (aop->type) {
1670         
1671     case AOP_R0:
1672     case AOP_R1:
1673     case AOP_DPTR:
1674     case AOP_DPTR2:
1675         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1676         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1677         assert( 0 );
1678         return NULL;
1679
1680
1681     case AOP_FSR0:
1682     case AOP_FSR2:
1683       pcop = Safe_calloc(1, sizeof(pCodeOpReg));
1684       PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;     /* access PLUSW register */
1685       PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
1686       PCOR(pcop)->r->wasUsed = 1;
1687       PCOR(pcop)->r->isFree = 0;
1688       
1689       PCOR(pcop)->instance = offset;
1690       pcop->type = PCOR(pcop)->r->pc_type;
1691       return (pcop);
1692
1693     case AOP_IMMD:
1694       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1695       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1696
1697     case AOP_ACC:
1698       {
1699         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1700
1701         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1702
1703         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1704         
1705         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1706         PCOR(pcop)->rIdx = rIdx;
1707         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1708         PCOR(pcop)->r->wasUsed=1;
1709         PCOR(pcop)->r->isFree=0;
1710
1711         PCOR(pcop)->instance = offset;
1712         pcop->type = PCOR(pcop)->r->pc_type;
1713 //      rs = aop->aopu.aop_reg[offset]->name;
1714 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1715         return pcop;
1716
1717
1718 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1719 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1720
1721 //      assert( 0 );
1722       }
1723         
1724     case AOP_DIR:
1725       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1726       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
1727         
1728     case AOP_REG:
1729       {
1730         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1731
1732         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1733         
1734         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1735 //      pcop->type = PO_GPR_REGISTER;
1736         PCOR(pcop)->rIdx = rIdx;
1737         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);
1738         PCOR(pcop)->r->wasUsed=1;
1739         PCOR(pcop)->r->isFree=0;
1740
1741         PCOR(pcop)->instance = offset;
1742         pcop->type = PCOR(pcop)->r->pc_type;
1743         rs = aop->aopu.aop_reg[offset]->name;
1744         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1745         return pcop;
1746       }
1747
1748     case AOP_CRY:
1749         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1750
1751       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
1752       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1753       //if(PCOR(pcop)->r == NULL)
1754       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1755       return pcop;
1756         
1757     case AOP_LIT:
1758         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1759       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1760
1761     case AOP_STR:
1762       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1763       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1764
1765       /*
1766       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1767       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1768       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1769       pcop->type = PCOR(pcop)->r->pc_type;
1770       pcop->name = PCOR(pcop)->r->name;
1771
1772       return pcop;
1773       */
1774
1775     case AOP_PCODE:
1776       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1777                           __LINE__, 
1778                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1779       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1780 #if 1
1781         switch( aop->aopu.pcop->type ) {
1782                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1783                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1784                 default:
1785                         assert( 0 );    /* should never reach here */;
1786         }
1787 #else
1788       PCOI(pcop)->offset = offset;
1789 #endif
1790       return pcop;
1791     }
1792
1793     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1794            "pic16_popGet got unsupported aop->type");
1795     exit(0);
1796 }
1797 /*-----------------------------------------------------------------*/
1798 /* pic16_aopPut - puts a string for a aop                                */
1799 /*-----------------------------------------------------------------*/
1800 void pic16_aopPut (asmop *aop, char *s, int offset)
1801 {
1802     char *d = buffer ;
1803     symbol *lbl ;
1804
1805     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1806
1807     if (aop->size && offset > ( aop->size - 1)) {
1808         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1809                "pic16_aopPut got offset > aop->size");
1810         exit(0);
1811     }
1812
1813     /* will assign value to value */
1814     /* depending on where it is ofcourse */
1815     switch (aop->type) {
1816     case AOP_DIR:
1817       if (offset) {
1818         sprintf(d,"(%s + %d)",
1819                 aop->aopu.aop_dir,offset);
1820         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1821
1822       } else
1823             sprintf(d,"%s",aop->aopu.aop_dir);
1824         
1825         if (strcmp(d,s)) {
1826           DEBUGpic16_emitcode(";","%d",__LINE__);
1827           if(strcmp(s,"W"))
1828             pic16_emitcode("movf","%s,w",s);
1829           pic16_emitcode("movwf","%s",d);
1830
1831           if(strcmp(s,"W")) {
1832             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1833             if(offset >= aop->size) {
1834               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1835               break;
1836             } else
1837               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1838           }
1839
1840           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1841
1842
1843         }
1844         break;
1845         
1846     case AOP_REG:
1847       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1848         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1849           /*
1850             if (*s == '@'           ||
1851                 strcmp(s,"r0") == 0 ||
1852                 strcmp(s,"r1") == 0 ||
1853                 strcmp(s,"r2") == 0 ||
1854                 strcmp(s,"r3") == 0 ||
1855                 strcmp(s,"r4") == 0 ||
1856                 strcmp(s,"r5") == 0 ||
1857                 strcmp(s,"r6") == 0 || 
1858                 strcmp(s,"r7") == 0 )
1859                 pic16_emitcode("mov","%s,%s  ; %d",
1860                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1861             else
1862           */
1863
1864           if(strcmp(s,"W")==0 )
1865             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1866
1867           pic16_emitcode("movwf","%s",
1868                    aop->aopu.aop_reg[offset]->name);
1869
1870           if(strcmp(s,zero)==0) {
1871             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1872
1873           } else if(strcmp(s,"W")==0) {
1874             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1875             pcop->type = PO_GPR_REGISTER;
1876
1877             PCOR(pcop)->rIdx = -1;
1878             PCOR(pcop)->r = NULL;
1879
1880             DEBUGpic16_emitcode(";","%d",__LINE__);
1881             pcop->name = Safe_strdup(s);
1882             pic16_emitpcode(POC_MOVFW,pcop);
1883             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1884           } else if(strcmp(s,one)==0) {
1885             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1886             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1887           } else {
1888             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1889           }
1890         }
1891         break;
1892         
1893     case AOP_DPTR:
1894     case AOP_DPTR2:
1895     
1896     if (aop->type == AOP_DPTR2)
1897     {
1898         genSetDPTR(1);
1899     }
1900     
1901         if (aop->code) {
1902             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1903                    "pic16_aopPut writting to code space");
1904             exit(0);
1905         }
1906         
1907         while (offset > aop->coff) {
1908             aop->coff++;
1909             pic16_emitcode ("inc","dptr");
1910         }
1911         
1912         while (offset < aop->coff) {
1913             aop->coff-- ;
1914             pic16_emitcode("lcall","__decdptr");
1915         }
1916         
1917         aop->coff = offset;
1918         
1919         /* if not in accumulater */
1920         MOVA(s);        
1921         
1922         pic16_emitcode ("movx","@dptr,a");
1923         
1924     if (aop->type == AOP_DPTR2)
1925     {
1926         genSetDPTR(0);
1927     }
1928         break;
1929         
1930     case AOP_R0:
1931     case AOP_R1:
1932         while (offset > aop->coff) {
1933             aop->coff++;
1934             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1935         }
1936         while (offset < aop->coff) {
1937             aop->coff-- ;
1938             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1939         }
1940         aop->coff = offset;
1941         
1942         if (aop->paged) {
1943             MOVA(s);           
1944             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1945             
1946         } else
1947             if (*s == '@') {
1948                 MOVA(s);
1949                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1950             } else
1951                 if (strcmp(s,"r0") == 0 ||
1952                     strcmp(s,"r1") == 0 ||
1953                     strcmp(s,"r2") == 0 ||
1954                     strcmp(s,"r3") == 0 ||
1955                     strcmp(s,"r4") == 0 ||
1956                     strcmp(s,"r5") == 0 ||
1957                     strcmp(s,"r6") == 0 || 
1958                     strcmp(s,"r7") == 0 ) {
1959                     char buffer[10];
1960                     sprintf(buffer,"a%s",s);
1961                     pic16_emitcode("mov","@%s,%s",
1962                              aop->aopu.aop_ptr->name,buffer);
1963                 } else
1964                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1965         
1966         break;
1967         
1968     case AOP_STK:
1969         if (strcmp(s,"a") == 0)
1970             pic16_emitcode("push","acc");
1971         else
1972             pic16_emitcode("push","%s",s);
1973         
1974         break;
1975         
1976     case AOP_CRY:
1977         /* if bit variable */
1978         if (!aop->aopu.aop_dir) {
1979             pic16_emitcode("clr","a");
1980             pic16_emitcode("rlc","a");
1981         } else {
1982             if (s == zero) 
1983                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1984             else
1985                 if (s == one)
1986                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1987                 else
1988                     if (!strcmp(s,"c"))
1989                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1990                     else {
1991                         lbl = newiTempLabel(NULL);
1992                         
1993                         if (strcmp(s,"a")) {
1994                             MOVA(s);
1995                         }
1996                         pic16_emitcode("clr","c");
1997                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1998                         pic16_emitcode("cpl","c");
1999                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2000                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2001                     }
2002         }
2003         break;
2004         
2005     case AOP_STR:
2006         aop->coff = offset;
2007         if (strcmp(aop->aopu.aop_str[offset],s))
2008             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2009         break;
2010         
2011     case AOP_ACC:
2012         aop->coff = offset;
2013         if (!offset && (strcmp(s,"acc") == 0))
2014             break;
2015         
2016         if (strcmp(aop->aopu.aop_str[offset],s))
2017             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2018         break;
2019
2020     default :
2021         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2022                "pic16_aopPut got unsupported aop->type");
2023         exit(0);    
2024     }    
2025
2026 }
2027
2028 /*-----------------------------------------------------------------*/
2029 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
2030 /*-----------------------------------------------------------------*/
2031 static void mov2w (asmop *aop, int offset)
2032 {
2033
2034 //  if(!aop)
2035 //    return;
2036
2037         DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2038
2039         if(is_LitAOp(aop))
2040                 pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2041         else
2042                 pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2043
2044 }
2045
2046
2047 /* push pcop into stack */
2048 void pic16_pushpCodeOp(pCodeOp *pcop)
2049 {
2050 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2051         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
2052 }
2053
2054 /* pop pcop from stack */
2055 void pic16_poppCodeOp(pCodeOp *pcop)
2056 {
2057         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
2058 }
2059
2060
2061 /*-----------------------------------------------------------------*/
2062 /* pushw - pushes wreg to stack                                    */
2063 /*-----------------------------------------------------------------*/
2064 void pushw(void)
2065 {
2066         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2067         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
2068 }
2069
2070                 
2071 /*-----------------------------------------------------------------*/
2072 /* pushaop - pushes aop to stack                                   */
2073 /*-----------------------------------------------------------------*/
2074 void pushaop(asmop *aop, int offset)
2075 {
2076         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2077         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
2078 }
2079
2080 /*-----------------------------------------------------------------*/
2081 /* popaop - pops aop from stack                                    */
2082 /*-----------------------------------------------------------------*/
2083 void popaop(asmop *aop, int offset)
2084 {
2085         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2086         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
2087 }
2088
2089 void popaopidx(asmop *aop, int offset, int index)
2090 {
2091   int ofs=1;
2092
2093         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2094
2095         if(STACK_MODEL_LARGE)ofs++;
2096
2097         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2098         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
2099 }
2100
2101 /*-----------------------------------------------------------------*/
2102 /* reAdjustPreg - points a register back to where it should        */
2103 /*-----------------------------------------------------------------*/
2104 static void reAdjustPreg (asmop *aop)
2105 {
2106     int size ;
2107
2108     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2109     aop->coff = 0;
2110     if ((size = aop->size) <= 1)
2111         return ;
2112     size-- ;
2113     switch (aop->type) {
2114         case AOP_R0 :
2115         case AOP_R1 :
2116             while (size--)
2117                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2118             break;          
2119         case AOP_DPTR :
2120         case AOP_DPTR2:
2121             if (aop->type == AOP_DPTR2)
2122             {
2123                 genSetDPTR(1);
2124             } 
2125             while (size--)
2126             {
2127                 pic16_emitcode("lcall","__decdptr");
2128             }
2129                 
2130             if (aop->type == AOP_DPTR2)
2131             {
2132                 genSetDPTR(0);
2133             }                
2134             break;  
2135
2136     }   
2137
2138 }
2139
2140
2141 #if 0
2142 /*-----------------------------------------------------------------*/
2143 /* opIsGptr: returns non-zero if the passed operand is             */   
2144 /* a generic pointer type.                                         */
2145 /*-----------------------------------------------------------------*/ 
2146 static int opIsGptr(operand *op)
2147 {
2148     sym_link *type = operandType(op);
2149     
2150     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2151     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2152     {
2153         return 1;
2154     }
2155     return 0;        
2156 }
2157 #endif
2158
2159 /*-----------------------------------------------------------------*/
2160 /* pic16_getDataSize - get the operand data size                         */
2161 /*-----------------------------------------------------------------*/
2162 int pic16_getDataSize(operand *op)
2163 {
2164     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2165
2166
2167     return AOP_SIZE(op);
2168
2169     // tsd- in the pic port, the genptr size is 1, so this code here
2170     // fails. ( in the 8051 port, the size was 4).
2171 #if 0
2172     int size;
2173     size = AOP_SIZE(op);
2174     if (size == GPTRSIZE)
2175     {
2176         sym_link *type = operandType(op);
2177         if (IS_GENPTR(type))
2178         {
2179             /* generic pointer; arithmetic operations
2180              * should ignore the high byte (pointer type).
2181              */
2182             size--;
2183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2184         }
2185     }
2186     return size;
2187 #endif
2188 }
2189
2190 /*-----------------------------------------------------------------*/
2191 /* pic16_outAcc - output Acc                                             */
2192 /*-----------------------------------------------------------------*/
2193 void pic16_outAcc(operand *result)
2194 {
2195   int size,offset;
2196   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2197   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2198
2199
2200   size = pic16_getDataSize(result);
2201   if(size){
2202     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2203     size--;
2204     offset = 1;
2205     /* unsigned or positive */
2206     while(size--)
2207       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2208   }
2209
2210 }
2211
2212 /*-----------------------------------------------------------------*/
2213 /* pic16_outBitC - output a bit C                                  */
2214 /*                 Move to result the value of Carry flag -- VR    */
2215 /*-----------------------------------------------------------------*/
2216 void pic16_outBitC(operand *result)
2217 {
2218   int i;
2219
2220     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2221     /* if the result is bit */
2222     if (AOP_TYPE(result) == AOP_CRY) {
2223         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2224         pic16_aopPut(AOP(result),"c",0);
2225     } else {
2226
2227         i = AOP_SIZE(result);
2228         while(i--) {
2229                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2230         }
2231         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2232         
2233 /*
2234         pic16_emitcode("clr","a  ; %d", __LINE__);
2235         pic16_emitcode("rlc","a");
2236         pic16_outAcc(result);
2237 */
2238     }
2239 }
2240
2241 /*-----------------------------------------------------------------*/
2242 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2243 /*-----------------------------------------------------------------*/
2244 void pic16_toBoolean(operand *oper)
2245 {
2246     int size = AOP_SIZE(oper) - 1;
2247     int offset = 1;
2248
2249     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2250
2251     if ( AOP_TYPE(oper) != AOP_ACC) {
2252       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2253     }
2254     while (size--) {
2255       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2256     }
2257 }
2258
2259
2260 #if !defined(GEN_Not)
2261 /*-----------------------------------------------------------------*/
2262 /* genNot - generate code for ! operation                          */
2263 /*-----------------------------------------------------------------*/
2264 static void pic16_genNot (iCode *ic)
2265 {
2266   symbol *tlbl;
2267   int size;
2268
2269   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2270   /* assign asmOps to operand & result */
2271   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2272   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2273
2274   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2275   /* if in bit space then a special case */
2276   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2277     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2278       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2279       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2280     } else {
2281       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2282       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2283       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2284     }
2285     goto release;
2286   }
2287
2288   size = AOP_SIZE(IC_LEFT(ic));
2289   if(size == 1) {
2290     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2291     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2292     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2293     goto release;
2294   }
2295   pic16_toBoolean(IC_LEFT(ic));
2296
2297   tlbl = newiTempLabel(NULL);
2298   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2299   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2300   pic16_outBitC(IC_RESULT(ic));
2301
2302  release:    
2303   /* release the aops */
2304   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2305   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2306 }
2307 #endif
2308
2309
2310 #if !defined(GEN_Cpl)
2311 /*-----------------------------------------------------------------*/
2312 /* genCpl - generate code for complement                           */
2313 /*-----------------------------------------------------------------*/
2314 static void pic16_genCpl (iCode *ic)
2315 {
2316     int offset = 0;
2317     int size ;
2318
2319
2320     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2321     /* assign asmOps to operand & result */
2322     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2323     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2324
2325     /* if both are in bit space then 
2326     a special case */
2327     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2328         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2329
2330         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2331         pic16_emitcode("cpl","c"); 
2332         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2333         goto release; 
2334     } 
2335
2336     size = AOP_SIZE(IC_RESULT(ic));
2337     while (size--) {
2338 /*
2339         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2340         MOVA(l);       
2341         pic16_emitcode("cpl","a");
2342         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2343 */
2344         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2345               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2346         } else {
2347                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2348                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2349         }
2350         offset++;
2351
2352     }
2353
2354
2355 release:
2356     /* release the aops */
2357     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2358     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2359 }
2360 #endif
2361
2362 /*-----------------------------------------------------------------*/
2363 /* genUminusFloat - unary minus for floating points                */
2364 /*-----------------------------------------------------------------*/
2365 static void genUminusFloat(operand *op,operand *result)
2366 {
2367     int size ,offset =0 ;
2368     char *l;
2369
2370     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2371     /* for this we just need to flip the 
2372     first it then copy the rest in place */
2373     size = AOP_SIZE(op) - 1;
2374     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2375
2376     MOVA(l);    
2377
2378     pic16_emitcode("cpl","acc.7");
2379     pic16_aopPut(AOP(result),"a",3);    
2380
2381     while(size--) {
2382         pic16_aopPut(AOP(result),
2383                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2384                offset);
2385         offset++;
2386     }          
2387 }
2388
2389 /*-----------------------------------------------------------------*/
2390 /* genUminus - unary minus code generation                         */
2391 /*-----------------------------------------------------------------*/
2392 static void genUminus (iCode *ic)
2393 {
2394   int size, i;
2395   sym_link *optype, *rtype;
2396
2397         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2398         
2399         /* assign asmops */
2400         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2401         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2402
2403         /* if both in bit space then special case */
2404         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2405                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2406
2407                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2408                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2409                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2410                 
2411                 goto release; 
2412         } 
2413
2414         optype = operandType(IC_LEFT(ic));
2415         rtype = operandType(IC_RESULT(ic));
2416
2417         /* if float then do float stuff */
2418         if (IS_FLOAT(optype)) {
2419                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2420                 goto release;
2421         }
2422
2423         /* otherwise subtract from zero by taking the 2's complement */
2424         size = AOP_SIZE(IC_LEFT(ic));
2425
2426         for(i=0; i<size; i++) {
2427                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2428                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2429                 else {
2430                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2431                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2432                 }
2433         }
2434
2435         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2436         for(i=1; i<size; i++) {
2437                 emitSKPNZ;
2438                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2439         }
2440
2441 release:
2442         /* release the aops */
2443         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2444         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2445 }
2446
2447 /*-----------------------------------------------------------------*/
2448 /* saveRegisters - will look for a call and save the registers     */
2449 /*-----------------------------------------------------------------*/
2450 static void saveRegisters(iCode *lic) 
2451 {
2452     int i;
2453     iCode *ic;
2454     bitVect *rsave;
2455     sym_link *dtype;
2456
2457     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2458     /* look for call */
2459     for (ic = lic ; ic ; ic = ic->next) 
2460         if (ic->op == CALL || ic->op == PCALL)
2461             break;
2462
2463     if (!ic) {
2464         fprintf(stderr,"found parameter push with no function call\n");
2465         return ;
2466     }
2467
2468     /* if the registers have been saved already then
2469     do nothing */
2470     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2471         return ;
2472
2473     /* find the registers in use at this time 
2474     and push them away to safety */
2475     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2476                           ic->rUsed);
2477
2478     ic->regsSaved = 1;
2479     if (options.useXstack) {
2480         if (bitVectBitValue(rsave,R0_IDX))
2481             pic16_emitcode("mov","b,r0");
2482         pic16_emitcode("mov","r0,%s",spname);
2483         for (i = 0 ; i < pic16_nRegs ; i++) {
2484             if (bitVectBitValue(rsave,i)) {
2485                 if (i == R0_IDX)
2486                     pic16_emitcode("mov","a,b");
2487                 else
2488                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2489                 pic16_emitcode("movx","@r0,a");
2490                 pic16_emitcode("inc","r0");
2491             }
2492         }
2493         pic16_emitcode("mov","%s,r0",spname);
2494         if (bitVectBitValue(rsave,R0_IDX))
2495             pic16_emitcode("mov","r0,b");           
2496     }// else
2497     //for (i = 0 ; i < pic16_nRegs ; i++) {
2498     //    if (bitVectBitValue(rsave,i))
2499     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2500     //}
2501
2502     dtype = operandType(IC_LEFT(ic));
2503     if (currFunc && dtype && 
2504         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2505         IFFUNC_ISISR(currFunc->type) &&
2506         !ic->bankSaved) 
2507
2508         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2509
2510 }
2511 /*-----------------------------------------------------------------*/
2512 /* unsaveRegisters - pop the pushed registers                      */
2513 /*-----------------------------------------------------------------*/
2514 static void unsaveRegisters (iCode *ic)
2515 {
2516     int i;
2517     bitVect *rsave;
2518
2519     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2520     /* find the registers in use at this time 
2521     and push them away to safety */
2522     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2523                           ic->rUsed);
2524     
2525     if (options.useXstack) {
2526         pic16_emitcode("mov","r0,%s",spname);   
2527         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2528             if (bitVectBitValue(rsave,i)) {
2529                 pic16_emitcode("dec","r0");
2530                 pic16_emitcode("movx","a,@r0");
2531                 if (i == R0_IDX)
2532                     pic16_emitcode("mov","b,a");
2533                 else
2534                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2535             }       
2536
2537         }
2538         pic16_emitcode("mov","%s,r0",spname);
2539         if (bitVectBitValue(rsave,R0_IDX))
2540             pic16_emitcode("mov","r0,b");
2541     } //else
2542     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2543     //    if (bitVectBitValue(rsave,i))
2544     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2545     //}
2546
2547 }  
2548
2549 #if 0  // patch 14
2550 /*-----------------------------------------------------------------*/
2551 /* pushSide -                                                      */
2552 /*-----------------------------------------------------------------*/
2553 static void pushSide(operand * oper, int size)
2554 {
2555         int offset = 0;
2556     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2557         while (size--) {
2558                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2559                 if (AOP_TYPE(oper) != AOP_REG &&
2560                     AOP_TYPE(oper) != AOP_DIR &&
2561                     strcmp(l,"a") ) {
2562                         pic16_emitcode("mov","a,%s",l);
2563                         pic16_emitcode("push","acc");
2564                 } else
2565                         pic16_emitcode("push","%s",l);
2566         }
2567 }
2568 #endif // patch 14
2569
2570 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2571 {
2572 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2573
2574         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2575                 pic16_emitpcode(POC_MOVFW, src);
2576                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2577         } else {
2578                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2579                         src, pic16_popGet(AOP(op), offset)));
2580         }
2581 }
2582
2583
2584 /*-----------------------------------------------------------------*/
2585 /* assignResultValue - assign results to oper, rescall==1 is       */
2586 /*                     called from genCall() or genPCall()         */
2587 /*-----------------------------------------------------------------*/
2588 static void assignResultValue(operand * oper, int rescall)
2589 {
2590   int size = AOP_SIZE(oper);
2591
2592         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2593         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2594
2595         if(rescall) {
2596                 /* assign result from a call/pcall function() */
2597                 
2598                 /* function results are stored in a special order,
2599                  * see top of file with Function return policy, or manual */
2600
2601                 if(size <= 4) {
2602                         /* 8-bits, result in WREG */
2603                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2604                         
2605                         if(size>1) {
2606                                 /* 16-bits, result in PRODL:WREG */
2607                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2608                         }
2609                         
2610                         if(size>2) {
2611                                 /* 24-bits, result in PRODH:PRODL:WREG */
2612                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2613                         }
2614                         
2615                         if(size>3) {
2616                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2617                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2618                         }
2619                 } else {
2620                         /* >32-bits, result on stack, and FSR0 points to beginning.
2621                          * Fix stack when done */
2622                          /* FIXME FIXME */
2623                         while (size--) {
2624 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2625 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2626                 
2627                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2628                                 GpsuedoStkPtr++;
2629                         }
2630                         
2631                         /* fix stack */
2632                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2633                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2634                         if(STACK_MODEL_LARGE) {
2635                                 emitSKPNC;
2636                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2637                         }
2638                 }                       
2639         } else {        
2640                 if(!GpsuedoStkPtr) {
2641 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2642                         /* The last byte in the assignment is in W */
2643                         size--;
2644                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2645                         GpsuedoStkPtr++;
2646                 }
2647
2648                 while (size--) {
2649 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2650 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2651                 
2652                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2653                         GpsuedoStkPtr++;
2654
2655 #if 0
2656 #if STACK_SUPPORT
2657                 if(!USE_STACK)
2658                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2659 #else
2660                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2661 #endif
2662 #endif
2663
2664                 }
2665         }
2666                 
2667 }
2668
2669
2670 /*-----------------------------------------------------------------*/
2671 /* genIpush - genrate code for pushing this gets a little complex  */
2672 /*-----------------------------------------------------------------*/
2673 static void genIpush (iCode *ic)
2674 {
2675   int size, offset=0;
2676
2677   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2678
2679
2680         pic16_aopOp(IC_LEFT(ic), ic, FALSE);
2681         
2682
2683         size = AOP_SIZE( IC_LEFT(ic) );
2684         
2685         while(size--) {
2686                 mov2w( AOP(IC_LEFT(ic)), offset );
2687                 pushw();
2688                 offset++;
2689         }
2690         
2691 #if 0
2692     int size, offset = 0 ;
2693     char *l;
2694
2695
2696     /* if this is not a parm push : ie. it is spill push 
2697     and spill push is always done on the local stack */
2698     if (!ic->parmPush) {
2699
2700         /* and the item is spilt then do nothing */
2701         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2702             return ;
2703
2704         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2705         size = AOP_SIZE(IC_LEFT(ic));
2706         /* push it on the stack */
2707         while(size--) {
2708             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2709             if (*l == '#') {
2710                 MOVA(l);
2711                 l = "acc";
2712             }
2713             pic16_emitcode("push","%s",l);
2714         }
2715         return ;        
2716     }
2717
2718     /* this is a paramter push: in this case we call
2719     the routine to find the call and save those
2720     registers that need to be saved */   
2721     saveRegisters(ic);
2722
2723     /* then do the push */
2724     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2725
2726
2727         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2728     size = AOP_SIZE(IC_LEFT(ic));
2729
2730     while (size--) {
2731         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2732         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2733             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2734             strcmp(l,"a") ) {
2735             pic16_emitcode("mov","a,%s",l);
2736             pic16_emitcode("push","acc");
2737         } else
2738             pic16_emitcode("push","%s",l);
2739     }       
2740
2741     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2742 #endif
2743 }
2744
2745 /*-----------------------------------------------------------------*/
2746 /* genIpop - recover the registers: can happen only for spilling   */
2747 /*-----------------------------------------------------------------*/
2748 static void genIpop (iCode *ic)
2749 {
2750   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2751 #if 0
2752     int size,offset ;
2753
2754
2755     /* if the temp was not pushed then */
2756     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2757         return ;
2758
2759     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2760     size = AOP_SIZE(IC_LEFT(ic));
2761     offset = (size-1);
2762     while (size--) 
2763         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2764                                    FALSE,TRUE));
2765
2766     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2767 #endif
2768 }
2769
2770 /*-----------------------------------------------------------------*/
2771 /* unsaverbank - restores the resgister bank from stack            */
2772 /*-----------------------------------------------------------------*/
2773 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2774 {
2775   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2776 #if 0
2777     int i;
2778     asmop *aop ;
2779     regs *r = NULL;
2780
2781     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2782     if (popPsw) {
2783         if (options.useXstack) {
2784             aop = newAsmop(0);
2785             r = getFreePtr(ic,&aop,FALSE);
2786             
2787             
2788             pic16_emitcode("mov","%s,_spx",r->name);
2789             pic16_emitcode("movx","a,@%s",r->name);
2790             pic16_emitcode("mov","psw,a");
2791             pic16_emitcode("dec","%s",r->name);
2792             
2793         }else
2794             pic16_emitcode ("pop","psw");
2795     }
2796
2797     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2798         if (options.useXstack) {       
2799             pic16_emitcode("movx","a,@%s",r->name);
2800             //pic16_emitcode("mov","(%s+%d),a",
2801             //       regspic16[i].base,8*bank+regspic16[i].offset);
2802             pic16_emitcode("dec","%s",r->name);
2803
2804         } else 
2805           pic16_emitcode("pop",""); //"(%s+%d)",
2806         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2807     }
2808
2809     if (options.useXstack) {
2810
2811         pic16_emitcode("mov","_spx,%s",r->name);
2812         pic16_freeAsmop(NULL,aop,ic,TRUE);
2813
2814     }
2815 #endif 
2816 }
2817
2818 /*-----------------------------------------------------------------*/
2819 /* saverbank - saves an entire register bank on the stack          */
2820 /*-----------------------------------------------------------------*/
2821 static void saverbank (int bank, iCode *ic, bool pushPsw)
2822 {
2823   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2824 #if 0
2825     int i;
2826     asmop *aop ;
2827     regs *r = NULL;
2828
2829     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2830     if (options.useXstack) {
2831
2832         aop = newAsmop(0);
2833         r = getFreePtr(ic,&aop,FALSE);  
2834         pic16_emitcode("mov","%s,_spx",r->name);
2835
2836     }
2837
2838     for (i = 0 ; i < pic16_nRegs ;i++) {
2839         if (options.useXstack) {
2840             pic16_emitcode("inc","%s",r->name);
2841             //pic16_emitcode("mov","a,(%s+%d)",
2842             //         regspic16[i].base,8*bank+regspic16[i].offset);
2843             pic16_emitcode("movx","@%s,a",r->name);           
2844         } else 
2845           pic16_emitcode("push","");// "(%s+%d)",
2846                      //regspic16[i].base,8*bank+regspic16[i].offset);
2847     }
2848     
2849     if (pushPsw) {
2850         if (options.useXstack) {
2851             pic16_emitcode("mov","a,psw");
2852             pic16_emitcode("movx","@%s,a",r->name);     
2853             pic16_emitcode("inc","%s",r->name);
2854             pic16_emitcode("mov","_spx,%s",r->name);       
2855             pic16_freeAsmop (NULL,aop,ic,TRUE);
2856             
2857         } else
2858             pic16_emitcode("push","psw");
2859         
2860         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2861     }
2862     ic->bankSaved = 1;
2863 #endif
2864 }
2865
2866
2867
2868 /*-----------------------------------------------------------------*/
2869 /* genCall - generates a call statement                            */
2870 /*-----------------------------------------------------------------*/
2871 static void genCall (iCode *ic)
2872 {
2873   sym_link *dtype;   
2874   int stackParms=0;
2875   
2876         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2877
2878         /* if caller saves & we have not saved then */
2879         if (!ic->regsSaved)
2880                 saveRegisters(ic);
2881
2882         /* if we are calling a function that is not using
2883          * the same register bank then we need to save the
2884          * destination registers on the stack */
2885         dtype = operandType(IC_LEFT(ic));
2886         if (currFunc && dtype && 
2887                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2888                 IFFUNC_ISISR(currFunc->type) &&
2889                 !ic->bankSaved) 
2890
2891                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2892
2893
2894         /* initialise stackParms for IPUSH pushes */
2895 //      stackParms = psuedoStkPtr;
2896 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
2897
2898         /* if send set is not empty the assign */
2899         if (_G.sendSet) {
2900           iCode *sic;
2901
2902                 /* For the Pic port, there is no data stack.
2903                  * So parameters passed to functions are stored
2904                  * in registers. (The pCode optimizer will get
2905                  * rid of most of these :). */
2906
2907           int psuedoStkPtr=-1; 
2908           int firstTimeThruLoop = 1;
2909
2910                 _G.sendSet = reverseSet(_G.sendSet);
2911
2912                 /* First figure how many parameters are getting passed */
2913                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2914                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2915                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2916                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2917                 }
2918
2919                 stackParms = psuedoStkPtr;
2920
2921                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2922                   int size, offset = 0;
2923
2924                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2925                         size = AOP_SIZE(IC_LEFT(sic));
2926
2927                         while (size--) {
2928                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2929                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2930                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2931
2932                                 if(!firstTimeThruLoop) {
2933                                         /* If this is not the first time we've been through the loop
2934                                          * then we need to save the parameter in a temporary
2935                                          * register. The last byte of the last parameter is
2936                                          * passed in W. */
2937
2938                                         pushw();
2939                                         --psuedoStkPtr;         // sanity check
2940                                 }
2941                         
2942                                 firstTimeThruLoop=0;
2943
2944                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2945                                 offset++;
2946                         }
2947                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2948                 }
2949                 _G.sendSet = NULL;
2950         }
2951
2952         /* make the call */
2953         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2954                         OP_SYMBOL(IC_LEFT(ic))->rname :
2955                         OP_SYMBOL(IC_LEFT(ic))->name));
2956
2957         GpsuedoStkPtr=0;
2958         /* if we need assign a result value */
2959         if ((IS_ITEMP(IC_RESULT(ic)) && 
2960                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2961                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2962                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2963
2964                 _G.accInUse++;
2965                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2966                 _G.accInUse--;
2967
2968                 assignResultValue(IC_RESULT(ic), 1);
2969
2970                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2971                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2972                 
2973                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2974         }
2975
2976         if(!stackParms && ic->parmBytes) {
2977                 stackParms = ic->parmBytes;
2978         }
2979         
2980         if(stackParms>0) {
2981                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2982                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2983                 if(STACK_MODEL_LARGE) {
2984                         emitSKPNC;
2985                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2986                 }
2987         }
2988
2989         /* adjust the stack for parameters if required */
2990 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2991 #if 0
2992         if (ic->parmBytes) {
2993           int i;
2994
2995                 if (ic->parmBytes > 3) {
2996                         pic16_emitcode("mov","a,%s",spname);
2997                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2998                         pic16_emitcode("mov","%s,a",spname);
2999                 } else 
3000                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3001                                 pic16_emitcode("dec","%s",spname);
3002         }
3003 #endif
3004
3005 #if 0
3006         /* if register bank was saved then pop them */
3007         if (ic->bankSaved)
3008                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3009
3010         /* if we hade saved some registers then unsave them */
3011         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3012                 unsaveRegisters (ic);
3013 #endif
3014 }
3015
3016
3017
3018 /*-----------------------------------------------------------------*/   // patch 14
3019 /* genPcall - generates a call by pointer statement                */
3020 /*-----------------------------------------------------------------*/
3021
3022 // new version, created from genCall
3023
3024 static void genPcall (iCode *ic)
3025 {
3026   sym_link *dtype;   
3027   int stackParms=0;
3028   symbol *retlbl = newiTempLabel(NULL);
3029   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3030   
3031         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3032
3033         /* if caller saves & we have not saved then */
3034         if (!ic->regsSaved)
3035                 saveRegisters(ic);
3036
3037         /* if we are calling a function that is not using
3038          * the same register bank then we need to save the
3039          * destination registers on the stack */
3040         dtype = operandType(IC_LEFT(ic));
3041         if (currFunc && dtype && 
3042                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
3043                 IFFUNC_ISISR(currFunc->type) &&
3044                 !ic->bankSaved) 
3045
3046                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3047
3048         /* if send set is not empty the assign */
3049         if (_G.sendSet) {
3050           iCode *sic;
3051
3052                 /* For the Pic port, there is no data stack.
3053                  * So parameters passed to functions are stored
3054                  * in registers. (The pCode optimizer will get
3055                  * rid of most of these :). */
3056
3057           int psuedoStkPtr=-1; 
3058           int firstTimeThruLoop = 1;
3059
3060                 _G.sendSet = reverseSet(_G.sendSet);
3061
3062                 /* First figure how many parameters are getting passed */
3063                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3064                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3065                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
3066                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
3067                 }
3068
3069                 stackParms = psuedoStkPtr;
3070
3071                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3072                   int size, offset = 0;
3073
3074                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3075                         size = AOP_SIZE(IC_LEFT(sic));
3076
3077                         while (size--) {
3078                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3079                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3080                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3081
3082                                 if(!firstTimeThruLoop) {
3083                                         /* If this is not the first time we've been through the loop
3084                                          * then we need to save the parameter in a temporary
3085                                          * register. The last byte of the last parameter is
3086                                          * passed in W. */
3087
3088                                         pushw();
3089                                         --psuedoStkPtr;         // sanity check
3090                                 }
3091                         
3092                                 firstTimeThruLoop=0;
3093
3094                                 mov2w (AOP(IC_LEFT(sic)),  offset);
3095                                 offset++;
3096                         }
3097                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3098                 }
3099                 _G.sendSet = NULL;
3100         }
3101
3102         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3103
3104         // push return address
3105         // push $ on return stack, then replace with retlbl
3106
3107         pic16_emitpcodeNULLop(POC_PUSH);
3108
3109         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3110         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3111         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3112         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3113         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3114         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3115
3116         /* make the call by writing the pointer into pc */
3117         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3118         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3119
3120         // note: MOVFF to PCL not allowed
3121         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3122         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3123
3124
3125 //      pic16_emitpcode(POC_GOTO, pic16_popGetLabel(retlbl->key));
3126 //      pic16_emitpcodeNULLop(POC_NOP);
3127 //      pic16_emitpcodeNULLop(POC_NOP);
3128
3129         /* return address is here: (X) */
3130         pic16_emitpLabelFORCE(retlbl->key);
3131
3132 //      pic16_emitpcodeNULLop(POC_NOP);
3133
3134         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3135
3136         GpsuedoStkPtr=0;
3137         /* if we need assign a result value */
3138         if ((IS_ITEMP(IC_RESULT(ic)) && 
3139                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3140                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
3141                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3142
3143                 _G.accInUse++;
3144                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3145                 _G.accInUse--;
3146
3147                 assignResultValue(IC_RESULT(ic), 1);
3148
3149                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3150                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3151                 
3152                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3153         }
3154
3155         if(stackParms>0) {
3156                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3157                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3158                 if(STACK_MODEL_LARGE) {
3159                         emitSKPNC;
3160                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3161                 }
3162         }
3163
3164         /* adjust the stack for parameters if required */
3165 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3166
3167         if (ic->parmBytes) {
3168           int i;
3169
3170                 if (ic->parmBytes > 3) {
3171                         pic16_emitcode("mov","a,%s",spname);
3172                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3173                         pic16_emitcode("mov","%s,a",spname);
3174                 } else 
3175                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3176                                 pic16_emitcode("dec","%s",spname);
3177         }
3178
3179         /* if register bank was saved then pop them */
3180         if (ic->bankSaved)
3181                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3182
3183         /* if we hade saved some registers then unsave them */
3184         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3185                 unsaveRegisters (ic);
3186 }
3187
3188
3189 #if 0                                                                           // patch 14
3190 // old version, kept for reference
3191
3192 /*-----------------------------------------------------------------*/
3193 /* genPcall - generates a call by pointer statement                */
3194 /*-----------------------------------------------------------------*/
3195 static void genPcall (iCode *ic)
3196 {
3197     sym_link *dtype;
3198     symbol *rlbl = newiTempLabel(NULL);
3199
3200
3201     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3202     /* if caller saves & we have not saved then */
3203     if (!ic->regsSaved)
3204         saveRegisters(ic);
3205
3206     /* if we are calling a function that is not using
3207     the same register bank then we need to save the
3208     destination registers on the stack */
3209     dtype = operandType(IC_LEFT(ic));
3210     if (currFunc && dtype && 
3211         IFFUNC_ISISR(currFunc->type) &&
3212         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3213         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3214
3215
3216     /* push the return address on to the stack */
3217     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3218     pic16_emitcode("push","acc");    
3219     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3220     pic16_emitcode("push","acc");
3221     
3222     if (options.model == MODEL_FLAT24)
3223     {
3224         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3225         pic16_emitcode("push","acc");    
3226     }
3227
3228     /* now push the calling address */
3229     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3230
3231     pushSide(IC_LEFT(ic), FPTRSIZE);
3232
3233     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3234
3235     /* if send set is not empty the assign */
3236     if (_G.sendSet) {
3237         iCode *sic ;
3238
3239         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3240              sic = setNextItem(_G.sendSet)) {
3241             int size, offset = 0;
3242             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3243             size = AOP_SIZE(IC_LEFT(sic));
3244             while (size--) {
3245                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3246                                 FALSE,FALSE);
3247                 if (strcmp(l,fReturn[offset]))
3248                     pic16_emitcode("mov","%s,%s",
3249                              fReturn[offset],
3250                              l);
3251                 offset++;
3252             }
3253             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3254         }
3255         _G.sendSet = NULL;
3256     }
3257
3258     pic16_emitcode("ret","");
3259     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3260
3261
3262     /* if we need assign a result value */
3263     if ((IS_ITEMP(IC_RESULT(ic)) &&
3264          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3265           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3266         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3267
3268         _G.accInUse++;
3269         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3270         _G.accInUse--;
3271         
3272         assignResultValue(IC_RESULT(ic), 1);
3273
3274         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3275     }
3276
3277     /* adjust the stack for parameters if 
3278     required */
3279     if (ic->parmBytes) {
3280         int i;
3281         if (ic->parmBytes > 3) {
3282             pic16_emitcode("mov","a,%s",spname);
3283             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3284             pic16_emitcode("mov","%s,a",spname);
3285         } else 
3286             for ( i = 0 ; i <  ic->parmBytes ;i++)
3287                 pic16_emitcode("dec","%s",spname);
3288
3289     }
3290
3291     /* if register bank was saved then unsave them */
3292     if (currFunc && dtype && 
3293         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3294         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3295
3296     /* if we hade saved some registers then
3297     unsave them */
3298     if (ic->regsSaved)
3299         unsaveRegisters (ic);
3300
3301 }
3302 #endif                                                                          // patch 14
3303
3304
3305 /*-----------------------------------------------------------------*/
3306 /* resultRemat - result  is rematerializable                       */
3307 /*-----------------------------------------------------------------*/
3308 static int resultRemat (iCode *ic)
3309 {
3310   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3311   if (SKIP_IC(ic) || ic->op == IFX)
3312     return 0;
3313
3314   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3315     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3316     if (sym->remat && !POINTER_SET(ic)) 
3317       return 1;
3318   }
3319
3320   return 0;
3321 }
3322
3323 #if defined(__BORLANDC__) || defined(_MSC_VER)
3324 #define STRCASECMP stricmp
3325 #else
3326 #define STRCASECMP strcasecmp
3327 #endif
3328
3329 #if 0
3330 /*-----------------------------------------------------------------*/
3331 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3332 /*-----------------------------------------------------------------*/
3333 static bool inExcludeList(char *s)
3334 {
3335   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3336     int i =0;
3337     
3338     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3339     if (options.excludeRegs[i] &&
3340     STRCASECMP(options.excludeRegs[i],"none") == 0)
3341         return FALSE ;
3342
3343     for ( i = 0 ; options.excludeRegs[i]; i++) {
3344         if (options.excludeRegs[i] &&
3345         STRCASECMP(s,options.excludeRegs[i]) == 0)
3346             return TRUE;
3347     }
3348     return FALSE ;
3349 }
3350 #endif
3351
3352 /*-----------------------------------------------------------------*/
3353 /* genFunction - generated code for function entry                 */
3354 /*-----------------------------------------------------------------*/
3355 static void genFunction (iCode *ic)
3356 {
3357   symbol *sym;
3358   sym_link *ftype;
3359   
3360         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3361
3362         pic16_labelOffset += (max_key+4);
3363         max_key=0;
3364         GpsuedoStkPtr=0;
3365         _G.nRegsSaved = 0;
3366
3367         ftype = operandType(IC_LEFT(ic));
3368         sym = OP_SYMBOL(IC_LEFT(ic));
3369
3370         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3371                 /* create an absolute section at the interrupt vector:
3372                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3373           symbol *asym;
3374           char asymname[128];
3375           pBlock *apb;
3376
3377                 {
3378                   int i, found=-1;
3379
3380                         sym = OP_SYMBOL( IC_LEFT(ic));
3381                         for(i=0;i<=2;i++) {
3382                                 if(interrupts[i]->name
3383                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3384                                         found = i;
3385                                         break;
3386                                 }
3387                         }
3388                         
3389                         if(found == -1) {
3390                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3391                                         __FILE__, __LINE__, sym->name);
3392                                 assert( 0 );
3393                         }
3394                         _G.interruptvector = found;
3395                 }
3396
3397                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3398                 asym = newSymbol(asymname, 0);
3399
3400                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3401                 pic16_addpBlock( apb );
3402
3403                 pic16_addpCode2pBlock(apb,
3404                         pic16_newpCodeCharP(";-----------------------------------------"));
3405
3406
3407                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3408
3409                 pic16_addpCode2pBlock(apb,
3410                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3411                 
3412                 /* mark the end of this tiny function */
3413                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3414
3415                 {
3416                   absSym *abSym;
3417
3418                         abSym = Safe_calloc(1, sizeof(absSym));
3419                         abSym->name = Safe_strdup( asymname );
3420
3421                         switch( _G.interruptvector ) {
3422                                 case 0: abSym->address = 0x000000; break;
3423                                 case 1: abSym->address = 0x000008; break;
3424                                 case 2: abSym->address = 0x000018; break;
3425                         }
3426
3427                         /* relocate interrupt vectors if needed */
3428                         abSym->address += pic16_options.ivt_loc;
3429
3430                         addSet(&absSymSet, abSym);
3431                 }
3432         }
3433
3434
3435         /* create the function header */
3436         pic16_emitcode(";","-----------------------------------------");
3437         pic16_emitcode(";"," function %s",sym->name);
3438         pic16_emitcode(";","-----------------------------------------");
3439
3440         pic16_emitcode("","%s:",sym->rname);
3441         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3442
3443
3444         {
3445           absSym *ab;
3446
3447                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3448                         if(!strcmp(ab->name, sym->name)) {
3449                                 pic16_pBlockConvert2Absolute(pb);
3450                                 break;
3451                         }
3452
3453         }
3454
3455
3456         if(IFFUNC_ISNAKED(ftype)) {
3457                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3458                 return;
3459         }
3460         
3461         /* if critical function then turn interrupts off */
3462         if (IFFUNC_ISCRITICAL(ftype))
3463                 pic16_emitcode("clr","ea");
3464
3465         /* if this is an interrupt service routine then
3466          * save acc, b, dpl, dph  */
3467         if (IFFUNC_ISISR(sym->type)) {
3468           int i;
3469                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3470                 if(!(_G.interruptvector == 1)) {
3471
3472                         /* do not save WREG,STATUS,BSR for high priority interrupts
3473                          * because they are stored in the hardware shadow registers already */
3474                          
3475                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3476                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3477                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3478                 }
3479
3480                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3481                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3482                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3483                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3484
3485 //                pic16_pBlockConvert2ISR(pb);
3486                 
3487                 /* if any registers used */
3488                 if (sym->regsUsed) {
3489                         /* save the registers used */
3490                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3491                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3492                                 if (bitVectBitValue(sym->regsUsed,i)) {
3493 #if 0
3494                                         fprintf(stderr, "%s:%d function %s uses register %s\n",
3495                                                         __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3496                                                         pic16_regWithIdx(i)->name);
3497 #endif
3498
3499                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3500                                         _G.nRegsSaved++;
3501
3502                                         if(!pic16_regWithIdx(i)->wasUsed) {
3503                                                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3504                                                         __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3505
3506                                                 pic16_regWithIdx(i)->wasUsed = 1;
3507                                         }
3508                                 }
3509                         }
3510                 }
3511         } else {
3512                 /* emit code to setup stack frame if user enabled,
3513                  * and function is not main() */
3514          
3515 //              fprintf(stderr, "function name: %s\n", sym->name);
3516                 if(strcmp(sym->name, "main")) {
3517                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3518                         /* setup the stack frame */
3519                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3520                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3521                                 if(STACK_MODEL_LARGE)
3522                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3523                         }
3524                 }
3525
3526                 /* if callee-save to be used for this function
3527                 * then save the registers being used in this function */
3528 //              if (IFFUNC_CALLEESAVES(sym->type))
3529                 {
3530                   int i;
3531
3532 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3533
3534 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3535
3536                         /* if any registers used */
3537                         if (sym->regsUsed) {
3538                                 /* save the registers used */
3539                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3540                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3541                                         if (bitVectBitValue(sym->regsUsed,i)) {
3542
3543 #if 0
3544                                                 fprintf(stderr, "%s:%d function %s uses register %s (wasUsed: %d, %p)\n",
3545                                                                 __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3546                                                                 pic16_regWithIdx(i)->name,
3547                                                                 pic16_regWithIdx(i)->wasUsed,
3548                                                                 pic16_regWithIdx(i));
3549 #endif
3550
3551                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3552
3553 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3554 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3555 //                                                      &pic16_pc_postdec1, 0));
3556
3557                                                 _G.nRegsSaved++;
3558
3559                                                 if(!pic16_regWithIdx(i)->wasUsed) {
3560                                                         fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3561                                                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3562
3563                                                         pic16_regWithIdx(i)->wasUsed = 1;
3564                                                 }
3565                                         
3566                                         }
3567                                 }
3568                         }
3569                 }
3570         }
3571
3572
3573         
3574 #if 0
3575         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3576
3577                 if (options.useXstack) {
3578                         pic16_emitcode("mov","r0,%s",spname);
3579                         pic16_emitcode("mov","a,_bp");
3580                         pic16_emitcode("movx","@r0,a");
3581                         pic16_emitcode("inc","%s",spname);
3582                 } else {
3583                         /* set up the stack */
3584                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3585                 }
3586                 pic16_emitcode ("mov","_bp,%s",spname);
3587         }
3588 #endif
3589         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3590
3591         /* adjust the stack for the function */
3592         if (sym->stack) {
3593           int i = sym->stack;
3594
3595                 if (i > 127 ) 
3596                         werror(W_STACK_OVERFLOW,sym->name);
3597
3598                 if (i > 3 && sym->recvSize < 4) {              
3599                         pic16_emitcode ("mov","a,sp");
3600                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3601                         pic16_emitcode ("mov","sp,a");
3602                 } else
3603                         while(i--)
3604                                 pic16_emitcode("inc","sp");
3605         }
3606
3607         if (sym->xstack) {
3608                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3609
3610                 pic16_emitcode ("mov","a,_spx");
3611                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3612                 pic16_emitcode ("mov","_spx,a");
3613         }
3614     
3615 }
3616
3617 /*-----------------------------------------------------------------*/
3618 /* genEndFunction - generates epilogue for functions               */
3619 /*-----------------------------------------------------------------*/
3620 static void genEndFunction (iCode *ic)
3621 {
3622     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3623
3624     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3625
3626     if(IFFUNC_ISNAKED(sym->type)) {
3627         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3628         return;
3629     }
3630
3631     /* add code for ISCRITICAL */
3632
3633 #if 0
3634     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3635     {
3636         pic16_emitcode ("mov","%s,_bp",spname);
3637     }
3638 #endif
3639
3640     /* if use external stack but some variables were
3641     added to the local stack then decrement the
3642     local stack */
3643     if (options.useXstack && sym->stack) {      
3644         pic16_emitcode("mov","a,sp");
3645         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3646         pic16_emitcode("mov","sp,a");
3647     }
3648
3649
3650 #if 0
3651     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3652         if (options.useXstack) {
3653             pic16_emitcode("mov","r0,%s",spname);
3654             pic16_emitcode("movx","a,@r0");
3655             pic16_emitcode("mov","_bp,a");
3656             pic16_emitcode("dec","%s",spname);
3657         }
3658         else
3659         {
3660             pic16_emitcode ("pop","_bp");
3661         }
3662     }
3663 #endif
3664
3665         if (IFFUNC_ISISR(sym->type)) {
3666                 /* now we need to restore the registers */
3667                 /* if any registers used */
3668                 if (sym->regsUsed) {
3669                   int i;
3670
3671                         /* restore registers used */
3672                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3673                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3674                                 if (bitVectBitValue(sym->regsUsed,i)) {
3675
3676 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3677 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3678 //                                                      pic16_regWithIdx(i)->name);
3679
3680                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3681
3682 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3683 //                                                      &pic16_pc_preinc1,
3684 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3685
3686                                 }
3687                         }
3688                 }
3689         
3690                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3691                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3692                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3693                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3694
3695                 if(!(_G.interruptvector == 1)) {
3696                         /* do not restore interrupt vector for WREG,STATUS,BSR
3697                          * for high priority interrupt, see genFunction */
3698                          
3699                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3700                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3701                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3702                 }
3703         
3704                 _G.interruptvector = 0;         /* sanity check */
3705
3706 //              pic16_pBlockConvert2ISR(pb);
3707
3708
3709                 /* if debug then send end of function */
3710 /*      if (options.debug && currFunc)  */
3711                 if (currFunc) {
3712                         debugFile->writeEndFunction (currFunc, ic, 1);
3713                 }
3714         
3715                 pic16_emitpcodeNULLop(POC_RETFIE);
3716         } else {
3717                 if (IFFUNC_ISCRITICAL(sym->type))
3718                         pic16_emitcode("setb","ea");
3719         
3720
3721 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3722
3723                 /* if any registers used */
3724                 if (sym->regsUsed) {
3725                   int i;
3726                         /* save the registers used */
3727                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3728                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3729                                 if (bitVectBitValue(sym->regsUsed,i)) {
3730         
3731 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3732 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3733 //                                                      pic16_regWithIdx(i)->name);
3734         
3735                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3736                                         
3737 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3738 //                                              &pic16_pc_preinc1,
3739 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3740
3741                                         _G.nRegsSaved--;
3742                                 }
3743                         }
3744                 }
3745         
3746 //              pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3747                 /* if debug then send end of function */
3748                 if (currFunc) {
3749                         debugFile->writeEndFunction (currFunc, ic, 1);
3750                 }
3751
3752                 /* insert code to restore stack frame, if user enabled it
3753                  * and function is not main() */
3754          
3755
3756                 if(strcmp(sym->name, "main")) {
3757                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3758                                 /* restore stack frame */
3759                                 if(STACK_MODEL_LARGE)
3760                                         pic16_emitpcode(POC_MOVFF,
3761                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3762                                 pic16_emitpcode(POC_MOVFF,
3763                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3764                         }
3765                 }
3766
3767                 pic16_emitcode ("return","");
3768                 pic16_emitpcodeNULLop(POC_RETURN);
3769
3770                 /* Mark the end of a function */
3771                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3772         }
3773
3774 }
3775
3776
3777 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3778 {
3779
3780         if(is_LitOp(op)) {
3781                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3782
3783                 if(dest->type != PO_WREG)
3784                         pic16_emitpcode(POC_MOVWF, dest);
3785         } else {
3786                 if(dest->type == PO_WREG && (offset == 0)) {
3787                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3788                         return;
3789                 }
3790                 
3791                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3792                         pic16_popGet(AOP(op), offset), dest));
3793         }
3794 }
3795
3796 /*-----------------------------------------------------------------*/
3797 /* genRet - generate code for return statement                     */
3798 /*-----------------------------------------------------------------*/
3799 static void genRet (iCode *ic)
3800 {
3801   int size;
3802   operand *left;
3803
3804         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3805         /* if we have no return value then
3806          * just generate the "ret" */
3807         
3808         if (!IC_LEFT(ic)) 
3809                 goto jumpret;       
3810     
3811         /* we have something to return then
3812          * move the return value into place */
3813         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3814         size = AOP_SIZE(IC_LEFT(ic));
3815
3816         if(size <= 4) {
3817                 if(size>3) {
3818                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3819 //                      pic16_emitpcode(POC_MOVFF,
3820 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3821                 }
3822                 if(size>2) {
3823                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3824 //                      pic16_emitpcode(POC_MOVFF,
3825 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3826                 }
3827                 if(size>1) {
3828                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3829 //                      pic16_emitpcode(POC_MOVFF,
3830 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3831                 }
3832
3833 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3834
3835                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3836 //              pic16_emitpcode(POC_MOVFF,
3837 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3838
3839         } else {
3840                 /* >32-bits, setup stack and FSR0 */
3841                 while (size--) {
3842 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3843 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3844
3845                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3846
3847 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3848                         GpsuedoStkPtr++;
3849                 }
3850                         
3851                 /* setup FSR0 */
3852                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3853                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3854
3855                 if(STACK_MODEL_LARGE) {
3856                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3857                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3858                 } else {
3859                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3860                 }
3861         }
3862                                 
3863 #if 0
3864         /* old code, left here for reference -- VR */    
3865         while (size--) {
3866           char *l ;
3867
3868                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3869                         /* #NOCHANGE */
3870                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3871                         pic16_emitpcomment("push %s",l);
3872                         pushed++;
3873                 } else {
3874                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3875                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3876                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3877                         
3878                         if (strcmp(fReturn[offset],l)) {
3879                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3880                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3881                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3882                                 } else {
3883                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3884                                 }
3885                                 
3886                                 if(size) {
3887                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3888                                 }
3889                                 offset++;
3890                         }
3891                 }
3892         }    
3893
3894         if (pushed) {
3895                 while(pushed) {
3896                         pushed--;
3897                         if (strcmp(fReturn[pushed],"a"))
3898                                 pic16_emitcode("pop",fReturn[pushed]);
3899                         else
3900                                 pic16_emitcode("pop","acc");
3901                 }
3902         }
3903 #endif
3904
3905
3906         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3907     
3908 jumpret:
3909         /* generate a jump to the return label
3910          * if the next is not the return statement */
3911         if (!(ic->next && ic->next->op == LABEL
3912                 && IC_LABEL(ic->next) == returnLabel)) {
3913         
3914                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3915                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
3916         }
3917 }
3918
3919 /*-----------------------------------------------------------------*/
3920 /* genLabel - generates a label                                    */
3921 /*-----------------------------------------------------------------*/
3922 static void genLabel (iCode *ic)
3923 {
3924
3925
3926     /* special case never generate */
3927     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3928     if (IC_LABEL(ic) == entryLabel)
3929         return ;
3930
3931     pic16_emitpLabel(IC_LABEL(ic)->key);
3932     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
3933 }
3934
3935 /*-----------------------------------------------------------------*/
3936 /* genGoto - generates a goto                                      */
3937 /*-----------------------------------------------------------------*/
3938 //tsd
3939 static void genGoto (iCode *ic)
3940 {
3941   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3942   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
3943 }
3944
3945
3946 /*-----------------------------------------------------------------*/
3947 /* genMultbits :- multiplication of bits                           */
3948 /*-----------------------------------------------------------------*/
3949 static void genMultbits (operand *left, 
3950                          operand *right, 
3951                          operand *result)
3952 {
3953   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3954
3955   if(!pic16_sameRegs(AOP(result),AOP(right)))
3956     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3957
3958   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3959   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3960   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3961
3962 }
3963
3964
3965 /*-----------------------------------------------------------------*/
3966 /* genMultOneByte : 8 bit multiplication & division                */
3967 /*-----------------------------------------------------------------*/
3968 static void genMultOneByte (operand *left,
3969                             operand *right,
3970                             operand *result)
3971 {
3972
3973   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3974   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3975   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3976
3977   /* (if two literals, the value is computed before) */
3978   /* if one literal, literal on the right */
3979   if (AOP_TYPE(left) == AOP_LIT){
3980     operand *t = right;
3981     right = left;
3982     left = t;
3983   }
3984
3985         /* size is already checked in genMult == 1 */
3986 //      size = AOP_SIZE(result);
3987
3988         if (AOP_TYPE(right) == AOP_LIT){
3989                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3990                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3991                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3992                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3993         } else {
3994                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3995                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3996                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3997                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3998         }
3999         
4000         pic16_genMult8X8_8 (left, right,result);
4001 }
4002
4003 /*-----------------------------------------------------------------*/
4004 /* genMultOneWord : 16 bit multiplication                          */
4005 /*-----------------------------------------------------------------*/
4006 static void genMultOneWord (operand *left,
4007                             operand *right,
4008                             operand *result)
4009 {
4010
4011         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4012         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4013         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4014
4015         /* (if two literals, the value is computed before)
4016          * if one literal, literal on the right */
4017         if (AOP_TYPE(left) == AOP_LIT){
4018           operand *t = right;
4019                 right = left;
4020                 left = t;
4021         }
4022
4023         /* size is checked already == 2 */
4024 //      size = AOP_SIZE(result);
4025
4026         if (AOP_TYPE(right) == AOP_LIT) {
4027                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4028                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4029                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4030                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4031         } else {
4032                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4033                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4034                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4035                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4036         }
4037         
4038         pic16_genMult16X16_16(left, right,result);
4039 }
4040
4041 /*-----------------------------------------------------------------*/
4042 /* genMultOneLong : 32 bit multiplication                          */
4043 /*-----------------------------------------------------------------*/
4044 static void genMultOneLong (operand *left,
4045                             operand *right,
4046                             operand *result)
4047 {
4048
4049         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4050         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4051         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4052
4053         /* (if two literals, the value is computed before)
4054          * if one literal, literal on the right */
4055         if (AOP_TYPE(left) == AOP_LIT){
4056           operand *t = right;
4057                 right = left;
4058                 left = t;
4059         }
4060
4061         /* size is checked already == 4 */
4062 //      size = AOP_SIZE(result);
4063
4064         if (AOP_TYPE(right) == AOP_LIT) {
4065                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4066                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4067                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4068                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4069         } else {
4070                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4071                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4072                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4073                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4074         }
4075         
4076         pic16_genMult32X32_32(left, right,result);
4077 }
4078
4079
4080
4081 /*-----------------------------------------------------------------*/
4082 /* genMult - generates code for multiplication                     */
4083 /*-----------------------------------------------------------------*/
4084 static void genMult (iCode *ic)
4085 {
4086   operand *left = IC_LEFT(ic);
4087   operand *right = IC_RIGHT(ic);
4088   operand *result= IC_RESULT(ic);   
4089
4090         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4091         /* assign the amsops */
4092         pic16_aopOp (left,ic,FALSE);
4093         pic16_aopOp (right,ic,FALSE);
4094         pic16_aopOp (result,ic,TRUE);
4095
4096         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4097
4098         /* special cases first *
4099         * both are bits */
4100         if (AOP_TYPE(left) == AOP_CRY
4101                 && AOP_TYPE(right)== AOP_CRY) {
4102                 genMultbits(left,right,result);
4103           goto release ;
4104         }
4105
4106         /* if both are of size == 1 */
4107         if(AOP_SIZE(left) == 1
4108                 && AOP_SIZE(right) == 1) {
4109                 genMultOneByte(left,right,result);
4110           goto release ;
4111         }
4112
4113         /* if both are of size == 2 */
4114         if(AOP_SIZE(left) == 2
4115                 && AOP_SIZE(right) == 2) {
4116                 genMultOneWord(left, right, result);
4117           goto release;
4118         }
4119         
4120         /* if both are of size == 4 */
4121         if(AOP_SIZE(left) == 4
4122                 && AOP_SIZE(right) == 4) {
4123                 genMultOneLong(left, right, result);
4124           goto release;
4125         }
4126         
4127         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4128
4129
4130         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4131         /* should have been converted to function call */
4132         assert(0) ;
4133
4134 release :
4135         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4136         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4137         pic16_freeAsmop(result,NULL,ic,TRUE); 
4138 }
4139
4140 /*-----------------------------------------------------------------*/
4141 /* genDivbits :- division of bits                                  */
4142 /*-----------------------------------------------------------------*/
4143 static void genDivbits (operand *left, 
4144                         operand *right, 
4145                         operand *result)
4146 {
4147
4148     char *l;
4149
4150     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4151     /* the result must be bit */    
4152     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4153     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4154
4155     MOVA(l);    
4156
4157     pic16_emitcode("div","ab");
4158     pic16_emitcode("rrc","a");
4159     pic16_aopPut(AOP(result),"c",0);
4160 }
4161
4162 /*-----------------------------------------------------------------*/
4163 /* genDivOneByte : 8 bit division                                  */
4164 /*-----------------------------------------------------------------*/
4165 static void genDivOneByte (operand *left,
4166                            operand *right,
4167                            operand *result)
4168 {
4169     sym_link *opetype = operandType(result);
4170     char *l ;
4171     symbol *lbl ;
4172     int size,offset;
4173
4174         /* result = divident / divisor
4175          * - divident may be a register or a literal,
4176          * - divisor may be a register or a literal,
4177          * so there are 3 cases (literal / literal is optimized
4178          * by the front-end) to handle.
4179          * In addition we must handle signed and unsigned, which
4180          * result in 6 final different cases -- VR */
4181
4182     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4183     size = AOP_SIZE(result) - 1;
4184     offset = 1;
4185     /* signed or unsigned */
4186     if (SPEC_USIGN(opetype)) {
4187       pCodeOp *pct1,    /* count */
4188                 *pct2,  /* reste */
4189                 *pct3;  /* temp */
4190       symbol *label1, *label2, *label3;;
4191
4192
4193         /* unsigned is easy */
4194
4195         pct1 = pic16_popGetTempReg();
4196         pct2 = pic16_popGetTempReg();
4197         pct3 = pic16_popGetTempReg();
4198         
4199         label1 = newiTempLabel(NULL);
4200         label2 = newiTempLabel(NULL);
4201         label3 = newiTempLabel(NULL);
4202
4203         /* the following algorithm is extracted from divuint.c */
4204
4205         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4206         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4207         
4208         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4209
4210         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4211         
4212         pic16_emitpLabel(label1->key);
4213         
4214         emitCLRC;
4215         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4216
4217
4218         emitCLRC;
4219         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4220         
4221
4222         emitSKPNC;
4223         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4224         
4225         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4226         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4227         
4228         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4229         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4230         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4231         
4232         pic16_emitpLabel( label3->key );
4233         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4234         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4235         
4236         
4237
4238         pic16_emitpLabel(label2->key);
4239         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4240         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4241         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4242         
4243         /* result is in wreg */
4244         if(AOP_TYPE(result) != AOP_ACC)
4245                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4246
4247         pic16_popReleaseTempReg( pct3 );
4248         pic16_popReleaseTempReg( pct2 );
4249         pic16_popReleaseTempReg( pct1 );
4250
4251         return ;
4252     }
4253
4254     /* signed is a little bit more difficult */
4255
4256     /* save the signs of the operands */
4257     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4258     MOVA(l);    
4259     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4260     pic16_emitcode("push","acc"); /* save it on the stack */
4261
4262     /* now sign adjust for both left & right */
4263     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4264     MOVA(l);       
4265     lbl = newiTempLabel(NULL);
4266     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4267     pic16_emitcode("cpl","a");   
4268     pic16_emitcode("inc","a");
4269     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4270     pic16_emitcode("mov","b,a");
4271
4272     /* sign adjust left side */
4273     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4274     MOVA(l);
4275
4276     lbl = newiTempLabel(NULL);
4277     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4278     pic16_emitcode("cpl","a");
4279     pic16_emitcode("inc","a");
4280     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4281
4282     /* now the division */
4283     pic16_emitcode("div","ab");
4284     /* we are interested in the lower order
4285     only */
4286     pic16_emitcode("mov","b,a");
4287     lbl = newiTempLabel(NULL);
4288     pic16_emitcode("pop","acc");   
4289     /* if there was an over flow we don't 
4290     adjust the sign of the result */
4291     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4292     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4293     CLRC;
4294     pic16_emitcode("clr","a");
4295     pic16_emitcode("subb","a,b");
4296     pic16_emitcode("mov","b,a");
4297     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4298
4299     /* now we are done */
4300     pic16_aopPut(AOP(result),"b",0);
4301     if(size > 0){
4302         pic16_emitcode("mov","c,b.7");
4303         pic16_emitcode("subb","a,acc");   
4304     }
4305     while (size--)
4306         pic16_aopPut(AOP(result),"a",offset++);
4307
4308 }
4309
4310 /*-----------------------------------------------------------------*/
4311 /* genDiv - generates code for division                            */
4312 /*-----------------------------------------------------------------*/
4313 static void genDiv (iCode *ic)
4314 {
4315     operand *left = IC_LEFT(ic);
4316     operand *right = IC_RIGHT(ic);
4317     operand *result= IC_RESULT(ic);   
4318
4319
4320         /* Division is a very lengthy algorithm, so it is better
4321          * to call support routines than inlining algorithm.
4322          * Division functions written here just in case someone
4323          * wants to inline and not use the support libraries -- VR */
4324
4325     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4326     /* assign the amsops */
4327     pic16_aopOp (left,ic,FALSE);
4328     pic16_aopOp (right,ic,FALSE);
4329     pic16_aopOp (result,ic,TRUE);
4330
4331     /* special cases first */
4332     /* both are bits */
4333     if (AOP_TYPE(left) == AOP_CRY &&
4334         AOP_TYPE(right)== AOP_CRY) {
4335         genDivbits(left,right,result);
4336         goto release ;
4337     }
4338
4339     /* if both are of size == 1 */
4340     if (AOP_SIZE(left) == 1 &&
4341         AOP_SIZE(right) == 1 ) {
4342         genDivOneByte(left,right,result);
4343         goto release ;
4344     }
4345
4346     /* should have been converted to function call */
4347     assert(0);
4348 release :
4349     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4350     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4351     pic16_freeAsmop(result,NULL,ic,TRUE); 
4352 }
4353
4354 /*-----------------------------------------------------------------*/
4355 /* genModbits :- modulus of bits                                   */
4356 /*-----------------------------------------------------------------*/
4357 static void genModbits (operand *left, 
4358                         operand *right, 
4359                         operand *result)
4360 {
4361
4362     char *l;
4363
4364     /* the result must be bit */    
4365     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4366     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4367
4368     MOVA(l);       
4369
4370     pic16_emitcode("div","ab");
4371     pic16_emitcode("mov","a,b");
4372     pic16_emitcode("rrc","a");
4373     pic16_aopPut(AOP(result),"c",0);
4374 }
4375
4376 /*-----------------------------------------------------------------*/
4377 /* genModOneByte : 8 bit modulus                                   */
4378 /*-----------------------------------------------------------------*/
4379 static void genModOneByte (operand *left,
4380                            operand *right,
4381                            operand *result)
4382 {
4383     sym_link *opetype = operandType(result);
4384     char *l ;
4385     symbol *lbl ;
4386
4387     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4388     /* signed or unsigned */
4389     if (SPEC_USIGN(opetype)) {
4390         /* unsigned is easy */
4391         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4392         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4393         MOVA(l);    
4394         pic16_emitcode("div","ab");
4395         pic16_aopPut(AOP(result),"b",0);
4396         return ;
4397     }
4398
4399     /* signed is a little bit more difficult */
4400
4401     /* save the signs of the operands */
4402     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4403     MOVA(l);
4404
4405     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4406     pic16_emitcode("push","acc"); /* save it on the stack */
4407
4408     /* now sign adjust for both left & right */
4409     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4410     MOVA(l);
4411
4412     lbl = newiTempLabel(NULL);
4413     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4414     pic16_emitcode("cpl","a");   
4415     pic16_emitcode("inc","a");
4416     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4417     pic16_emitcode("mov","b,a"); 
4418
4419     /* sign adjust left side */
4420     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4421     MOVA(l);
4422
4423     lbl = newiTempLabel(NULL);
4424     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4425     pic16_emitcode("cpl","a");   
4426     pic16_emitcode("inc","a");
4427     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4428
4429     /* now the multiplication */
4430     pic16_emitcode("div","ab");
4431     /* we are interested in the lower order
4432     only */
4433     lbl = newiTempLabel(NULL);
4434     pic16_emitcode("pop","acc");   
4435     /* if there was an over flow we don't 
4436     adjust the sign of the result */
4437     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4438     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4439     CLRC ;
4440     pic16_emitcode("clr","a");
4441     pic16_emitcode("subb","a,b");
4442     pic16_emitcode("mov","b,a");
4443     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4444
4445     /* now we are done */
4446     pic16_aopPut(AOP(result),"b",0);
4447
4448 }
4449
4450 /*-----------------------------------------------------------------*/
4451 /* genMod - generates code for division                            */
4452 /*-----------------------------------------------------------------*/
4453 static void genMod (iCode *ic)
4454 {
4455     operand *left = IC_LEFT(ic);
4456     operand *right = IC_RIGHT(ic);
4457     operand *result= IC_RESULT(ic);  
4458
4459     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4460     /* assign the amsops */
4461     pic16_aopOp (left,ic,FALSE);
4462     pic16_aopOp (right,ic,FALSE);
4463     pic16_aopOp (result,ic,TRUE);
4464
4465     /* special cases first */
4466     /* both are bits */
4467     if (AOP_TYPE(left) == AOP_CRY &&
4468         AOP_TYPE(right)== AOP_CRY) {
4469         genModbits(left,right,result);
4470         goto release ;
4471     }
4472
4473     /* if both are of size == 1 */
4474     if (AOP_SIZE(left) == 1 &&
4475         AOP_SIZE(right) == 1 ) {
4476         genModOneByte(left,right,result);
4477         goto release ;
4478     }
4479
4480     /* should have been converted to function call */
4481     assert(0);
4482
4483 release :
4484     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4485     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4486     pic16_freeAsmop(result,NULL,ic,TRUE); 
4487 }
4488
4489 /*-----------------------------------------------------------------*/
4490 /* genIfxJump :- will create a jump depending on the ifx           */
4491 /*-----------------------------------------------------------------*/
4492 /*
4493   note: May need to add parameter to indicate when a variable is in bit space.
4494 */
4495 static void genIfxJump (iCode *ic, char *jval)
4496 {
4497
4498     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4499     /* if true label then we jump if condition
4500     supplied is true */
4501     if ( IC_TRUE(ic) ) {
4502
4503         if(strcmp(jval,"a") == 0)
4504           emitSKPZ;
4505         else if (strcmp(jval,"c") == 0)
4506           emitSKPC;
4507         else {
4508           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4509           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4510         }
4511
4512         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4513         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4514
4515     }
4516     else {
4517         /* false label is present */
4518         if(strcmp(jval,"a") == 0)
4519           emitSKPNZ;
4520         else if (strcmp(jval,"c") == 0)
4521           emitSKPNC;
4522         else {
4523           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4524           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4525         }
4526
4527         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4528         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4529
4530     }
4531
4532
4533     /* mark the icode as generated */
4534     ic->generated = 1;
4535 }
4536
4537 #if 0
4538 // not needed ATM
4539
4540 /*-----------------------------------------------------------------*/
4541 /* genSkip                                                         */
4542 /*-----------------------------------------------------------------*/
4543 static void genSkip(iCode *ifx,int status_bit)
4544 {
4545   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4546   if(!ifx)
4547     return;
4548
4549   if ( IC_TRUE(ifx) ) {
4550     switch(status_bit) {
4551     case 'z':
4552       emitSKPNZ;
4553       break;
4554
4555     case 'c':
4556       emitSKPNC;
4557       break;
4558
4559     case 'd':
4560       emitSKPDC;
4561       break;
4562
4563     }
4564
4565     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4566     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4567
4568   } else {
4569
4570     switch(status_bit) {
4571
4572     case 'z':
4573       emitSKPZ;
4574       break;
4575
4576     case 'c':
4577       emitSKPC;
4578       break;
4579
4580     case 'd':
4581       emitSKPDC;
4582       break;
4583     }
4584     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4585     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4586
4587   }
4588
4589 }
4590 #endif
4591
4592 /*-----------------------------------------------------------------*/
4593 /* genSkipc                                                        */
4594 /*-----------------------------------------------------------------*/
4595 static void genSkipc(resolvedIfx *rifx)
4596 {
4597   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4598   
4599   if(!rifx)
4600     return;
4601
4602   if(rifx->condition)
4603     emitSKPC;
4604   else
4605     emitSKPNC;
4606
4607   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4608   rifx->generated = 1;
4609 }
4610
4611 /*-----------------------------------------------------------------*/
4612 /* genSkipz2                                                       */
4613 /*-----------------------------------------------------------------*/
4614 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4615 {
4616   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4617   
4618   if(!rifx)
4619     return;
4620
4621   if( (rifx->condition ^ invert_condition) & 1)
4622     emitSKPZ;
4623   else
4624     emitSKPNZ;
4625
4626   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4627   rifx->generated = 1;
4628 }
4629
4630 #if 0
4631 /*-----------------------------------------------------------------*/
4632 /* genSkipz                                                        */
4633 /*-----------------------------------------------------------------*/
4634 static void genSkipz(iCode *ifx, int condition)
4635 {
4636   if(!ifx)
4637     return;
4638
4639   if(condition)
4640     emitSKPNZ;
4641   else
4642     emitSKPZ;
4643
4644   if ( IC_TRUE(ifx) )
4645     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4646   else
4647     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4648
4649   if ( IC_TRUE(ifx) )
4650     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4651   else
4652     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4653
4654 }
4655 #endif
4656
4657 /*-----------------------------------------------------------------*/
4658 /* genSkipCond                                                     */
4659 /*-----------------------------------------------------------------*/
4660 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4661 {
4662   if(!rifx)
4663     return;
4664
4665   if(rifx->condition)
4666     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4667   else
4668     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4669
4670
4671   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4672   rifx->generated = 1;
4673 }
4674
4675 #if 0
4676 /*-----------------------------------------------------------------*/
4677 /* genChkZeroes :- greater or less than comparison                 */
4678 /*     For each byte in a literal that is zero, inclusive or the   */
4679 /*     the corresponding byte in the operand with W                */
4680 /*     returns true if any of the bytes are zero                   */
4681 /*-----------------------------------------------------------------*/
4682 static int genChkZeroes(operand *op, int lit,  int size)
4683 {
4684
4685   int i;
4686   int flag =1;
4687
4688   while(size--) {
4689     i = (lit >> (size*8)) & 0xff;
4690
4691     if(i==0) {
4692       if(flag) 
4693         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4694       else
4695         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4696       flag = 0;
4697     }
4698   }
4699
4700   return (flag==0);
4701 }
4702 #endif
4703
4704 /*-----------------------------------------------------------------*/
4705 /* genCmp :- greater or less than comparison                       */
4706 /*-----------------------------------------------------------------*/
4707 static void genCmp (operand *left,operand *right,
4708                     operand *result, iCode *ifx, int sign)
4709 {
4710   int size; //, offset = 0 ;
4711   unsigned long lit = 0L,i = 0;
4712   resolvedIfx rFalseIfx;
4713   //  resolvedIfx rTrueIfx;
4714   symbol *truelbl;
4715   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4716 /*
4717   if(ifx) {
4718     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4719     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4720   }
4721 */
4722
4723   resolveIfx(&rFalseIfx,ifx);
4724   truelbl  = newiTempLabel(NULL);
4725   size = max(AOP_SIZE(left),AOP_SIZE(right));
4726
4727   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4728
4729 #define _swapp
4730
4731   /* if literal is on the right then swap with left */
4732   if ((AOP_TYPE(right) == AOP_LIT)) {
4733     operand *tmp = right ;
4734     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4735     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4736 #ifdef _swapp
4737
4738     lit = (lit - 1) & mask;
4739     right = left;
4740     left = tmp;
4741     rFalseIfx.condition ^= 1;
4742 #endif
4743
4744   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4745     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4746   }
4747
4748
4749   //if(IC_TRUE(ifx) == NULL)
4750   /* if left & right are bit variables */
4751   if (AOP_TYPE(left) == AOP_CRY &&
4752       AOP_TYPE(right) == AOP_CRY ) {
4753     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4754     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4755   } else {
4756     /* subtract right from left if at the
4757        end the carry flag is set then we know that
4758        left is greater than right */
4759
4760     symbol *lbl  = newiTempLabel(NULL);
4761
4762 #if 0
4763         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4764                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
4765 #endif
4766
4767 #ifndef _swapp
4768     if(AOP_TYPE(right) == AOP_LIT) {
4769
4770       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4771
4772       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4773
4774       /* special cases */
4775
4776       if(lit == 0) {
4777
4778         if(sign != 0) 
4779           genSkipCond(&rFalseIfx,left,size-1,7);
4780         else 
4781           /* no need to compare to 0...*/
4782           /* NOTE: this is a de-generate compare that most certainly 
4783            *       creates some dead code. */
4784           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4785
4786         if(ifx) ifx->generated = 1;
4787         return;
4788
4789       }
4790       size--;
4791
4792       if(size == 0) {
4793         //i = (lit >> (size*8)) & 0xff;
4794         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4795         
4796         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4797
4798         i = ((0-lit) & 0xff);
4799         if(sign) {
4800           if( i == 0x81) { 
4801             /* lit is 0x7f, all signed chars are less than
4802              * this except for 0x7f itself */
4803             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4804             genSkipz2(&rFalseIfx,0);
4805           } else {
4806             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4807             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4808             genSkipc(&rFalseIfx);
4809           }
4810
4811         } else {
4812           if(lit == 1) {
4813             genSkipz2(&rFalseIfx,1);
4814           } else {
4815             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4816             genSkipc(&rFalseIfx);
4817           }
4818         }
4819
4820         if(ifx) ifx->generated = 1;
4821         return;
4822       }
4823
4824       /* chars are out of the way. now do ints and longs */
4825
4826
4827       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4828         
4829       /* special cases */
4830
4831       if(sign) {
4832
4833         if(lit == 0) {
4834           genSkipCond(&rFalseIfx,left,size,7);
4835           if(ifx) ifx->generated = 1;
4836           return;
4837         }
4838
4839         if(lit <0x100) {
4840           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4841
4842           //rFalseIfx.condition ^= 1;
4843           //genSkipCond(&rFalseIfx,left,size,7);
4844           //rFalseIfx.condition ^= 1;
4845
4846           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4847           if(rFalseIfx.condition)
4848             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4849           else
4850             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4851
4852           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4853           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4854           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4855
4856           while(size > 1)
4857             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4858
4859           if(rFalseIfx.condition) {
4860             emitSKPZ;
4861             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4862
4863           } else {
4864             emitSKPNZ;
4865           }
4866
4867           genSkipc(&rFalseIfx);
4868           pic16_emitpLabel(truelbl->key);
4869           if(ifx) ifx->generated = 1;
4870           return;
4871
4872         }
4873
4874         if(size == 1) {
4875
4876           if( (lit & 0xff) == 0) {
4877             /* lower byte is zero */
4878             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4879             i = ((lit >> 8) & 0xff) ^0x80;
4880             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4881             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4882             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4883             genSkipc(&rFalseIfx);
4884
4885
4886             if(ifx) ifx->generated = 1;
4887             return;
4888
4889           }
4890         } else {
4891           /* Special cases for signed longs */
4892           if( (lit & 0xffffff) == 0) {
4893             /* lower byte is zero */
4894             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4895             i = ((lit >> 8*3) & 0xff) ^0x80;
4896             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4897             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4898             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4899             genSkipc(&rFalseIfx);
4900
4901
4902             if(ifx) ifx->generated = 1;
4903             return;
4904
4905           }
4906
4907         }
4908
4909
4910         if(lit & (0x80 << (size*8))) {
4911           /* lit is negative */
4912           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4913
4914           //genSkipCond(&rFalseIfx,left,size,7);
4915
4916           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4917
4918           if(rFalseIfx.condition)
4919             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4920           else
4921             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4922
4923
4924         } else {
4925           /* lit is positive */
4926           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4927           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
4928           if(rFalseIfx.condition)
4929             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4930           else
4931             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4932
4933         }
4934
4935         /*
4936           This works, but is only good for ints.
4937           It also requires a "known zero" register.
4938           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4939           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4940           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4941           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4942           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4943           genSkipc(&rFalseIfx);
4944
4945           pic16_emitpLabel(truelbl->key);
4946           if(ifx) ifx->generated = 1;
4947           return;
4948         **/
4949           
4950         /* There are no more special cases, so perform a general compare */
4951   
4952         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4953         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4954
4955         while(size--) {
4956
4957           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4958           emitSKPNZ;
4959           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4960         }
4961         //rFalseIfx.condition ^= 1;
4962         genSkipc(&rFalseIfx);
4963
4964         pic16_emitpLabel(truelbl->key);
4965
4966         if(ifx) ifx->generated = 1;
4967         return;
4968
4969
4970       }
4971
4972
4973       /* sign is out of the way. So now do an unsigned compare */
4974       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4975
4976
4977       /* General case - compare to an unsigned literal on the right.*/
4978
4979       i = (lit >> (size*8)) & 0xff;
4980       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4981       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4982       while(size--) {
4983         i = (lit >> (size*8)) & 0xff;
4984
4985         if(i) {
4986           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4987           emitSKPNZ;
4988           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4989         } else {
4990           /* this byte of the lit is zero, 
4991            *if it's not the last then OR in the variable */
4992           if(size)
4993             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4994         }
4995       }
4996
4997
4998       pic16_emitpLabel(lbl->key);
4999 //      pic16_emitpLabel(truelbl->key);
5000       //if(emitFinalCheck)
5001       genSkipc(&rFalseIfx);
5002       if(sign)
5003         pic16_emitpLabel(truelbl->key);
5004
5005       if(ifx) ifx->generated = 1;
5006       return;
5007
5008
5009     }
5010 #endif  // _swapp
5011
5012     if(AOP_TYPE(left) == AOP_LIT) {
5013       //symbol *lbl = newiTempLabel(NULL);
5014
5015       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5016
5017
5018       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5019
5020       /* Special cases */
5021       if((lit == 0) && (sign == 0)){
5022
5023         size--;
5024         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5025         while(size) 
5026           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5027
5028         genSkipz2(&rFalseIfx,0);
5029         if(ifx) ifx->generated = 1;
5030         return;
5031       }
5032
5033       if(size==1) {
5034         /* Special cases */
5035         lit &= 0xff;
5036         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5037           /* degenerate compare can never be true */
5038           if(rFalseIfx.condition == 0)
5039             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5040
5041           if(ifx) ifx->generated = 1;
5042           return;
5043         }
5044
5045         if(sign) {
5046           /* signed comparisons to a literal byte */
5047
5048           int lp1 = (lit+1) & 0xff;
5049
5050           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5051           switch (lp1) {
5052           case 0:
5053             rFalseIfx.condition ^= 1;
5054             genSkipCond(&rFalseIfx,right,0,7);
5055             break;
5056           case 0x7f:
5057             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5058             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5059             genSkipz2(&rFalseIfx,1);
5060             break;
5061           default:
5062             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5063             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5064             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5065             rFalseIfx.condition ^= 1;
5066             genSkipc(&rFalseIfx);
5067             break;
5068           }
5069         } else {
5070           /* unsigned comparisons to a literal byte */
5071
5072           switch(lit & 0xff ) {
5073           case 0:
5074             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5075             genSkipz2(&rFalseIfx,0);
5076             break;
5077           case 0x7f:
5078             rFalseIfx.condition ^= 1;
5079             genSkipCond(&rFalseIfx,right,0,7);
5080             break;
5081
5082           default:
5083             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5084             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5085             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5086             rFalseIfx.condition ^= 1;
5087             if (AOP_TYPE(result) == AOP_CRY)
5088               genSkipc(&rFalseIfx);
5089             else {
5090               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5091               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5092             }         
5093             break;
5094           }
5095         }
5096
5097         if(ifx) ifx->generated = 1;
5098         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5099                 goto check_carry;
5100         return;
5101
5102       } else {
5103
5104         /* Size is greater than 1 */
5105
5106         if(sign) {
5107           int lp1 = lit+1;
5108
5109           size--;
5110
5111           if(lp1 == 0) {
5112             /* this means lit = 0xffffffff, or -1 */
5113
5114
5115             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5116             rFalseIfx.condition ^= 1;
5117             genSkipCond(&rFalseIfx,right,size,7);
5118             if(ifx) ifx->generated = 1;
5119             return;
5120           }
5121
5122           if(lit == 0) {
5123             int s = size;
5124
5125             if(rFalseIfx.condition) {
5126               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5127               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5128             }
5129
5130             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5131             while(size--)
5132               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5133
5134
5135             emitSKPZ;
5136             if(rFalseIfx.condition) {
5137               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5138               pic16_emitpLabel(truelbl->key);
5139             }else {
5140               rFalseIfx.condition ^= 1;
5141               genSkipCond(&rFalseIfx,right,s,7);
5142             }
5143
5144             if(ifx) ifx->generated = 1;
5145             return;
5146           }
5147
5148           if((size == 1) &&  (0 == (lp1&0xff))) {
5149             /* lower byte of signed word is zero */
5150             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5151             i = ((lp1 >> 8) & 0xff) ^0x80;
5152             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5153             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5154             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5155             rFalseIfx.condition ^= 1;
5156             genSkipc(&rFalseIfx);
5157
5158
5159             if(ifx) ifx->generated = 1;
5160             return;
5161           }
5162
5163           if(lit & (0x80 << (size*8))) {
5164             /* Lit is less than zero */
5165             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5166             //rFalseIfx.condition ^= 1;
5167             //genSkipCond(&rFalseIfx,left,size,7);
5168             //rFalseIfx.condition ^= 1;
5169             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5170             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5171
5172             if(rFalseIfx.condition)
5173               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5174             else
5175               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5176
5177
5178           } else {
5179             /* Lit is greater than or equal to zero */
5180             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5181             //rFalseIfx.condition ^= 1;
5182             //genSkipCond(&rFalseIfx,right,size,7);
5183             //rFalseIfx.condition ^= 1;
5184
5185             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5186             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5187
5188             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5189             if(rFalseIfx.condition)
5190               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5191             else
5192               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5193
5194           }
5195
5196
5197           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5198           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5199
5200           while(size--) {
5201
5202             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5203             emitSKPNZ;
5204             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5205           }
5206           rFalseIfx.condition ^= 1;
5207           //rFalseIfx.condition = 1;
5208           genSkipc(&rFalseIfx);
5209
5210           pic16_emitpLabel(truelbl->key);
5211
5212           if(ifx) ifx->generated = 1;
5213           return;
5214           // end of if (sign)
5215         } else {
5216
5217           /* compare word or long to an unsigned literal on the right.*/
5218
5219
5220           size--;
5221           if(lit < 0xff) {
5222             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5223             switch (lit) {
5224             case 0:
5225               break; /* handled above */
5226 /*
5227             case 0xff:
5228               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5229               while(size--)
5230                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5231               genSkipz2(&rFalseIfx,0);
5232               break;
5233 */
5234             default:
5235               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5236               while(--size)
5237                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5238
5239               emitSKPZ;
5240               if(rFalseIfx.condition)
5241                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5242               else
5243                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5244
5245
5246               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5247               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5248
5249               rFalseIfx.condition ^= 1;
5250               genSkipc(&rFalseIfx);
5251             }
5252
5253             pic16_emitpLabel(truelbl->key);
5254
5255             if(ifx) ifx->generated = 1;
5256             return;
5257           }
5258
5259
5260           lit++;
5261           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5262           i = (lit >> (size*8)) & 0xff;
5263
5264           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5265           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5266
5267           while(size--) {
5268             i = (lit >> (size*8)) & 0xff;
5269
5270             if(i) {
5271               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5272               emitSKPNZ;
5273               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5274             } else {
5275               /* this byte of the lit is zero, 
5276                * if it's not the last then OR in the variable */
5277               if(size)
5278                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5279             }
5280           }
5281
5282
5283           pic16_emitpLabel(lbl->key);
5284
5285           rFalseIfx.condition ^= 1;
5286
5287           genSkipc(&rFalseIfx);
5288         }
5289
5290         if(sign)
5291           pic16_emitpLabel(truelbl->key);
5292         if(ifx) ifx->generated = 1;
5293         return;
5294       }
5295     }
5296     /* Compare two variables */
5297
5298     DEBUGpic16_emitcode(";sign","%d",sign);
5299
5300     size--;
5301     if(sign) {
5302       /* Sigh. thus sucks... */
5303       if(size) {
5304         pCodeOp *pctemp;
5305         
5306         pctemp = pic16_popGetTempReg();
5307         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5308         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr));
5309         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5310         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5311         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5312         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5313         pic16_popReleaseTempReg(pctemp);
5314       } else {
5315         /* Signed char comparison */
5316         /* Special thanks to Nikolai Golovchenko for this snippet */
5317         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5318         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5319         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5320         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5321         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5322         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5323
5324         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5325         genSkipc(&rFalseIfx);
5326           
5327         if(ifx) ifx->generated = 1;
5328         return;
5329       }
5330
5331     } else {
5332
5333       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5334       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5335     }
5336
5337
5338     /* The rest of the bytes of a multi-byte compare */
5339     while (size) {
5340
5341       emitSKPZ;
5342       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5343       size--;
5344
5345       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5346       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5347
5348
5349     }
5350
5351     pic16_emitpLabel(lbl->key);
5352
5353     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5354     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5355         (AOP_TYPE(result) == AOP_REG)) {
5356       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5357       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5358     } else {
5359       genSkipc(&rFalseIfx);
5360     }         
5361     //genSkipc(&rFalseIfx);
5362     if(ifx) ifx->generated = 1;
5363
5364     return;
5365
5366   }
5367
5368 check_carry:
5369   if ((AOP_TYPE(result) != AOP_CRY) 
5370         && AOP_SIZE(result)) {
5371     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5372
5373     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5374
5375     pic16_outBitC(result);
5376   } else {
5377     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5378     /* if the result is used in the next
5379        ifx conditional branch then generate
5380        code a little differently */
5381     if (ifx )
5382       genIfxJump (ifx,"c");
5383     else
5384       pic16_outBitC(result);
5385     /* leave the result in acc */
5386   }
5387
5388 }
5389
5390 /*-----------------------------------------------------------------*/
5391 /* genCmpGt :- greater than comparison                             */
5392 /*-----------------------------------------------------------------*/
5393 static void genCmpGt (iCode *ic, iCode *ifx)
5394 {
5395     operand *left, *right, *result;
5396     sym_link *letype , *retype;
5397     int sign ;
5398
5399     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5400     left = IC_LEFT(ic);
5401     right= IC_RIGHT(ic);
5402     result = IC_RESULT(ic);
5403
5404     letype = getSpec(operandType(left));
5405     retype =getSpec(operandType(right));
5406     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5407     /* assign the amsops */
5408     pic16_aopOp (left,ic,FALSE);
5409     pic16_aopOp (right,ic,FALSE);
5410     pic16_aopOp (result,ic,TRUE);
5411
5412     genCmp(right, left, result, ifx, sign);
5413
5414     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5415     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5416     pic16_freeAsmop(result,NULL,ic,TRUE); 
5417 }
5418
5419 /*-----------------------------------------------------------------*/
5420 /* genCmpLt - less than comparisons                                */
5421 /*-----------------------------------------------------------------*/
5422 static void genCmpLt (iCode *ic, iCode *ifx)
5423 {
5424     operand *left, *right, *result;
5425     sym_link *letype , *retype;
5426     int sign ;
5427
5428     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5429     left = IC_LEFT(ic);
5430     right= IC_RIGHT(ic);
5431     result = IC_RESULT(ic);
5432
5433     letype = getSpec(operandType(left));
5434     retype =getSpec(operandType(right));
5435     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5436
5437     /* assign the amsops */
5438     pic16_aopOp (left,ic,FALSE);
5439     pic16_aopOp (right,ic,FALSE);
5440     pic16_aopOp (result,ic,TRUE);
5441
5442     genCmp(left, right, result, ifx, sign);
5443
5444     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5445     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5446     pic16_freeAsmop(result,NULL,ic,TRUE); 
5447 }
5448
5449 #if 0
5450 // not needed ATM
5451 // FIXME reenable literal optimisation when the pic16 port is stable
5452
5453 /*-----------------------------------------------------------------*/
5454 /* genc16bit2lit - compare a 16 bit value to a literal             */
5455 /*-----------------------------------------------------------------*/
5456 static void genc16bit2lit(operand *op, int lit, int offset)
5457 {
5458   int i;
5459
5460   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5461   if( (lit&0xff) == 0) 
5462     i=1;
5463   else
5464     i=0;
5465
5466   switch( BYTEofLONG(lit,i)) { 
5467   case 0:
5468     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5469     break;
5470   case 1:
5471     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5472     break;
5473   case 0xff:
5474     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5475     break;
5476   default:
5477     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5478     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5479   }
5480
5481   i ^= 1;
5482
5483   switch( BYTEofLONG(lit,i)) { 
5484   case 0:
5485     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5486     break;
5487   case 1:
5488     emitSKPNZ;
5489     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5490     break;
5491   case 0xff:
5492     emitSKPNZ;
5493     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5494     break;
5495   default:
5496     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5497     emitSKPNZ;
5498     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5499
5500   }
5501
5502 }
5503 #endif
5504
5505 #if 0
5506 // not needed ATM
5507 /*-----------------------------------------------------------------*/
5508 /* gencjneshort - compare and jump if not equal                    */
5509 /*-----------------------------------------------------------------*/
5510 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5511 {
5512   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5513   int offset = 0;
5514   int res_offset = 0;  /* the result may be a different size then left or right */
5515   int res_size = AOP_SIZE(result);
5516   resolvedIfx rIfx;
5517   symbol *lbl, *lbl_done;
5518
5519   unsigned long lit = 0L;
5520   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5521
5522   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5523   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5524   if(result)
5525     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5526   resolveIfx(&rIfx,ifx);
5527   lbl =  newiTempLabel(NULL);
5528   lbl_done =  newiTempLabel(NULL);
5529
5530
5531   /* if the left side is a literal or 
5532      if the right is in a pointer register and left 
5533      is not */
5534   if ((AOP_TYPE(left) == AOP_LIT) || 
5535       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5536     operand *t = right;
5537     right = left;
5538     left = t;
5539   }
5540   if(AOP_TYPE(right) == AOP_LIT)
5541     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5542
5543   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5544     preserve_result = 1;
5545
5546   if(result && !preserve_result)
5547     {
5548       int i;
5549       for(i = 0; i < AOP_SIZE(result); i++)
5550         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5551     }
5552
5553
5554   /* if the right side is a literal then anything goes */
5555   if (AOP_TYPE(right) == AOP_LIT &&
5556       AOP_TYPE(left) != AOP_DIR ) {
5557     switch(size) {
5558     case 2:
5559       genc16bit2lit(left, lit, 0);
5560       emitSKPZ;
5561       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5562       break;
5563     default:
5564       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5565       while (size--) {
5566         if(lit & 0xff) {
5567           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5568           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5569         } else {
5570           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5571         }
5572
5573         emitSKPZ;
5574         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5575         offset++;
5576         if(res_offset < res_size-1)
5577           res_offset++;
5578         lit >>= 8;
5579       }
5580       break;
5581     }
5582   }
5583
5584   /* if the right side is in a register or in direct space or
5585      if the left is a pointer register & right is not */    
5586   else if (AOP_TYPE(right) == AOP_REG ||
5587            AOP_TYPE(right) == AOP_DIR || 
5588            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5589            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5590     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5591     int lbl_key = lbl->key;
5592
5593     if(result) {
5594       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5595       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5596     }else {
5597       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5598       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5599               __FUNCTION__,__LINE__);
5600       return;
5601     }
5602    
5603 /*     switch(size) { */
5604 /*     case 2: */
5605 /*       genc16bit2lit(left, lit, 0); */
5606 /*       emitSKPNZ; */
5607 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5608 /*       break; */
5609 /*     default: */
5610     while (size--) {
5611       int emit_skip=1;
5612       if((AOP_TYPE(left) == AOP_DIR) && 
5613          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5614
5615         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5616         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5617
5618       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5619             
5620         switch (lit & 0xff) {
5621         case 0:
5622           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5623           break;
5624         case 1:
5625           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5626           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5627           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5628           emit_skip=0;
5629           break;
5630         case 0xff:
5631           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5632           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5633           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5634           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5635           emit_skip=0;
5636           break;
5637         default:
5638           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5639           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5640         }
5641         lit >>= 8;
5642
5643       } else {
5644         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5645       }
5646       if(emit_skip) {
5647         if(AOP_TYPE(result) == AOP_CRY) {
5648           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5649           if(rIfx.condition)
5650             emitSKPNZ;
5651           else
5652             emitSKPZ;
5653           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5654         } else {
5655           /* fix me. probably need to check result size too */
5656           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5657           if(rIfx.condition)
5658             emitSKPZ;
5659           else
5660             emitSKPNZ;
5661           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5662           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5663         }
5664         if(ifx)
5665           ifx->generated=1;
5666       }
5667       emit_skip++;
5668       offset++;
5669       if(res_offset < res_size-1)
5670         res_offset++;
5671     }
5672 /*       break; */
5673 /*     } */
5674   } else if(AOP_TYPE(right) == AOP_REG &&
5675             AOP_TYPE(left) != AOP_DIR){
5676
5677     while(size--) {
5678       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5679       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5680       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5681       if(rIfx.condition)
5682         emitSKPNZ;
5683       else
5684         emitSKPZ;
5685       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5686       offset++;
5687       if(res_offset < res_size-1)
5688         res_offset++;
5689     }
5690       
5691   }else{
5692     /* right is a pointer reg need both a & b */
5693     while(size--) {
5694       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5695       if(strcmp(l,"b"))
5696         pic16_emitcode("mov","b,%s",l);
5697       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5698       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5699       offset++;
5700     }
5701   }
5702
5703   if(result && preserve_result)
5704     {
5705       int i;
5706       for(i = 0; i < AOP_SIZE(result); i++)
5707         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5708     }
5709
5710   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5711
5712   if(result && preserve_result)
5713     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5714
5715   if(!rIfx.condition)
5716     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5717
5718   pic16_emitpLabel(lbl->key);
5719
5720   if(result && preserve_result)
5721     {
5722       int i;
5723       for(i = 0; i < AOP_SIZE(result); i++)
5724         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5725
5726       pic16_emitpLabel(lbl_done->key);
5727    }
5728
5729   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5730
5731   if(ifx)
5732     ifx->generated = 1;
5733 }
5734 #endif
5735
5736 #if 0
5737 /*-----------------------------------------------------------------*/
5738 /* gencjne - compare and jump if not equal                         */
5739 /*-----------------------------------------------------------------*/
5740 static void gencjne(operand *left, operand *right, iCode *ifx)
5741 {
5742     symbol *tlbl  = newiTempLabel(NULL);
5743
5744     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5745     gencjneshort(left, right, lbl);
5746
5747     pic16_emitcode("mov","a,%s",one);
5748     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5749     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5750     pic16_emitcode("clr","a");
5751     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5752
5753     pic16_emitpLabel(lbl->key);
5754     pic16_emitpLabel(tlbl->key);
5755
5756 }
5757 #endif
5758
5759
5760 /*-----------------------------------------------------------------*/
5761 /* is_LitOp - check if operand has to be treated as literal        */
5762 /*-----------------------------------------------------------------*/
5763 static bool is_LitOp(operand *op)
5764 {
5765   return (AOP_TYPE(op) == AOP_LIT)
5766       || ( (AOP_TYPE(op) == AOP_PCODE)
5767           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5768               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5769 }
5770
5771 /*-----------------------------------------------------------------*/
5772 /* is_LitAOp - check if operand has to be treated as literal        */
5773 /*-----------------------------------------------------------------*/
5774 static bool is_LitAOp(asmop *aop)
5775 {
5776   return (aop->type == AOP_LIT)
5777       || ( (aop->type == AOP_PCODE)
5778           && ( (aop->aopu.pcop->type == PO_LITERAL)
5779               || (aop->aopu.pcop->type == PO_IMMEDIATE) ));  
5780 }
5781
5782
5783
5784 /*-----------------------------------------------------------------*/
5785 /* genCmpEq - generates code for equal to                          */
5786 /*-----------------------------------------------------------------*/
5787 static void genCmpEq (iCode *ic, iCode *ifx)
5788 {
5789   operand *left, *right, *result;
5790   symbol *falselbl = newiTempLabel(NULL);
5791   symbol *donelbl = newiTempLabel(NULL);
5792
5793   int preserve_result = 0;
5794   int generate_result = 0;
5795   int i=0;
5796
5797   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5798   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5799   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5800  
5801   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5802   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5803
5804   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5805     {
5806       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5807       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5808       goto release;
5809     }
5810
5811   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5812     {
5813       operand *tmp = right ;
5814       right = left;
5815       left = tmp;
5816     }
5817
5818   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5819     preserve_result = 1;
5820
5821   if(result && AOP_SIZE(result))
5822     generate_result = 1;
5823
5824   if(generate_result && !preserve_result)
5825     {
5826       for(i = 0; i < AOP_SIZE(result); i++)
5827         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5828     }
5829
5830   for(i=0; i < AOP_SIZE(left); i++)
5831     {
5832       if(AOP_TYPE(left) != AOP_ACC)
5833         {
5834           if(is_LitOp(left))
5835             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5836           else
5837             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5838         }
5839       if(is_LitOp(right))
5840         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5841       else
5842         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5843
5844       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5845     }
5846
5847   // result == true
5848
5849   if(generate_result && preserve_result)
5850     {
5851       for(i = 0; i < AOP_SIZE(result); i++)
5852         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5853     }
5854
5855   if(generate_result)
5856     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5857
5858   if(generate_result && preserve_result)
5859     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5860
5861   if(ifx && IC_TRUE(ifx))
5862     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5863
5864   if(ifx && IC_FALSE(ifx))
5865     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5866
5867   pic16_emitpLabel(falselbl->key);
5868
5869   // result == false
5870
5871   if(ifx && IC_FALSE(ifx))
5872     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5873
5874   if(generate_result && preserve_result)
5875     {
5876       for(i = 0; i < AOP_SIZE(result); i++)
5877         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5878     }
5879
5880   pic16_emitpLabel(donelbl->key);
5881
5882   if(ifx)
5883     ifx->generated = 1;
5884
5885 release:
5886   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5887   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5888   pic16_freeAsmop(result,NULL,ic,TRUE);
5889
5890 }
5891
5892
5893 #if 0
5894 // old version kept for reference
5895
5896 /*-----------------------------------------------------------------*/
5897 /* genCmpEq - generates code for equal to                          */
5898 /*-----------------------------------------------------------------*/
5899 static void genCmpEq (iCode *ic, iCode *ifx)
5900 {
5901     operand *left, *right, *result;
5902     unsigned long lit = 0L;
5903     int size,offset=0;
5904     symbol *falselbl  = newiTempLabel(NULL);
5905
5906
5907     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5908
5909     if(ifx)
5910       DEBUGpic16_emitcode ("; ifx is non-null","");
5911     else
5912       DEBUGpic16_emitcode ("; ifx is null","");
5913
5914     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5915     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5916     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5917
5918     size = max(AOP_SIZE(left),AOP_SIZE(right));
5919
5920     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5921
5922     /* if literal, literal on the right or 
5923     if the right is in a pointer register and left 
5924     is not */
5925     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5926         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5927       operand *tmp = right ;
5928       right = left;
5929       left = tmp;
5930     }
5931
5932
5933     if(ifx && !AOP_SIZE(result)){
5934         symbol *tlbl;
5935         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5936         /* if they are both bit variables */
5937         if (AOP_TYPE(left) == AOP_CRY &&
5938             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5939                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5940             if(AOP_TYPE(right) == AOP_LIT){
5941                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5942                 if(lit == 0L){
5943                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5944                     pic16_emitcode("cpl","c");
5945                 } else if(lit == 1L) {
5946                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5947                 } else {
5948                     pic16_emitcode("clr","c");
5949                 }
5950                 /* AOP_TYPE(right) == AOP_CRY */
5951             } else {
5952                 symbol *lbl = newiTempLabel(NULL);
5953                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5954                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5955                 pic16_emitcode("cpl","c");
5956                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5957             }
5958             /* if true label then we jump if condition
5959             supplied is true */
5960             tlbl = newiTempLabel(NULL);
5961             if ( IC_TRUE(ifx) ) {
5962                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5963                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5964             } else {
5965                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5966                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5967             }
5968             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
5969
5970                 {
5971                 /* left and right are both bit variables, result is carry */
5972                         resolvedIfx rIfx;
5973               
5974                         resolveIfx(&rIfx,ifx);
5975
5976                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5977                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5978                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5979                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5980                         genSkipz2(&rIfx,0);
5981                 }
5982         } else {
5983
5984                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5985
5986                         /* They're not both bit variables. Is the right a literal? */
5987                         if(AOP_TYPE(right) == AOP_LIT) {
5988                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5989             
5990                         switch(size) {
5991
5992                                 case 1:
5993                                         switch(lit & 0xff) {
5994                                                 case 1:
5995                                                                 if ( IC_TRUE(ifx) ) {
5996                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5997                                                                         emitSKPNZ;
5998                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5999                                                                 } else {
6000                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6001                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6002                                                                 }
6003                                                                 break;
6004                                                 case 0xff:
6005                                                                 if ( IC_TRUE(ifx) ) {
6006                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6007                                                                         emitSKPNZ;
6008                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6009                                                                 } else {
6010                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6011                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6012                                                                 }
6013                                                                 break;
6014                                                 default:
6015                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6016                                                                 if(lit)
6017                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6018                                                                 genSkip(ifx,'z');
6019                                         } // switch lit
6020
6021
6022                                         /* end of size == 1 */
6023                                         break;
6024               
6025                                 case 2:
6026                                         genc16bit2lit(left,lit,offset);
6027                                         genSkip(ifx,'z');
6028                                         break;
6029                                         /* end of size == 2 */
6030
6031                                 default:
6032                                         /* size is 4 */
6033                                         if(lit==0) {
6034                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6035                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6036                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6037                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6038                                                 genSkip(ifx,'z');
6039                                         } else {
6040                                                 /* search for patterns that can be optimized */
6041
6042                                                 genc16bit2lit(left,lit,0);
6043                                                 lit >>= 16;
6044                                                 if(lit) {
6045                                                                 if(IC_TRUE(ifx))
6046                                                                 emitSKPZ; // if hi word unequal
6047                                                                 else
6048                                                                 emitSKPNZ; // if hi word equal
6049                                                                 // fail early
6050                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6051                                                         genc16bit2lit(left,lit,2);
6052                                                         genSkip(ifx,'z');
6053                                                 } else {
6054                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6055                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6056                                                         genSkip(ifx,'z');
6057                                                 }
6058                                         }
6059                                                 pic16_emitpLabel(falselbl->key);
6060                                                 break;
6061
6062                         } // switch size
6063           
6064                         ifx->generated = 1;
6065                         goto release ;
6066             
6067
6068           } else if(AOP_TYPE(right) == AOP_CRY ) {
6069             /* we know the left is not a bit, but that the right is */
6070             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6071             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6072                       pic16_popGet(AOP(right),offset));
6073             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6074
6075             /* if the two are equal, then W will be 0 and the Z bit is set
6076              * we could test Z now, or go ahead and check the high order bytes if
6077              * the variable we're comparing is larger than a byte. */
6078
6079             while(--size)
6080               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6081
6082             if ( IC_TRUE(ifx) ) {
6083               emitSKPNZ;
6084               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6085               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6086             } else {
6087               emitSKPZ;
6088               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6089               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6090             }
6091
6092           } else {
6093             /* They're both variables that are larger than bits */
6094             int s = size;
6095
6096             tlbl = newiTempLabel(NULL);
6097
6098             while(size--) {
6099               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6100               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6101
6102               if ( IC_TRUE(ifx) ) {
6103                 if(size) {
6104                   emitSKPZ;
6105                 
6106                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6107
6108                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6109                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6110                 } else {
6111                   emitSKPNZ;
6112
6113                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6114
6115
6116                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6117                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6118                 }
6119               } else {
6120                 emitSKPZ;
6121
6122                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6123
6124                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6125                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6126               }
6127               offset++;
6128             }
6129             if(s>1 && IC_TRUE(ifx)) {
6130               pic16_emitpLabel(tlbl->key);
6131               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6132             }
6133           }
6134         }
6135         /* mark the icode as generated */
6136         ifx->generated = 1;
6137         goto release ;
6138     }
6139
6140     /* if they are both bit variables */
6141     if (AOP_TYPE(left) == AOP_CRY &&
6142         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6143         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6144         if(AOP_TYPE(right) == AOP_LIT){
6145             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6146             if(lit == 0L){
6147                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6148                 pic16_emitcode("cpl","c");
6149             } else if(lit == 1L) {
6150                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6151             } else {
6152                 pic16_emitcode("clr","c");
6153             }
6154             /* AOP_TYPE(right) == AOP_CRY */
6155         } else {
6156             symbol *lbl = newiTempLabel(NULL);
6157             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6158             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6159             pic16_emitcode("cpl","c");
6160             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6161         }
6162         /* c = 1 if egal */
6163         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6164             pic16_outBitC(result);
6165             goto release ;
6166         }
6167         if (ifx) {
6168             genIfxJump (ifx,"c");
6169             goto release ;
6170         }
6171         /* if the result is used in an arithmetic operation
6172         then put the result in place */
6173         pic16_outBitC(result);
6174     } else {
6175       
6176       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6177       gencjne(left,right,result,ifx);
6178 /*
6179       if(ifx) 
6180         gencjne(left,right,newiTempLabel(NULL));
6181       else {
6182         if(IC_TRUE(ifx)->key)
6183           gencjne(left,right,IC_TRUE(ifx)->key);
6184         else
6185           gencjne(left,right,IC_FALSE(ifx)->key);
6186         ifx->generated = 1;
6187         goto release ;
6188       }
6189       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6190         pic16_aopPut(AOP(result),"a",0);
6191         goto release ;
6192       }
6193
6194       if (ifx) {
6195         genIfxJump (ifx,"a");
6196         goto release ;
6197       }
6198 */
6199       /* if the result is used in an arithmetic operation
6200          then put the result in place */
6201 /*
6202       if (AOP_TYPE(result) != AOP_CRY) 
6203         pic16_outAcc(result);
6204 */
6205       /* leave the result in acc */
6206     }
6207
6208 release:
6209     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6210     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6211     pic16_freeAsmop(result,NULL,ic,TRUE);
6212 }
6213 #endif
6214
6215 /*-----------------------------------------------------------------*/
6216 /* ifxForOp - returns the icode containing the ifx for operand     */
6217 /*-----------------------------------------------------------------*/
6218 static iCode *ifxForOp ( operand *op, iCode *ic )
6219 {
6220     /* if true symbol then needs to be assigned */
6221     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6222     if (IS_TRUE_SYMOP(op))
6223         return NULL ;
6224
6225     /* if this has register type condition and
6226     the next instruction is ifx with the same operand
6227     and live to of the operand is upto the ifx only then */
6228     if (ic->next
6229         && ic->next->op == IFX
6230         && IC_COND(ic->next)->key == op->key
6231         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6232         ) {
6233                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6234           return ic->next;
6235     }
6236
6237     if (ic->next &&
6238         ic->next->op == IFX &&
6239         IC_COND(ic->next)->key == op->key) {
6240       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6241       return ic->next;
6242     }
6243
6244     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6245     if (ic->next &&
6246         ic->next->op == IFX)
6247       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6248
6249     if (ic->next &&
6250         ic->next->op == IFX &&
6251         IC_COND(ic->next)->key == op->key) {
6252       DEBUGpic16_emitcode ("; "," key is okay");
6253       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6254                            OP_SYMBOL(op)->liveTo,
6255                            ic->next->seq);
6256     }
6257
6258 #if 0
6259     /* the code below is completely untested
6260      * it just allows ulong2fs.c compile -- VR */
6261          
6262     ic = ic->next;
6263     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6264                                         __FILE__, __FUNCTION__, __LINE__);
6265         
6266     /* if this has register type condition and
6267     the next instruction is ifx with the same operand
6268     and live to of the operand is upto the ifx only then */
6269     if (ic->next &&
6270         ic->next->op == IFX &&
6271         IC_COND(ic->next)->key == op->key &&
6272         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6273         return ic->next;
6274
6275     if (ic->next &&
6276         ic->next->op == IFX &&
6277         IC_COND(ic->next)->key == op->key) {
6278       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6279       return ic->next;
6280     }
6281
6282     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6283                                         __FILE__, __FUNCTION__, __LINE__);
6284
6285 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6286 #endif
6287
6288     return NULL;
6289 }
6290 /*-----------------------------------------------------------------*/
6291 /* genAndOp - for && operation                                     */
6292 /*-----------------------------------------------------------------*/
6293 static void genAndOp (iCode *ic)
6294 {
6295     operand *left,*right, *result;
6296 /*     symbol *tlbl; */
6297
6298     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6299     /* note here that && operations that are in an
6300     if statement are taken away by backPatchLabels
6301     only those used in arthmetic operations remain */
6302     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6303     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6304     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6305
6306     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6307
6308     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6309     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6310     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6311
6312     /* if both are bit variables */
6313 /*     if (AOP_TYPE(left) == AOP_CRY && */
6314 /*         AOP_TYPE(right) == AOP_CRY ) { */
6315 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6316 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6317 /*         pic16_outBitC(result); */
6318 /*     } else { */
6319 /*         tlbl = newiTempLabel(NULL); */
6320 /*         pic16_toBoolean(left);     */
6321 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6322 /*         pic16_toBoolean(right); */
6323 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6324 /*         pic16_outBitAcc(result); */
6325 /*     } */
6326
6327     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6328     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6329     pic16_freeAsmop(result,NULL,ic,TRUE);
6330 }
6331
6332
6333 /*-----------------------------------------------------------------*/
6334 /* genOrOp - for || operation                                      */
6335 /*-----------------------------------------------------------------*/
6336 /*
6337   tsd pic port -
6338   modified this code, but it doesn't appear to ever get called
6339 */
6340
6341 static void genOrOp (iCode *ic)
6342 {
6343     operand *left,*right, *result;
6344     symbol *tlbl;
6345
6346     /* note here that || operations that are in an
6347     if statement are taken away by backPatchLabels
6348     only those used in arthmetic operations remain */
6349     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6350     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6351     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6352     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6353
6354     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6355
6356     /* if both are bit variables */
6357     if (AOP_TYPE(left) == AOP_CRY &&
6358         AOP_TYPE(right) == AOP_CRY ) {
6359       pic16_emitcode("clrc","");
6360       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6361                AOP(left)->aopu.aop_dir,
6362                AOP(left)->aopu.aop_dir);
6363       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6364                AOP(right)->aopu.aop_dir,
6365                AOP(right)->aopu.aop_dir);
6366       pic16_emitcode("setc","");
6367
6368     } else {
6369         tlbl = newiTempLabel(NULL);
6370         pic16_toBoolean(left);
6371         emitSKPZ;
6372         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
6373         pic16_toBoolean(right);
6374         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6375
6376         pic16_outBitAcc(result);
6377     }
6378
6379     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6380     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6381     pic16_freeAsmop(result,NULL,ic,TRUE);            
6382 }
6383
6384 /*-----------------------------------------------------------------*/
6385 /* isLiteralBit - test if lit == 2^n                               */
6386 /*-----------------------------------------------------------------*/
6387 static int isLiteralBit(unsigned long lit)
6388 {
6389     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6390     0x100L,0x200L,0x400L,0x800L,
6391     0x1000L,0x2000L,0x4000L,0x8000L,
6392     0x10000L,0x20000L,0x40000L,0x80000L,
6393     0x100000L,0x200000L,0x400000L,0x800000L,
6394     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6395     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6396     int idx;
6397     
6398     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6399     for(idx = 0; idx < 32; idx++)
6400         if(lit == pw[idx])
6401             return idx+1;
6402     return 0;
6403 }
6404
6405 /*-----------------------------------------------------------------*/
6406 /* continueIfTrue -                                                */
6407 /*-----------------------------------------------------------------*/
6408 static void continueIfTrue (iCode *ic)
6409 {
6410     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6411     if(IC_TRUE(ic))
6412         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6413     ic->generated = 1;
6414 }
6415
6416 /*-----------------------------------------------------------------*/
6417 /* jmpIfTrue -                                                     */
6418 /*-----------------------------------------------------------------*/
6419 static void jumpIfTrue (iCode *ic)
6420 {
6421     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6422     if(!IC_TRUE(ic))
6423         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6424     ic->generated = 1;
6425 }
6426
6427 /*-----------------------------------------------------------------*/
6428 /* jmpTrueOrFalse -                                                */
6429 /*-----------------------------------------------------------------*/
6430 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6431 {
6432     // ugly but optimized by peephole
6433     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6434     if(IC_TRUE(ic)){
6435         symbol *nlbl = newiTempLabel(NULL);
6436         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6437         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6438         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6439         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6440     }
6441     else{
6442         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6443         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6444     }
6445     ic->generated = 1;
6446 }
6447
6448 /*-----------------------------------------------------------------*/
6449 /* genAnd  - code for and                                          */
6450 /*-----------------------------------------------------------------*/
6451 static void genAnd (iCode *ic, iCode *ifx)
6452 {
6453   operand *left, *right, *result;
6454   int size, offset=0;  
6455   unsigned long lit = 0L;
6456   int bytelit = 0;
6457   resolvedIfx rIfx;
6458
6459
6460   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6461   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6462   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6463   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6464
6465   resolveIfx(&rIfx,ifx);
6466
6467   /* if left is a literal & right is not then exchange them */
6468   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6469       AOP_NEEDSACC(left)) {
6470     operand *tmp = right ;
6471     right = left;
6472     left = tmp;
6473   }
6474
6475   /* if result = right then exchange them */
6476   if(pic16_sameRegs(AOP(result),AOP(right))){
6477     operand *tmp = right ;
6478     right = left;
6479     left = tmp;
6480   }
6481
6482   /* if right is bit then exchange them */
6483   if (AOP_TYPE(right) == AOP_CRY &&
6484       AOP_TYPE(left) != AOP_CRY){
6485     operand *tmp = right ;
6486     right = left;
6487     left = tmp;
6488   }
6489   if(AOP_TYPE(right) == AOP_LIT)
6490     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6491
6492   size = AOP_SIZE(result);
6493
6494   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6495
6496   // if(bit & yy)
6497   // result = bit & yy;
6498   if (AOP_TYPE(left) == AOP_CRY){
6499     // c = bit & literal;
6500     if(AOP_TYPE(right) == AOP_LIT){
6501       if(lit & 1) {
6502         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6503           // no change
6504           goto release;
6505         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6506       } else {
6507         // bit(result) = 0;
6508         if(size && (AOP_TYPE(result) == AOP_CRY)){
6509           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6510           goto release;
6511         }
6512         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6513           jumpIfTrue(ifx);
6514           goto release;
6515         }
6516         pic16_emitcode("clr","c");
6517       }
6518     } else {
6519       if (AOP_TYPE(right) == AOP_CRY){
6520         // c = bit & bit;
6521         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6522         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6523       } else {
6524         // c = bit & val;
6525         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6526         // c = lsb
6527         pic16_emitcode("rrc","a");
6528         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6529       }
6530     }
6531     // bit = c
6532     // val = c
6533     if(size)
6534       pic16_outBitC(result);
6535     // if(bit & ...)
6536     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6537       genIfxJump(ifx, "c");           
6538     goto release ;
6539   }
6540
6541   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6542   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6543   if((AOP_TYPE(right) == AOP_LIT) &&
6544      (AOP_TYPE(result) == AOP_CRY) &&
6545      (AOP_TYPE(left) != AOP_CRY)){
6546     int posbit = isLiteralBit(lit);
6547     /* left &  2^n */
6548     if(posbit){
6549       posbit--;
6550       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6551       // bit = left & 2^n
6552       if(size)
6553         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6554       // if(left &  2^n)
6555       else{
6556         if(ifx){
6557 /*
6558           if(IC_TRUE(ifx)) {
6559             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6560             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6561           } else {
6562             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6563             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6564           }
6565 */
6566         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6567         size = AOP_SIZE(left);
6568
6569         {
6570           int bp = posbit, ofs=0;
6571           
6572             while(bp > 7) {
6573               bp -= 8;
6574               ofs++;
6575             }
6576         
6577           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6578                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
6579
6580         }
6581 /*
6582           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6583                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6584 */
6585           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6586           
6587           ifx->generated = 1;
6588         }
6589         goto release;
6590       }
6591     } else {
6592       symbol *tlbl = newiTempLabel(NULL);
6593       int sizel = AOP_SIZE(left);
6594       if(size)
6595         pic16_emitcode("setb","c");
6596       while(sizel--){
6597         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6598           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6599           // byte ==  2^n ?
6600           if((posbit = isLiteralBit(bytelit)) != 0)
6601             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6602           else{
6603             if(bytelit != 0x0FFL)
6604               pic16_emitcode("anl","a,%s",
6605                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6606             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6607           }
6608         }
6609         offset++;
6610       }
6611       // bit = left & literal
6612       if(size){
6613         pic16_emitcode("clr","c");
6614         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6615       }
6616       // if(left & literal)
6617       else{
6618         if(ifx)
6619           jmpTrueOrFalse(ifx, tlbl);
6620         goto release ;
6621       }
6622     }
6623     pic16_outBitC(result);
6624     goto release ;
6625   }
6626
6627   /* if left is same as result */
6628   if(pic16_sameRegs(AOP(result),AOP(left))){
6629     int know_W = -1;
6630     for(;size--; offset++,lit>>=8) {
6631       if(AOP_TYPE(right) == AOP_LIT){
6632         switch(lit & 0xff) {
6633         case 0x00:
6634           /*  and'ing with 0 has clears the result */
6635 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6636           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6637           break;
6638         case 0xff:
6639           /* and'ing with 0xff is a nop when the result and left are the same */
6640           break;
6641
6642         default:
6643           {
6644             int p = my_powof2( (~lit) & 0xff );
6645             if(p>=0) {
6646               /* only one bit is set in the literal, so use a bcf instruction */
6647 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6648               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6649
6650             } else {
6651               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6652               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6653               if(know_W != (lit&0xff))
6654                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6655               know_W = lit &0xff;
6656               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6657             }
6658           }    
6659         }
6660       } else {
6661         if (AOP_TYPE(left) == AOP_ACC) {
6662           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6663         } else {                    
6664           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6665           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6666
6667         }
6668       }
6669     }
6670
6671   } else {
6672     // left & result in different registers
6673     if(AOP_TYPE(result) == AOP_CRY){
6674       // result = bit
6675       // if(size), result in bit
6676       // if(!size && ifx), conditional oper: if(left & right)
6677       symbol *tlbl = newiTempLabel(NULL);
6678       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6679       if(size)
6680         pic16_emitcode("setb","c");
6681       while(sizer--){
6682         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6683         pic16_emitcode("anl","a,%s",
6684                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6685         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6686         offset++;
6687       }
6688       if(size){
6689         CLRC;
6690         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6691         pic16_outBitC(result);
6692       } else if(ifx)
6693         jmpTrueOrFalse(ifx, tlbl);
6694     } else {
6695       for(;(size--);offset++) {
6696         // normal case
6697         // result = left & right
6698         if(AOP_TYPE(right) == AOP_LIT){
6699           int t = (lit >> (offset*8)) & 0x0FFL;
6700           switch(t) { 
6701           case 0x00:
6702             pic16_emitcode("clrf","%s",
6703                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6704             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6705             break;
6706           case 0xff:
6707             pic16_emitcode("movf","%s,w",
6708                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6709             pic16_emitcode("movwf","%s",
6710                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6711             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6712             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6713             break;
6714           default:
6715             pic16_emitcode("movlw","0x%x",t);
6716             pic16_emitcode("andwf","%s,w",
6717                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6718             pic16_emitcode("movwf","%s",
6719                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6720               
6721             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6722             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6723             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6724           }
6725           continue;
6726         }
6727
6728         if (AOP_TYPE(left) == AOP_ACC) {
6729           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6730           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6731         } else {
6732           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6733           pic16_emitcode("andwf","%s,w",
6734                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6735           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6736           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6737         }
6738         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6739         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6740       }
6741     }
6742   }
6743
6744   release :
6745     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6746   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6747   pic16_freeAsmop(result,NULL,ic,TRUE);     
6748 }
6749
6750 /*-----------------------------------------------------------------*/
6751 /* genOr  - code for or                                            */
6752 /*-----------------------------------------------------------------*/
6753 static void genOr (iCode *ic, iCode *ifx)
6754 {
6755     operand *left, *right, *result;
6756     int size, offset=0;
6757     unsigned long lit = 0L;
6758
6759     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6760
6761     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6762     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6763     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6764
6765     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6766
6767     /* if left is a literal & right is not then exchange them */
6768     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6769         AOP_NEEDSACC(left)) {
6770         operand *tmp = right ;
6771         right = left;
6772         left = tmp;
6773     }
6774
6775     /* if result = right then exchange them */
6776     if(pic16_sameRegs(AOP(result),AOP(right))){
6777         operand *tmp = right ;
6778         right = left;
6779         left = tmp;
6780     }
6781
6782     /* if right is bit then exchange them */
6783     if (AOP_TYPE(right) == AOP_CRY &&
6784         AOP_TYPE(left) != AOP_CRY){
6785         operand *tmp = right ;
6786         right = left;
6787         left = tmp;
6788     }
6789
6790     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6791
6792     if(AOP_TYPE(right) == AOP_LIT)
6793         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6794
6795     size = AOP_SIZE(result);
6796
6797     // if(bit | yy)
6798     // xx = bit | yy;
6799     if (AOP_TYPE(left) == AOP_CRY){
6800         if(AOP_TYPE(right) == AOP_LIT){
6801             // c = bit & literal;
6802             if(lit){
6803                 // lit != 0 => result = 1
6804                 if(AOP_TYPE(result) == AOP_CRY){
6805                   if(size)
6806                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6807                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6808                   //     AOP(result)->aopu.aop_dir,
6809                   //     AOP(result)->aopu.aop_dir);
6810                     else if(ifx)
6811                         continueIfTrue(ifx);
6812                     goto release;
6813                 }
6814             } else {
6815                 // lit == 0 => result = left
6816                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6817                     goto release;
6818                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6819             }
6820         } else {
6821             if (AOP_TYPE(right) == AOP_CRY){
6822               if(pic16_sameRegs(AOP(result),AOP(left))){
6823                 // c = bit | bit;
6824                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6825                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6826                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6827
6828                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6829                          AOP(result)->aopu.aop_dir,
6830                          AOP(result)->aopu.aop_dir);
6831                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6832                          AOP(right)->aopu.aop_dir,
6833                          AOP(right)->aopu.aop_dir);
6834                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6835                          AOP(result)->aopu.aop_dir,
6836                          AOP(result)->aopu.aop_dir);
6837               } else {
6838                 if( AOP_TYPE(result) == AOP_ACC) {
6839                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6840                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6841                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6842                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6843
6844                 } else {
6845
6846                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6847                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6848                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6849                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6850
6851                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6852                                  AOP(result)->aopu.aop_dir,
6853                                  AOP(result)->aopu.aop_dir);
6854                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6855                                  AOP(right)->aopu.aop_dir,
6856                                  AOP(right)->aopu.aop_dir);
6857                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6858                                  AOP(left)->aopu.aop_dir,
6859                                  AOP(left)->aopu.aop_dir);
6860                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6861                                  AOP(result)->aopu.aop_dir,
6862                                  AOP(result)->aopu.aop_dir);
6863                 }
6864               }
6865             } else {
6866                 // c = bit | val;
6867                 symbol *tlbl = newiTempLabel(NULL);
6868                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6869
6870
6871                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6872                 if( AOP_TYPE(right) == AOP_ACC) {
6873                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6874                   emitSKPNZ;
6875                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6876                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6877                 }
6878
6879
6880
6881                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6882                     pic16_emitcode(";XXX setb","c");
6883                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6884                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6885                 pic16_toBoolean(right);
6886                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6887                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6888                     jmpTrueOrFalse(ifx, tlbl);
6889                     goto release;
6890                 } else {
6891                     CLRC;
6892                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6893                 }
6894             }
6895         }
6896         // bit = c
6897         // val = c
6898         if(size)
6899             pic16_outBitC(result);
6900         // if(bit | ...)
6901         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6902             genIfxJump(ifx, "c");           
6903         goto release ;
6904     }
6905
6906     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6907     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6908     if((AOP_TYPE(right) == AOP_LIT) &&
6909        (AOP_TYPE(result) == AOP_CRY) &&
6910        (AOP_TYPE(left) != AOP_CRY)){
6911         if(lit){
6912           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6913             // result = 1
6914             if(size)
6915                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6916             else 
6917                 continueIfTrue(ifx);
6918             goto release;
6919         } else {
6920           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6921             // lit = 0, result = boolean(left)
6922             if(size)
6923                 pic16_emitcode(";XXX setb","c");
6924             pic16_toBoolean(right);
6925             if(size){
6926                 symbol *tlbl = newiTempLabel(NULL);
6927                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6928                 CLRC;
6929                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6930             } else {
6931                 genIfxJump (ifx,"a");
6932                 goto release;
6933             }
6934         }
6935         pic16_outBitC(result);
6936         goto release ;
6937     }
6938
6939     /* if left is same as result */
6940     if(pic16_sameRegs(AOP(result),AOP(left))){
6941       int know_W = -1;
6942       for(;size--; offset++,lit>>=8) {
6943         if(AOP_TYPE(right) == AOP_LIT){
6944           if((lit & 0xff) == 0)
6945             /*  or'ing with 0 has no effect */
6946             continue;
6947           else {
6948             int p = my_powof2(lit & 0xff);
6949             if(p>=0) {
6950               /* only one bit is set in the literal, so use a bsf instruction */
6951               pic16_emitpcode(POC_BSF,
6952                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
6953             } else {
6954               if(know_W != (lit & 0xff))
6955                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6956               know_W = lit & 0xff;
6957               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6958             }
6959                     
6960           }
6961         } else {
6962           if (AOP_TYPE(left) == AOP_ACC) {
6963             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6964             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6965           } else {                  
6966             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6967             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6968
6969             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6970             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6971
6972           }
6973         }
6974       }
6975     } else {
6976         // left & result in different registers
6977         if(AOP_TYPE(result) == AOP_CRY){
6978             // result = bit
6979             // if(size), result in bit
6980             // if(!size && ifx), conditional oper: if(left | right)
6981             symbol *tlbl = newiTempLabel(NULL);
6982             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6983             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6984
6985
6986             if(size)
6987                 pic16_emitcode(";XXX setb","c");
6988             while(sizer--){
6989                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6990                 pic16_emitcode(";XXX orl","a,%s",
6991                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6992                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6993                 offset++;
6994             }
6995             if(size){
6996                 CLRC;
6997                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6998                 pic16_outBitC(result);
6999             } else if(ifx)
7000                 jmpTrueOrFalse(ifx, tlbl);
7001         } else for(;(size--);offset++){
7002           // normal case
7003           // result = left & right
7004           if(AOP_TYPE(right) == AOP_LIT){
7005             int t = (lit >> (offset*8)) & 0x0FFL;
7006             switch(t) { 
7007             case 0x00:
7008               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7009               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7010
7011               pic16_emitcode("movf","%s,w",
7012                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7013               pic16_emitcode("movwf","%s",
7014                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7015               break;
7016             default:
7017               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7018               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7019               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7020
7021               pic16_emitcode("movlw","0x%x",t);
7022               pic16_emitcode("iorwf","%s,w",
7023                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7024               pic16_emitcode("movwf","%s",
7025                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7026               
7027             }
7028             continue;
7029           }
7030
7031           // faster than result <- left, anl result,right
7032           // and better if result is SFR
7033           if (AOP_TYPE(left) == AOP_ACC) {
7034             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7035             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7036           } else {
7037             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7038             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7039
7040             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7041             pic16_emitcode("iorwf","%s,w",
7042                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7043           }
7044           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7045           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7046         }
7047     }
7048
7049 release :
7050     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7051     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7052     pic16_freeAsmop(result,NULL,ic,TRUE);     
7053 }
7054
7055 /*-----------------------------------------------------------------*/
7056 /* genXor - code for xclusive or                                   */
7057 /*-----------------------------------------------------------------*/
7058 static void genXor (iCode *ic, iCode *ifx)
7059 {
7060   operand *left, *right, *result;
7061   int size, offset=0;
7062   unsigned long lit = 0L;
7063
7064   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7065
7066   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7067   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7068   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7069
7070   /* if left is a literal & right is not ||
7071      if left needs acc & right does not */
7072   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7073       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7074     operand *tmp = right ;
7075     right = left;
7076     left = tmp;
7077   }
7078
7079   /* if result = right then exchange them */
7080   if(pic16_sameRegs(AOP(result),AOP(right))){
7081     operand *tmp = right ;
7082     right = left;
7083     left = tmp;
7084   }
7085
7086   /* if right is bit then exchange them */
7087   if (AOP_TYPE(right) == AOP_CRY &&
7088       AOP_TYPE(left) != AOP_CRY){
7089     operand *tmp = right ;
7090     right = left;
7091     left = tmp;
7092   }
7093   if(AOP_TYPE(right) == AOP_LIT)
7094     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7095
7096   size = AOP_SIZE(result);
7097
7098   // if(bit ^ yy)
7099   // xx = bit ^ yy;
7100   if (AOP_TYPE(left) == AOP_CRY){
7101     if(AOP_TYPE(right) == AOP_LIT){
7102       // c = bit & literal;
7103       if(lit>>1){
7104         // lit>>1  != 0 => result = 1
7105         if(AOP_TYPE(result) == AOP_CRY){
7106           if(size)
7107             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7108             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7109           else if(ifx)
7110             continueIfTrue(ifx);
7111           goto release;
7112         }
7113         pic16_emitcode("setb","c");
7114       } else{
7115         // lit == (0 or 1)
7116         if(lit == 0){
7117           // lit == 0, result = left
7118           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7119             goto release;
7120           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7121         } else{
7122           // lit == 1, result = not(left)
7123           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7124             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7125             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7126             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7127             goto release;
7128           } else {
7129             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7130             pic16_emitcode("cpl","c");
7131           }
7132         }
7133       }
7134
7135     } else {
7136       // right != literal
7137       symbol *tlbl = newiTempLabel(NULL);
7138       if (AOP_TYPE(right) == AOP_CRY){
7139         // c = bit ^ bit;
7140         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7141       }
7142       else{
7143         int sizer = AOP_SIZE(right);
7144         // c = bit ^ val
7145         // if val>>1 != 0, result = 1
7146         pic16_emitcode("setb","c");
7147         while(sizer){
7148           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7149           if(sizer == 1)
7150             // test the msb of the lsb
7151             pic16_emitcode("anl","a,#0xfe");
7152           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7153           sizer--;
7154         }
7155         // val = (0,1)
7156         pic16_emitcode("rrc","a");
7157       }
7158       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7159       pic16_emitcode("cpl","c");
7160       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7161     }
7162     // bit = c
7163     // val = c
7164     if(size)
7165       pic16_outBitC(result);
7166     // if(bit | ...)
7167     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7168       genIfxJump(ifx, "c");           
7169     goto release ;
7170   }
7171
7172   if(pic16_sameRegs(AOP(result),AOP(left))){
7173     /* if left is same as result */
7174     for(;size--; offset++) {
7175       if(AOP_TYPE(right) == AOP_LIT){
7176         int t  = (lit >> (offset*8)) & 0x0FFL;
7177         if(t == 0x00L)
7178           continue;
7179         else
7180           if (IS_AOP_PREG(left)) {
7181             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7182             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7183             pic16_aopPut(AOP(result),"a",offset);
7184           } else {
7185             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7186             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7187             pic16_emitcode("xrl","%s,%s",
7188                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
7189                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7190           }
7191       } else {
7192         if (AOP_TYPE(left) == AOP_ACC)
7193           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7194         else {
7195           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7196           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7197 /*
7198           if (IS_AOP_PREG(left)) {
7199             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7200             pic16_aopPut(AOP(result),"a",offset);
7201           } else
7202             pic16_emitcode("xrl","%s,a",
7203                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7204 */
7205         }
7206       }
7207     }
7208   } else {
7209     // left & result in different registers
7210     if(AOP_TYPE(result) == AOP_CRY){
7211       // result = bit
7212       // if(size), result in bit
7213       // if(!size && ifx), conditional oper: if(left ^ right)
7214       symbol *tlbl = newiTempLabel(NULL);
7215       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7216       if(size)
7217         pic16_emitcode("setb","c");
7218       while(sizer--){
7219         if((AOP_TYPE(right) == AOP_LIT) &&
7220            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7221           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7222         } else {
7223           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7224           pic16_emitcode("xrl","a,%s",
7225                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7226         }
7227         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7228         offset++;
7229       }
7230       if(size){
7231         CLRC;
7232         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7233         pic16_outBitC(result);
7234       } else if(ifx)
7235         jmpTrueOrFalse(ifx, tlbl);
7236     } else for(;(size--);offset++){
7237       // normal case
7238       // result = left & right
7239       if(AOP_TYPE(right) == AOP_LIT){
7240         int t = (lit >> (offset*8)) & 0x0FFL;
7241         switch(t) { 
7242         case 0x00:
7243           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7244           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7245           pic16_emitcode("movf","%s,w",
7246                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7247           pic16_emitcode("movwf","%s",
7248                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7249           break;
7250         case 0xff:
7251           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7252           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7253           pic16_emitcode("comf","%s,w",
7254                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7255           pic16_emitcode("movwf","%s",
7256                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7257           break;
7258         default:
7259           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7260           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7261           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7262           pic16_emitcode("movlw","0x%x",t);
7263           pic16_emitcode("xorwf","%s,w",
7264                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7265           pic16_emitcode("movwf","%s",
7266                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7267
7268         }
7269         continue;
7270       }
7271
7272       // faster than result <- left, anl result,right
7273       // and better if result is SFR
7274       if (AOP_TYPE(left) == AOP_ACC) {
7275         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7276         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7277       } else {
7278         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7279         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7280         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7281         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7282       }
7283       if ( AOP_TYPE(result) != AOP_ACC){
7284         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7285         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7286       }
7287     }
7288   }
7289
7290   release :
7291     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7292   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7293   pic16_freeAsmop(result,NULL,ic,TRUE);     
7294 }
7295
7296 /*-----------------------------------------------------------------*/
7297 /* genInline - write the inline code out                           */
7298 /*-----------------------------------------------------------------*/
7299 static void genInline (iCode *ic)
7300 {
7301   char *buffer, *bp, *bp1;
7302     
7303         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7304
7305         _G.inLine += (!options.asmpeep);
7306
7307         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7308         strcpy(buffer,IC_INLINE(ic));
7309
7310 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7311
7312         /* emit each line as a code */
7313         while (*bp) {
7314                 if (*bp == '\n') {
7315                         *bp++ = '\0';
7316
7317                         if(*bp1)
7318                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7319                         bp1 = bp;
7320                 } else {
7321                         if (*bp == ':') {
7322                                 bp++;
7323                                 *bp = '\0';
7324                                 bp++;
7325
7326                                 /* print label, use this special format with NULL directive
7327                                  * to denote that the argument should not be indented with tab */
7328                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7329                                 bp1 = bp;
7330                         } else
7331                                 bp++;
7332                 }
7333         }
7334
7335         if ((bp1 != bp) && *bp1)
7336                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7337
7338
7339     Safe_free(buffer);
7340
7341     _G.inLine -= (!options.asmpeep);
7342 }
7343
7344 /*-----------------------------------------------------------------*/
7345 /* genRRC - rotate right with carry                                */
7346 /*-----------------------------------------------------------------*/
7347 static void genRRC (iCode *ic)
7348 {
7349   operand *left , *result ;
7350   int size, offset = 0, same;
7351
7352   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7353
7354   /* rotate right with carry */
7355   left = IC_LEFT(ic);
7356   result=IC_RESULT(ic);
7357   pic16_aopOp (left,ic,FALSE);
7358   pic16_aopOp (result,ic,FALSE);
7359
7360   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7361
7362   same = pic16_sameRegs(AOP(result),AOP(left));
7363
7364   size = AOP_SIZE(result);    
7365
7366   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7367
7368   /* get the lsb and put it into the carry */
7369   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7370
7371   offset = 0 ;
7372
7373   while(size--) {
7374
7375     if(same) {
7376       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7377     } else {
7378       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7379       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7380     }
7381
7382     offset++;
7383   }
7384
7385   pic16_freeAsmop(left,NULL,ic,TRUE);
7386   pic16_freeAsmop(result,NULL,ic,TRUE);
7387 }
7388
7389 /*-----------------------------------------------------------------*/
7390 /* genRLC - generate code for rotate left with carry               */
7391 /*-----------------------------------------------------------------*/
7392 static void genRLC (iCode *ic)
7393 {    
7394   operand *left , *result ;
7395   int size, offset = 0;
7396   int same;
7397
7398   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7399   /* rotate right with carry */
7400   left = IC_LEFT(ic);
7401   result=IC_RESULT(ic);
7402   pic16_aopOp (left,ic,FALSE);
7403   pic16_aopOp (result,ic,FALSE);
7404
7405   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7406
7407   same = pic16_sameRegs(AOP(result),AOP(left));
7408
7409   /* move it to the result */
7410   size = AOP_SIZE(result);    
7411
7412   /* get the msb and put it into the carry */
7413   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7414
7415   offset = 0 ;
7416
7417   while(size--) {
7418
7419     if(same) {
7420       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7421     } else {
7422       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7423       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7424     }
7425
7426     offset++;
7427   }
7428
7429
7430   pic16_freeAsmop(left,NULL,ic,TRUE);
7431   pic16_freeAsmop(result,NULL,ic,TRUE);
7432 }
7433
7434
7435 /* gpasm can get the highest order bit with HIGH/UPPER
7436  * so the following probably is not needed -- VR */
7437  
7438 /*-----------------------------------------------------------------*/
7439 /* genGetHbit - generates code get highest order bit               */
7440 /*-----------------------------------------------------------------*/
7441 static void genGetHbit (iCode *ic)
7442 {
7443     operand *left, *result;
7444     left = IC_LEFT(ic);
7445     result=IC_RESULT(ic);
7446     pic16_aopOp (left,ic,FALSE);
7447     pic16_aopOp (result,ic,FALSE);
7448
7449     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7450     /* get the highest order byte into a */
7451     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7452     if(AOP_TYPE(result) == AOP_CRY){
7453         pic16_emitcode("rlc","a");
7454         pic16_outBitC(result);
7455     }
7456     else{
7457         pic16_emitcode("rl","a");
7458         pic16_emitcode("anl","a,#0x01");
7459         pic16_outAcc(result);
7460     }
7461
7462
7463     pic16_freeAsmop(left,NULL,ic,TRUE);
7464     pic16_freeAsmop(result,NULL,ic,TRUE);
7465 }
7466
7467 #if 0
7468 /*-----------------------------------------------------------------*/
7469 /* AccRol - rotate left accumulator by known count                 */
7470 /*-----------------------------------------------------------------*/
7471 static void AccRol (int shCount)
7472 {
7473     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7474     shCount &= 0x0007;              // shCount : 0..7
7475     switch(shCount){
7476         case 0 :
7477             break;
7478         case 1 :
7479             pic16_emitcode("rl","a");
7480             break;
7481         case 2 :
7482             pic16_emitcode("rl","a");
7483             pic16_emitcode("rl","a");
7484             break;
7485         case 3 :
7486             pic16_emitcode("swap","a");
7487             pic16_emitcode("rr","a");
7488             break;
7489         case 4 :
7490             pic16_emitcode("swap","a");
7491             break;
7492         case 5 :
7493             pic16_emitcode("swap","a");
7494             pic16_emitcode("rl","a");
7495             break;
7496         case 6 :
7497             pic16_emitcode("rr","a");
7498             pic16_emitcode("rr","a");
7499             break;
7500         case 7 :
7501             pic16_emitcode("rr","a");
7502             break;
7503     }
7504 }
7505 #endif
7506
7507 /*-----------------------------------------------------------------*/
7508 /* AccLsh - left shift accumulator by known count                  */
7509 /*-----------------------------------------------------------------*/
7510 static void AccLsh (int shCount)
7511 {
7512         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7513         switch(shCount){
7514                 case 0 :
7515                         return;
7516                         break;
7517                 case 1 :
7518                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7519                         break;
7520                 case 2 :
7521                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7522                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7523                         break;
7524                 case 3 :
7525                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7526                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7527                         break;
7528                 case 4 :
7529                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7530                         break;
7531                 case 5 :
7532                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7533                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7534                         break;
7535                 case 6 :
7536                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7537                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7538                         break;
7539                 case 7 :
7540                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7541                         break;
7542         }
7543
7544         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7545 }
7546
7547 /*-----------------------------------------------------------------*/
7548 /* AccRsh - right shift accumulator by known count                 */
7549 /*-----------------------------------------------------------------*/
7550 static void AccRsh (int shCount, int andmask)
7551 {
7552         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7553         switch(shCount){
7554                 case 0 :
7555                         return; break;
7556                 case 1 :
7557                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7558 //                      andmask = 0;    /* no need */
7559                         break;
7560                 case 2 :
7561                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7562                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7563 //                      andmask = 0;    /* no need */
7564                         break;
7565                 case 3 :
7566                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7567                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7568                         break;
7569                 case 4 :
7570                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7571                         break;
7572                 case 5 :
7573                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7574                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7575                         break;
7576                 case 6 :
7577                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7578                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7579                         break;
7580                 case 7 :
7581                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7582                         break;
7583         }
7584         
7585         if(andmask)
7586                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7587         else
7588                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7589 }
7590
7591 #if 0
7592 /*-----------------------------------------------------------------*/
7593 /* AccSRsh - signed right shift accumulator by known count                 */
7594 /*-----------------------------------------------------------------*/
7595 static void AccSRsh (int shCount)
7596 {
7597     symbol *tlbl ;
7598     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7599     if(shCount != 0){
7600         if(shCount == 1){
7601             pic16_emitcode("mov","c,acc.7");
7602             pic16_emitcode("rrc","a");
7603         } else if(shCount == 2){
7604             pic16_emitcode("mov","c,acc.7");
7605             pic16_emitcode("rrc","a");
7606             pic16_emitcode("mov","c,acc.7");
7607             pic16_emitcode("rrc","a");
7608         } else {
7609             tlbl = newiTempLabel(NULL);
7610             /* rotate right accumulator */
7611             AccRol(8 - shCount);
7612             /* and kill the higher order bits */
7613             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7614             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7615             pic16_emitcode("orl","a,#0x%02x",
7616                      (unsigned char)~SRMask[shCount]);
7617             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7618         }
7619     }
7620 }
7621 #endif
7622 /*-----------------------------------------------------------------*/
7623 /* shiftR1Left2Result - shift right one byte from left to result   */
7624 /*-----------------------------------------------------------------*/
7625 static void shiftR1Left2ResultSigned (operand *left, int offl,
7626                                 operand *result, int offr,
7627                                 int shCount)
7628 {
7629   int same;
7630
7631   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7632
7633   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7634
7635   switch(shCount) {
7636   case 1:
7637     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7638     if(same) 
7639       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7640     else {
7641       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7642       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7643     }
7644
7645     break;
7646   case 2:
7647
7648     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7649     if(same) 
7650       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7651     else {
7652       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7653       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7654     }
7655     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7656     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7657
7658     break;
7659
7660   case 3:
7661     if(same)
7662       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7663     else {
7664       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7665       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7666     }
7667
7668     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7669     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7670     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7671
7672     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7673     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7674
7675     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7676     break;
7677
7678   case 4:
7679     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7680     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7681     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7682     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7683     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7684     break;
7685   case 5:
7686     if(same) {
7687       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7688     } else {
7689       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7690       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7691     }
7692     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7693     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7694     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
7695     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7696     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7697     break;
7698
7699   case 6:
7700     if(same) {
7701       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7702       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7703       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7704       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7705       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7706       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7707     } else {
7708       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7709       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7710       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7711       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
7712       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
7713     }
7714     break;
7715
7716   case 7:
7717     if(same) {
7718       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7719       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7720       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7721       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7722     } else {
7723       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7724       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
7725       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7726     }
7727
7728   default:
7729     break;
7730   }
7731 }
7732
7733 /*-----------------------------------------------------------------*/
7734 /* shiftR1Left2Result - shift right one byte from left to result   */
7735 /*-----------------------------------------------------------------*/
7736 static void shiftR1Left2Result (operand *left, int offl,
7737                                 operand *result, int offr,
7738                                 int shCount, int sign)
7739 {
7740   int same;
7741
7742   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7743
7744   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7745
7746   /* Copy the msb into the carry if signed. */
7747   if(sign) {
7748     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7749     return;
7750   }
7751
7752
7753
7754   switch(shCount) {
7755   case 1:
7756     emitCLRC;
7757     if(same) 
7758       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7759     else {
7760       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7761       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7762     }
7763     break;
7764   case 2:
7765     emitCLRC;
7766     if(same) {
7767       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7768     } else {
7769       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7770       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7771     }
7772     emitCLRC;
7773     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7774
7775     break;
7776   case 3:
7777     if(same)
7778       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7779     else {
7780       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7781       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7782     }
7783
7784     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7785     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7786     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7787     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7788     break;
7789       
7790   case 4:
7791     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7792     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7793     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7794     break;
7795
7796   case 5:
7797     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7798     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7799     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7800     emitCLRC;
7801     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7802
7803     break;
7804   case 6:
7805
7806     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7807     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7808     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7809     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7810     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7811     break;
7812
7813   case 7:
7814
7815     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7816     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7817     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7818
7819     break;
7820
7821   default:
7822     break;
7823   }
7824 }
7825
7826 /*-----------------------------------------------------------------*/
7827 /* shiftL1Left2Result - shift left one byte from left to result    */
7828 /*-----------------------------------------------------------------*/
7829 static void shiftL1Left2Result (operand *left, int offl,
7830                                 operand *result, int offr, int shCount)
7831 {
7832   int same;
7833
7834   //    char *l;
7835   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7836
7837   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7838   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7839     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7840     //    MOVA(l);
7841     /* shift left accumulator */
7842     //AccLsh(shCount); // don't comment out just yet...
7843   //    pic16_aopPut(AOP(result),"a",offr);
7844
7845   switch(shCount) {
7846   case 1:
7847     /* Shift left 1 bit position */
7848     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7849     if(same) {
7850       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7851     } else {
7852       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7853       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7854     }
7855     break;
7856   case 2:
7857     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7858     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7859     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7860     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7861     break;
7862   case 3:
7863     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7864     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7865     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7866     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7867     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7868     break;
7869   case 4:
7870     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7871     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7872     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7873     break;
7874   case 5:
7875     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7876     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7877     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7878     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7879     break;
7880   case 6:
7881     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7882     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7883     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7884     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7885     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7886     break;
7887   case 7:
7888     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7889     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7890     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7891     break;
7892
7893   default:
7894     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7895   }
7896
7897 }
7898
7899 /*-----------------------------------------------------------------*/
7900 /* movLeft2Result - move byte from left to result                  */
7901 /*-----------------------------------------------------------------*/
7902 static void movLeft2Result (operand *left, int offl,
7903                             operand *result, int offr)
7904 {
7905   char *l;
7906   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7907   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7908     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7909
7910     if (*l == '@' && (IS_AOP_PREG(result))) {
7911       pic16_emitcode("mov","a,%s",l);
7912       pic16_aopPut(AOP(result),"a",offr);
7913     } else {
7914       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7915       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7916     }
7917   }
7918 }
7919
7920 /*-----------------------------------------------------------------*/
7921 /* shiftL2Left2Result - shift left two bytes from left to result   */
7922 /*-----------------------------------------------------------------*/
7923 static void shiftL2Left2Result (operand *left, int offl,
7924                                 operand *result, int offr, int shCount)
7925 {
7926   int same = pic16_sameRegs(AOP(result), AOP(left));
7927   int i;
7928
7929   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7930
7931   if (same && (offl != offr)) { // shift bytes
7932     if (offr > offl) {
7933        for(i=1;i>-1;i--) {
7934          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7935          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7936        }
7937     } else { // just treat as different later on
7938                 same = 0;
7939     }
7940   }
7941
7942   if(same) {
7943     switch(shCount) {
7944     case 0:
7945       break;
7946     case 1:
7947     case 2:
7948     case 3:
7949
7950       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7951       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7952       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7953
7954       while(--shCount) {
7955                 emitCLRC;
7956                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7957                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7958       }
7959
7960       break;
7961     case 4:
7962     case 5:
7963       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7964       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7965       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7966       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7967       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7968       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7969       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7970       if(shCount >=5) {
7971                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7972                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7973       }
7974       break;
7975     case 6:
7976       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7977       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7978       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7979       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7980       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7981       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7982       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7983       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7984       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7985       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7986       break;
7987     case 7:
7988       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7989       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7990       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7991       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7992       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7993     }
7994
7995   } else {
7996     switch(shCount) {
7997     case 0:
7998       break;
7999     case 1:
8000     case 2:
8001     case 3:
8002       /* note, use a mov/add for the shift since the mov has a
8003          chance of getting optimized out */
8004       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8005       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8006       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8007       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8008       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8009
8010       while(--shCount) {
8011                 emitCLRC;
8012                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8013                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8014       }
8015       break;
8016
8017     case 4:
8018     case 5:
8019       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8020       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8021       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8022       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8023       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8024       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8025       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8026       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8027
8028
8029       if(shCount == 5) {
8030                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8031                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8032       }
8033       break;
8034     case 6:
8035       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8036       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8037       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8038       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8039
8040       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8041       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8042       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8043       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8044       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8045       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8046       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8047       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8048       break;
8049     case 7:
8050       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8051       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8052       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8053       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8054       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8055     }
8056   }
8057
8058 }
8059 /*-----------------------------------------------------------------*/
8060 /* shiftR2Left2Result - shift right two bytes from left to result  */
8061 /*-----------------------------------------------------------------*/
8062 static void shiftR2Left2Result (operand *left, int offl,
8063                                 operand *result, int offr,
8064                                 int shCount, int sign)
8065 {
8066   int same = pic16_sameRegs(AOP(result), AOP(left));
8067   int i;
8068   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8069
8070   if (same && (offl != offr)) { // shift right bytes
8071     if (offr < offl) {
8072        for(i=0;i<2;i++) {
8073          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8074          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8075        }
8076     } else { // just treat as different later on
8077                 same = 0;
8078     }
8079   }
8080
8081   switch(shCount) {
8082   case 0:
8083     break;
8084   case 1:
8085   case 2:
8086   case 3:
8087     if(sign)
8088       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8089     else
8090       emitCLRC;
8091
8092     if(same) {
8093       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8094       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8095     } else {
8096       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8097       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8098       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8099       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8100     }
8101
8102     while(--shCount) {
8103       if(sign)
8104                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8105       else
8106                 emitCLRC;
8107       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8108       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8109     }
8110     break;
8111   case 4:
8112   case 5:
8113     if(same) {
8114
8115       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
8116       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
8117       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8118
8119       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8120       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
8121       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8122       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8123     } else {
8124       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8125       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8126       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8127
8128       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8129       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8130       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8131       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
8132       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8133     }
8134
8135     if(shCount >=5) {
8136       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
8137       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8138     }
8139
8140     if(sign) {
8141       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
8142       pic16_emitpcode(POC_BTFSC, 
8143                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
8144       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8145     }
8146
8147     break;
8148
8149   case 6:
8150     if(same) {
8151
8152       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8153       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8154
8155       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8156       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8157       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8158       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8159       if(sign) {
8160         pic16_emitpcode(POC_BTFSC, 
8161                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8162         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8163       }
8164       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8165       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
8166       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
8167       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8168     } else {
8169       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8170       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8171       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8172       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8173       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8174       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8175       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
8176       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
8177       if(sign) {
8178         pic16_emitpcode(POC_BTFSC, 
8179                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8180         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
8181       }
8182       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8183       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8184
8185         
8186     }
8187
8188     break;
8189   case 7:
8190     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8191     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8192     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8193     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8194     if(sign) {
8195       emitSKPNC;
8196       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8197     } else 
8198       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8199   }
8200 }
8201
8202
8203 /*-----------------------------------------------------------------*/
8204 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8205 /*-----------------------------------------------------------------*/
8206 static void shiftLLeftOrResult (operand *left, int offl,
8207                                 operand *result, int offr, int shCount)
8208 {
8209     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8210
8211     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8212     /* shift left accumulator */
8213     AccLsh(shCount);
8214     /* or with result */
8215     /* back to result */
8216     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8217 }
8218
8219 /*-----------------------------------------------------------------*/
8220 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8221 /*-----------------------------------------------------------------*/
8222 static void shiftRLeftOrResult (operand *left, int offl,
8223                                 operand *result, int offr, int shCount)
8224 {
8225     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8226     
8227     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8228     /* shift right accumulator */
8229     AccRsh(shCount, 1);
8230     /* or with result */
8231     /* back to result */
8232     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8233 }
8234
8235 /*-----------------------------------------------------------------*/
8236 /* genlshOne - left shift a one byte quantity by known count       */
8237 /*-----------------------------------------------------------------*/
8238 static void genlshOne (operand *result, operand *left, int shCount)
8239 {       
8240     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8241     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8242 }
8243
8244 /*-----------------------------------------------------------------*/
8245 /* genlshTwo - left shift two bytes by known amount != 0           */
8246 /*-----------------------------------------------------------------*/
8247 static void genlshTwo (operand *result,operand *left, int shCount)
8248 {
8249     int size;
8250     
8251     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8252     size = pic16_getDataSize(result);
8253
8254     /* if shCount >= 8 */
8255     if (shCount >= 8) {
8256         shCount -= 8 ;
8257
8258         if (size > 1){
8259             if (shCount)
8260                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8261             else 
8262                 movLeft2Result(left, LSB, result, MSB16);
8263         }
8264         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8265     }
8266
8267     /*  1 <= shCount <= 7 */
8268     else {  
8269         if(size == 1)
8270             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8271         else 
8272             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8273     }
8274 }
8275
8276 /*-----------------------------------------------------------------*/
8277 /* shiftLLong - shift left one long from left to result            */
8278 /* offr = LSB or MSB16                                             */
8279 /*-----------------------------------------------------------------*/
8280 static void shiftLLong (operand *left, operand *result, int offr )
8281 {
8282     int size = AOP_SIZE(result);
8283     int same = pic16_sameRegs(AOP(left),AOP(result));
8284         int i;
8285
8286     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8287
8288         if (same && (offr == MSB16)) { //shift one byte
8289                 for(i=size-1;i>=MSB16;i--) {
8290                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8291                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8292                 }
8293         } else {
8294                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8295         }
8296         
8297     if (size >= LSB+offr ){
8298                 if (same) {
8299                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8300                 } else {
8301                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8302                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8303                 }
8304          }
8305
8306     if(size >= MSB16+offr){
8307                 if (same) {
8308                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8309                 } else {
8310                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8311                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8312                 }
8313     }
8314
8315     if(size >= MSB24+offr){
8316                 if (same) {
8317                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8318                 } else {
8319                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8320                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8321                 }
8322     }
8323
8324     if(size > MSB32+offr){
8325                 if (same) {
8326                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8327                 } else {
8328                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8329                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8330                 }
8331     }
8332     if(offr != LSB)
8333                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8334
8335 }
8336
8337 /*-----------------------------------------------------------------*/
8338 /* genlshFour - shift four byte by a known amount != 0             */
8339 /*-----------------------------------------------------------------*/
8340 static void genlshFour (operand *result, operand *left, int shCount)
8341 {
8342     int size;
8343
8344     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8345     size = AOP_SIZE(result);
8346
8347     /* if shifting more that 3 bytes */
8348     if (shCount >= 24 ) {
8349         shCount -= 24;
8350         if (shCount)
8351             /* lowest order of left goes to the highest
8352             order of the destination */
8353             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8354         else
8355             movLeft2Result(left, LSB, result, MSB32);
8356
8357                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8358                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8359                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8360
8361         return;
8362     }
8363
8364     /* more than two bytes */
8365     else if ( shCount >= 16 ) {
8366         /* lower order two bytes goes to higher order two bytes */
8367         shCount -= 16;
8368         /* if some more remaining */
8369         if (shCount)
8370             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8371         else {
8372             movLeft2Result(left, MSB16, result, MSB32);
8373             movLeft2Result(left, LSB, result, MSB24);
8374         }
8375                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8376                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8377         return;
8378     }    
8379
8380     /* if more than 1 byte */
8381     else if ( shCount >= 8 ) {
8382         /* lower order three bytes goes to higher order  three bytes */
8383         shCount -= 8;
8384         if(size == 2){
8385             if(shCount)
8386                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8387             else
8388                 movLeft2Result(left, LSB, result, MSB16);
8389         }
8390         else{   /* size = 4 */
8391             if(shCount == 0){
8392                 movLeft2Result(left, MSB24, result, MSB32);
8393                 movLeft2Result(left, MSB16, result, MSB24);
8394                 movLeft2Result(left, LSB, result, MSB16);
8395                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8396             }
8397             else if(shCount == 1)
8398                 shiftLLong(left, result, MSB16);
8399             else{
8400                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8401                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8402                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8403                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8404             }
8405         }
8406     }
8407
8408     /* 1 <= shCount <= 7 */
8409     else if(shCount <= 3)
8410     { 
8411         shiftLLong(left, result, LSB);
8412         while(--shCount >= 1)
8413             shiftLLong(result, result, LSB);
8414     }
8415     /* 3 <= shCount <= 7, optimize */
8416     else{
8417         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8418         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8419         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8420     }
8421 }
8422
8423 /*-----------------------------------------------------------------*/
8424 /* genLeftShiftLiteral - left shifting by known count              */
8425 /*-----------------------------------------------------------------*/
8426 static void genLeftShiftLiteral (operand *left,
8427                                  operand *right,
8428                                  operand *result,
8429                                  iCode *ic)
8430 {    
8431     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8432     int size;
8433
8434     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8435     pic16_freeAsmop(right,NULL,ic,TRUE);
8436
8437     pic16_aopOp(left,ic,FALSE);
8438     pic16_aopOp(result,ic,FALSE);
8439
8440     size = getSize(operandType(result));
8441
8442 #if VIEW_SIZE
8443     pic16_emitcode("; shift left ","result %d, left %d",size,
8444              AOP_SIZE(left));
8445 #endif
8446
8447     /* I suppose that the left size >= result size */
8448     if(shCount == 0){
8449         while(size--){
8450             movLeft2Result(left, size, result, size);
8451         }
8452     }
8453
8454     else if(shCount >= (size * 8))
8455         while(size--)
8456             pic16_aopPut(AOP(result),zero,size);
8457     else{
8458         switch (size) {
8459             case 1:
8460                 genlshOne (result,left,shCount);
8461                 break;
8462
8463             case 2:
8464             case 3:
8465                 genlshTwo (result,left,shCount);
8466                 break;
8467
8468             case 4:
8469                 genlshFour (result,left,shCount);
8470                 break;
8471         }
8472     }
8473     pic16_freeAsmop(left,NULL,ic,TRUE);
8474     pic16_freeAsmop(result,NULL,ic,TRUE);
8475 }
8476
8477 /*-----------------------------------------------------------------*
8478  * genMultiAsm - repeat assembly instruction for size of register.
8479  * if endian == 1, then the high byte (i.e base address + size of 
8480  * register) is used first else the low byte is used first;
8481  *-----------------------------------------------------------------*/
8482 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8483 {
8484
8485   int offset = 0;
8486
8487   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8488
8489   if(!reg)
8490     return;
8491
8492   if(!endian) {
8493     endian = 1;
8494   } else {
8495     endian = -1;
8496     offset = size-1;
8497   }
8498
8499   while(size--) {
8500     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8501     offset += endian;
8502   }
8503
8504 }
8505 /*-----------------------------------------------------------------*/
8506 /* genLeftShift - generates code for left shifting                 */
8507 /*-----------------------------------------------------------------*/
8508 static void genLeftShift (iCode *ic)
8509 {
8510   operand *left,*right, *result;
8511   int size, offset;
8512   char *l;
8513   symbol *tlbl , *tlbl1;
8514   pCodeOp *pctemp;
8515
8516   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8517
8518   right = IC_RIGHT(ic);
8519   left  = IC_LEFT(ic);
8520   result = IC_RESULT(ic);
8521
8522   pic16_aopOp(right,ic,FALSE);
8523
8524   /* if the shift count is known then do it 
8525      as efficiently as possible */
8526   if (AOP_TYPE(right) == AOP_LIT) {
8527     genLeftShiftLiteral (left,right,result,ic);
8528     return ;
8529   }
8530
8531   /* shift count is unknown then we have to form 
8532      a loop get the loop count in B : Note: we take
8533      only the lower order byte since shifting
8534      more that 32 bits make no sense anyway, ( the
8535      largest size of an object can be only 32 bits ) */  
8536
8537     
8538   pic16_aopOp(left,ic,FALSE);
8539   pic16_aopOp(result,ic,FALSE);
8540
8541   /* now move the left to the result if they are not the
8542      same */
8543   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8544       AOP_SIZE(result) > 1) {
8545
8546     size = AOP_SIZE(result);
8547     offset=0;
8548     while (size--) {
8549       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8550       if (*l == '@' && (IS_AOP_PREG(result))) {
8551
8552         pic16_emitcode("mov","a,%s",l);
8553         pic16_aopPut(AOP(result),"a",offset);
8554       } else {
8555         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8556         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8557         //pic16_aopPut(AOP(result),l,offset);
8558       }
8559       offset++;
8560     }
8561   }
8562
8563   size = AOP_SIZE(result);
8564
8565   /* if it is only one byte then */
8566   if (size == 1) {
8567     if(optimized_for_speed) {
8568       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8569       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8570       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
8571       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8572       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8573       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8574       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8575       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8576       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8577       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8578       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
8579       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8580     } else {
8581
8582       tlbl = newiTempLabel(NULL);
8583       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8584                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8585                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8586       }
8587
8588       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8589       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8590       pic16_emitpLabel(tlbl->key);
8591       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8592       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8593       emitSKPC;
8594       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8595     }
8596     goto release ;
8597   }
8598     
8599   if (pic16_sameRegs(AOP(left),AOP(result))) {
8600
8601     tlbl = newiTempLabel(NULL);
8602     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8603     genMultiAsm(POC_RRCF, result, size,1);
8604     pic16_emitpLabel(tlbl->key);
8605     genMultiAsm(POC_RLCF, result, size,0);
8606     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8607     emitSKPC;
8608     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8609     goto release;
8610   }
8611
8612   //tlbl = newiTempLabel(NULL);
8613   //offset = 0 ;   
8614   //tlbl1 = newiTempLabel(NULL);
8615
8616   //reAdjustPreg(AOP(result));    
8617     
8618   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8619   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8620   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8621   //MOVA(l);
8622   //pic16_emitcode("add","a,acc");         
8623   //pic16_aopPut(AOP(result),"a",offset++);
8624   //while (--size) {
8625   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8626   //  MOVA(l);
8627   //  pic16_emitcode("rlc","a");         
8628   //  pic16_aopPut(AOP(result),"a",offset++);
8629   //}
8630   //reAdjustPreg(AOP(result));
8631
8632   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8633   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8634
8635
8636   tlbl = newiTempLabel(NULL);
8637   tlbl1= newiTempLabel(NULL);
8638
8639   size = AOP_SIZE(result);
8640   offset = 1;
8641
8642   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8643
8644   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8645
8646   /* offset should be 0, 1 or 3 */
8647   
8648   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8649   emitSKPNZ;
8650   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8651
8652   pic16_emitpcode(POC_MOVWF, pctemp);
8653
8654
8655   pic16_emitpLabel(tlbl->key);
8656
8657   emitCLRC;
8658   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8659   while(--size)
8660     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8661
8662   pic16_emitpcode(POC_DECFSZ,  pctemp);
8663   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8664   pic16_emitpLabel(tlbl1->key);
8665
8666   pic16_popReleaseTempReg(pctemp);
8667
8668
8669  release:
8670   pic16_freeAsmop (right,NULL,ic,TRUE);
8671   pic16_freeAsmop(left,NULL,ic,TRUE);
8672   pic16_freeAsmop(result,NULL,ic,TRUE);
8673 }
8674
8675 /*-----------------------------------------------------------------*/
8676 /* genrshOne - right shift a one byte quantity by known count      */
8677 /*-----------------------------------------------------------------*/
8678 static void genrshOne (operand *result, operand *left,
8679                        int shCount, int sign)
8680 {
8681     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8682     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8683 }
8684
8685 /*-----------------------------------------------------------------*/
8686 /* genrshTwo - right shift two bytes by known amount != 0          */
8687 /*-----------------------------------------------------------------*/
8688 static void genrshTwo (operand *result,operand *left,
8689                        int shCount, int sign)
8690 {
8691   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8692   /* if shCount >= 8 */
8693   if (shCount >= 8) {
8694     shCount -= 8 ;
8695     if (shCount)
8696       shiftR1Left2Result(left, MSB16, result, LSB,
8697                          shCount, sign);
8698     else
8699       movLeft2Result(left, MSB16, result, LSB);
8700
8701     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8702
8703     if(sign) {
8704       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8705       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8706     }
8707   }
8708
8709   /*  1 <= shCount <= 7 */
8710   else
8711     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8712 }
8713
8714 /*-----------------------------------------------------------------*/
8715 /* shiftRLong - shift right one long from left to result           */
8716 /* offl = LSB or MSB16                                             */
8717 /*-----------------------------------------------------------------*/
8718 static void shiftRLong (operand *left, int offl,
8719                         operand *result, int sign)
8720 {
8721     int size = AOP_SIZE(result);
8722     int same = pic16_sameRegs(AOP(left),AOP(result));
8723     int i;
8724     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8725
8726         if (same && (offl == MSB16)) { //shift one byte right
8727                 for(i=MSB16;i<size;i++) {
8728                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8729                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8730                 }
8731         }
8732
8733     if(sign)
8734                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8735         else
8736                 emitCLRC;
8737
8738         if (same) {
8739                 if (offl == LSB)
8740                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8741         } else {
8742         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8743         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8744         }
8745
8746     if(offl == MSB16) {
8747         /* add sign of "a" */
8748         pic16_addSign(result, MSB32, sign);
8749         }
8750
8751         if (same) {
8752         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8753         } else {
8754         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8755         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8756         }
8757         
8758         if (same) {
8759         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8760         } else {
8761         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8762         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8763         }
8764
8765         if (same) {
8766         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8767         } else {
8768         if(offl == LSB){
8769                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8770                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8771         }
8772         }
8773 }
8774
8775 /*-----------------------------------------------------------------*/
8776 /* genrshFour - shift four byte by a known amount != 0             */
8777 /*-----------------------------------------------------------------*/
8778 static void genrshFour (operand *result, operand *left,
8779                         int shCount, int sign)
8780 {
8781   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8782   /* if shifting more that 3 bytes */
8783   if(shCount >= 24 ) {
8784     shCount -= 24;
8785     if(shCount)
8786       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8787     else
8788       movLeft2Result(left, MSB32, result, LSB);
8789
8790     pic16_addSign(result, MSB16, sign);
8791   }
8792   else if(shCount >= 16){
8793     shCount -= 16;
8794     if(shCount)
8795       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8796     else{
8797       movLeft2Result(left, MSB24, result, LSB);
8798       movLeft2Result(left, MSB32, result, MSB16);
8799     }
8800     pic16_addSign(result, MSB24, sign);
8801   }
8802   else if(shCount >= 8){
8803     shCount -= 8;
8804     if(shCount == 1)
8805       shiftRLong(left, MSB16, result, sign);
8806     else if(shCount == 0){
8807       movLeft2Result(left, MSB16, result, LSB);
8808       movLeft2Result(left, MSB24, result, MSB16);
8809       movLeft2Result(left, MSB32, result, MSB24);
8810       pic16_addSign(result, MSB32, sign);
8811     }
8812     else{ //shcount >= 2
8813       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8814       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8815       /* the last shift is signed */
8816       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8817       pic16_addSign(result, MSB32, sign);
8818     }
8819   }
8820   else{   /* 1 <= shCount <= 7 */
8821     if(shCount <= 2){
8822       shiftRLong(left, LSB, result, sign);
8823       if(shCount == 2)
8824         shiftRLong(result, LSB, result, sign);
8825     }
8826     else{
8827       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8828       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8829       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8830     }
8831   }
8832 }
8833
8834 /*-----------------------------------------------------------------*/
8835 /* genRightShiftLiteral - right shifting by known count            */
8836 /*-----------------------------------------------------------------*/
8837 static void genRightShiftLiteral (operand *left,
8838                                   operand *right,
8839                                   operand *result,
8840                                   iCode *ic,
8841                                   int sign)
8842 {    
8843   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8844   int lsize,res_size;
8845
8846   pic16_freeAsmop(right,NULL,ic,TRUE);
8847
8848   pic16_aopOp(left,ic,FALSE);
8849   pic16_aopOp(result,ic,FALSE);
8850
8851   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8852
8853 #if VIEW_SIZE
8854   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8855                  AOP_SIZE(left));
8856 #endif
8857
8858   lsize = pic16_getDataSize(left);
8859   res_size = pic16_getDataSize(result);
8860   /* test the LEFT size !!! */
8861
8862   /* I suppose that the left size >= result size */
8863   if(shCount == 0){
8864     while(res_size--)
8865       movLeft2Result(left, lsize, result, res_size);
8866   }
8867
8868   else if(shCount >= (lsize * 8)){
8869
8870     if(res_size == 1) {
8871       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8872       if(sign) {
8873         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8874         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8875       }
8876     } else {
8877
8878       if(sign) {
8879         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8880         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8881         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8882         while(res_size--)
8883           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8884
8885       } else {
8886
8887         while(res_size--)
8888           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8889       }
8890     }
8891   } else {
8892
8893     switch (res_size) {
8894     case 1:
8895       genrshOne (result,left,shCount,sign);
8896       break;
8897
8898     case 2:
8899       genrshTwo (result,left,shCount,sign);
8900       break;
8901
8902     case 4:
8903       genrshFour (result,left,shCount,sign);
8904       break;
8905     default :
8906       break;
8907     }
8908
8909   }
8910
8911   pic16_freeAsmop(left,NULL,ic,TRUE);
8912   pic16_freeAsmop(result,NULL,ic,TRUE);
8913 }
8914
8915 /*-----------------------------------------------------------------*/
8916 /* genSignedRightShift - right shift of signed number              */
8917 /*-----------------------------------------------------------------*/
8918 static void genSignedRightShift (iCode *ic)
8919 {
8920   operand *right, *left, *result;
8921   int size, offset;
8922   //  char *l;
8923   symbol *tlbl, *tlbl1 ;
8924   pCodeOp *pctemp;
8925
8926   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8927
8928   /* we do it the hard way put the shift count in b
8929      and loop thru preserving the sign */
8930   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8931
8932   right = IC_RIGHT(ic);
8933   left  = IC_LEFT(ic);
8934   result = IC_RESULT(ic);
8935
8936   pic16_aopOp(right,ic,FALSE);  
8937   pic16_aopOp(left,ic,FALSE);
8938   pic16_aopOp(result,ic,FALSE);
8939
8940
8941   if ( AOP_TYPE(right) == AOP_LIT) {
8942     genRightShiftLiteral (left,right,result,ic,1);
8943     return ;
8944   }
8945   /* shift count is unknown then we have to form 
8946      a loop get the loop count in B : Note: we take
8947      only the lower order byte since shifting
8948      more that 32 bits make no sense anyway, ( the
8949      largest size of an object can be only 32 bits ) */  
8950
8951   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8952   //pic16_emitcode("inc","b");
8953   //pic16_freeAsmop (right,NULL,ic,TRUE);
8954   //pic16_aopOp(left,ic,FALSE);
8955   //pic16_aopOp(result,ic,FALSE);
8956
8957   /* now move the left to the result if they are not the
8958      same */
8959   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8960       AOP_SIZE(result) > 1) {
8961
8962     size = AOP_SIZE(result);
8963     offset=0;
8964     while (size--) { 
8965       /*
8966         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8967         if (*l == '@' && IS_AOP_PREG(result)) {
8968
8969         pic16_emitcode("mov","a,%s",l);
8970         pic16_aopPut(AOP(result),"a",offset);
8971         } else
8972         pic16_aopPut(AOP(result),l,offset);
8973       */
8974       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8975       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8976
8977       offset++;
8978     }
8979   }
8980
8981   /* mov the highest order bit to OVR */    
8982   tlbl = newiTempLabel(NULL);
8983   tlbl1= newiTempLabel(NULL);
8984
8985   size = AOP_SIZE(result);
8986   offset = size - 1;
8987
8988   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8989
8990   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8991
8992   /* offset should be 0, 1 or 3 */
8993   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8994   emitSKPNZ;
8995   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8996
8997   pic16_emitpcode(POC_MOVWF, pctemp);
8998
8999
9000   pic16_emitpLabel(tlbl->key);
9001
9002   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
9003   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
9004
9005   while(--size) {
9006     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
9007   }
9008
9009   pic16_emitpcode(POC_DECFSZ,  pctemp);
9010   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9011   pic16_emitpLabel(tlbl1->key);
9012
9013   pic16_popReleaseTempReg(pctemp);
9014 #if 0
9015   size = AOP_SIZE(result);
9016   offset = size - 1;
9017   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
9018   pic16_emitcode("rlc","a");
9019   pic16_emitcode("mov","ov,c");
9020   /* if it is only one byte then */
9021   if (size == 1) {
9022     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9023     MOVA(l);
9024     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9025     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
9026     pic16_emitcode("mov","c,ov");
9027     pic16_emitcode("rrc","a");
9028     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9029     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9030     pic16_aopPut(AOP(result),"a",0);
9031     goto release ;
9032   }
9033
9034   reAdjustPreg(AOP(result));
9035   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9036   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9037   pic16_emitcode("mov","c,ov");
9038   while (size--) {
9039     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9040     MOVA(l);
9041     pic16_emitcode("rrc","a");         
9042     pic16_aopPut(AOP(result),"a",offset--);
9043   }
9044   reAdjustPreg(AOP(result));
9045   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9046   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9047
9048  release:
9049 #endif
9050
9051   pic16_freeAsmop(left,NULL,ic,TRUE);
9052   pic16_freeAsmop(result,NULL,ic,TRUE);
9053   pic16_freeAsmop(right,NULL,ic,TRUE);
9054 }
9055
9056 /*-----------------------------------------------------------------*/
9057 /* genRightShift - generate code for right shifting                */
9058 /*-----------------------------------------------------------------*/
9059 static void genRightShift (iCode *ic)
9060 {
9061     operand *right, *left, *result;
9062     sym_link *letype ;
9063     int size, offset;
9064     char *l;
9065     symbol *tlbl, *tlbl1 ;
9066
9067     /* if signed then we do it the hard way preserve the
9068     sign bit moving it inwards */
9069     letype = getSpec(operandType(IC_LEFT(ic)));
9070     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9071
9072     if (!SPEC_USIGN(letype)) {
9073         genSignedRightShift (ic);
9074         return ;
9075     }
9076
9077     /* signed & unsigned types are treated the same : i.e. the
9078     signed is NOT propagated inwards : quoting from the
9079     ANSI - standard : "for E1 >> E2, is equivalent to division
9080     by 2**E2 if unsigned or if it has a non-negative value,
9081     otherwise the result is implementation defined ", MY definition
9082     is that the sign does not get propagated */
9083
9084     right = IC_RIGHT(ic);
9085     left  = IC_LEFT(ic);
9086     result = IC_RESULT(ic);
9087
9088     pic16_aopOp(right,ic,FALSE);
9089
9090     /* if the shift count is known then do it 
9091     as efficiently as possible */
9092     if (AOP_TYPE(right) == AOP_LIT) {
9093         genRightShiftLiteral (left,right,result,ic, 0);
9094         return ;
9095     }
9096
9097     /* shift count is unknown then we have to form 
9098     a loop get the loop count in B : Note: we take
9099     only the lower order byte since shifting
9100     more that 32 bits make no sense anyway, ( the
9101     largest size of an object can be only 32 bits ) */  
9102
9103     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
9104     pic16_emitcode("inc","b");
9105     pic16_aopOp(left,ic,FALSE);
9106     pic16_aopOp(result,ic,FALSE);
9107
9108     /* now move the left to the result if they are not the
9109     same */
9110     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9111         AOP_SIZE(result) > 1) {
9112
9113         size = AOP_SIZE(result);
9114         offset=0;
9115         while (size--) {
9116             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9117             if (*l == '@' && IS_AOP_PREG(result)) {
9118
9119                 pic16_emitcode("mov","a,%s",l);
9120                 pic16_aopPut(AOP(result),"a",offset);
9121             } else
9122                 pic16_aopPut(AOP(result),l,offset);
9123             offset++;
9124         }
9125     }
9126
9127     tlbl = newiTempLabel(NULL);
9128     tlbl1= newiTempLabel(NULL);
9129     size = AOP_SIZE(result);
9130     offset = size - 1;
9131
9132     /* if it is only one byte then */
9133     if (size == 1) {
9134
9135       tlbl = newiTempLabel(NULL);
9136       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9137         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9138         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9139       }
9140
9141       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9142       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9143       pic16_emitpLabel(tlbl->key);
9144       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9145       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9146       emitSKPC;
9147       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9148
9149       goto release ;
9150     }
9151
9152     reAdjustPreg(AOP(result));
9153     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
9154     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9155     CLRC;
9156     while (size--) {
9157         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9158         MOVA(l);
9159         pic16_emitcode("rrc","a");         
9160         pic16_aopPut(AOP(result),"a",offset--);
9161     }
9162     reAdjustPreg(AOP(result));
9163
9164     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9165     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9166
9167 release:
9168     pic16_freeAsmop(left,NULL,ic,TRUE);
9169     pic16_freeAsmop (right,NULL,ic,TRUE);
9170     pic16_freeAsmop(result,NULL,ic,TRUE);
9171 }
9172
9173 /*-----------------------------------------------------------------*/
9174 /* genUnpackBits - generates code for unpacking bits               */
9175 /*-----------------------------------------------------------------*/
9176 static void genUnpackBits (operand *result, char *rname, int ptype)
9177 {    
9178     int shCnt ;
9179     int rlen = 0 ;
9180     sym_link *etype;
9181     int offset = 0 ;
9182
9183         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9184         etype = getSpec(operandType(result));
9185
9186         /* read the first byte  */
9187         switch (ptype) {
9188                 case POINTER:
9189                 case IPOINTER:
9190                 case PPOINTER:
9191                 case FPOINTER:
9192                 case GPOINTER:
9193                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9194                         break;
9195                 case CPOINTER:
9196                         pic16_emitcode("clr","a");
9197                         pic16_emitcode("movc","a","@a+dptr");
9198                         break;
9199         }
9200         
9201
9202         /* if we have bitdisplacement then it fits   */
9203         /* into this byte completely or if length is */
9204         /* less than a byte                          */
9205         if ((shCnt = SPEC_BSTR(etype)) || 
9206                 (SPEC_BLEN(etype) <= 8))  {
9207
9208                 /* shift right acc */
9209                 AccRsh(shCnt, 0);
9210
9211                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9212                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9213
9214 /* VR -- normally I would use the following, but since we use the hack,
9215  * to avoid the masking from AccRsh, why not mask it right now? */
9216
9217 /*
9218                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9219 */
9220
9221                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9222           return ;
9223         }
9224
9225
9226
9227         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9228         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9229         exit(-1);
9230
9231     /* bit field did not fit in a byte  */
9232     rlen = SPEC_BLEN(etype) - 8;
9233     pic16_aopPut(AOP(result),"a",offset++);
9234
9235     while (1)  {
9236
9237         switch (ptype) {
9238         case POINTER:
9239         case IPOINTER:
9240             pic16_emitcode("inc","%s",rname);
9241             pic16_emitcode("mov","a,@%s",rname);
9242             break;
9243             
9244         case PPOINTER:
9245             pic16_emitcode("inc","%s",rname);
9246             pic16_emitcode("movx","a,@%s",rname);
9247             break;
9248
9249         case FPOINTER:
9250             pic16_emitcode("inc","dptr");
9251             pic16_emitcode("movx","a,@dptr");
9252             break;
9253             
9254         case CPOINTER:
9255             pic16_emitcode("clr","a");
9256             pic16_emitcode("inc","dptr");
9257             pic16_emitcode("movc","a","@a+dptr");
9258             break;
9259             
9260         case GPOINTER:
9261             pic16_emitcode("inc","dptr");
9262             pic16_emitcode("lcall","__gptrget");
9263             break;
9264         }
9265
9266         rlen -= 8;            
9267         /* if we are done */
9268         if ( rlen <= 0 )
9269             break ;
9270         
9271         pic16_aopPut(AOP(result),"a",offset++);
9272                               
9273     }
9274     
9275     if (rlen) {
9276         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9277         pic16_aopPut(AOP(result),"a",offset);          
9278     }
9279     
9280     return ;
9281 }
9282
9283
9284 static void genDataPointerGet(operand *left,
9285                               operand *result,
9286                               iCode *ic)
9287 {
9288   int size, offset = 0, leoffset=0 ;
9289
9290         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9291         pic16_aopOp(result, ic, FALSE);
9292
9293         size = AOP_SIZE(result);
9294 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9295
9296
9297 #if 0
9298         /* The following tests may save a redudant movff instruction when
9299          * accessing unions */
9300          
9301         /* if they are the same */
9302         if (operandsEqu (left, result)) {
9303                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9304                 goto release;
9305         }
9306 #endif
9307
9308 #if 0
9309         /* if they are the same registers */
9310         if (pic16_sameRegs(AOP(left),AOP(result))) {
9311                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9312                 goto release;
9313         }
9314 #endif
9315
9316 #if 1
9317         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
9318                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
9319                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
9320                 goto release;
9321         }
9322 #endif
9323
9324
9325 #if 0
9326         if ( AOP_TYPE(left) == AOP_PCODE) {
9327                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9328                                 AOP(left)->aopu.pcop->name,
9329                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9330                                 PCOR(AOP(left)->aopu.pcop)->instance:
9331                                 PCOI(AOP(left)->aopu.pcop)->offset);
9332         }
9333 #endif
9334
9335         if(AOP(left)->aopu.pcop->type == PO_DIR)
9336                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9337
9338         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9339
9340         while (size--) {
9341                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9342                 
9343                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9344                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9345                         mov2w(AOP(left), offset); // patch 8
9346                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9347                 } else {
9348                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9349                                 pic16_popGet(AOP(left), offset), //patch 8
9350                                 pic16_popGet(AOP(result), offset)));
9351                 }
9352
9353                 offset++;
9354                 leoffset++;
9355         }
9356
9357 release:
9358     pic16_freeAsmop(result,NULL,ic,TRUE);
9359 }
9360
9361 void pic16_loadFSR0(operand *op)
9362 {
9363         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9364 }
9365
9366
9367 /*-----------------------------------------------------------------*/
9368 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9369 /*-----------------------------------------------------------------*/
9370 static void genNearPointerGet (operand *left, 
9371                                operand *result, 
9372                                iCode *ic)
9373 {
9374     asmop *aop = NULL;
9375     //regs *preg = NULL ;
9376     sym_link *rtype, *retype;
9377     sym_link *ltype = operandType(left);    
9378
9379         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9380         rtype = operandType(result);
9381         retype= getSpec(rtype);
9382     
9383         pic16_aopOp(left,ic,FALSE);
9384
9385 //      pic16_DumpOp("(left)",left);
9386 //      pic16_DumpOp("(result)",result);
9387
9388         /* if left is rematerialisable and
9389          * result is not bit variable type and
9390          * the left is pointer to data space i.e
9391          * lower 128 bytes of space */
9392         if (AOP_TYPE(left) == AOP_PCODE
9393                 && !IS_BITFIELD(retype)
9394                 && DCL_TYPE(ltype) == POINTER) {
9395
9396                 genDataPointerGet (left,result,ic);
9397                 pic16_freeAsmop(left, NULL, ic, TRUE);
9398           return ;
9399         }
9400     
9401         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9402
9403         /* if the value is already in a pointer register
9404          * then don't need anything more */
9405         if (!AOP_INPREG(AOP(left))) {
9406                 /* otherwise get a free pointer register */
9407                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9408                 
9409                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9410                 if( (AOP_TYPE(left) == AOP_PCODE) 
9411                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9412                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9413                 {
9414                         pic16_loadFSR0( left );  // patch 10
9415                 } else {
9416                         // set up FSR0 with address from left
9417                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9418                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9419                 }
9420         }
9421 //       else
9422 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9423     
9424         pic16_aopOp (result,ic,FALSE);
9425     
9426       /* if bitfield then unpack the bits */
9427     if (IS_BITFIELD(retype)) 
9428         genUnpackBits (result, NULL, POINTER);
9429     else {
9430         /* we have can just get the values */
9431       int size = AOP_SIZE(result);
9432       int offset = 0;   
9433         
9434       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9435
9436
9437         /* fsr0 is loaded already -- VR */
9438 //      pic16_loadFSR0( left );
9439
9440 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9441 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9442       while(size--) {
9443
9444         if(size) {
9445                 pic16_emitpcode(POC_MOVFF,
9446                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9447                                 pic16_popGet(AOP(result), offset++)));
9448         } else {
9449                 pic16_emitpcode(POC_MOVFF,
9450                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9451                                 pic16_popGet(AOP(result), offset++)));
9452         }
9453       }
9454 #if 0
9455 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9456 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9457         if(size)
9458           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9459 #endif
9460 /*
9461         while (size--) {
9462             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9463
9464                 pic16_emitcode("mov","a,@%s",rname);
9465                 pic16_aopPut(AOP(result),"a",offset);
9466             } else {
9467                 sprintf(buffer,"@%s",rname);
9468                 pic16_aopPut(AOP(result),buffer,offset);
9469             }
9470             offset++ ;
9471             if (size)
9472                 pic16_emitcode("inc","%s",rname);
9473         }
9474 */
9475     }
9476
9477     /* now some housekeeping stuff */
9478     if (aop) {
9479         /* we had to allocate for this iCode */
9480     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9481         pic16_freeAsmop(NULL,aop,ic,TRUE);
9482     } else { 
9483         /* we did not allocate which means left
9484            already in a pointer register, then
9485            if size > 0 && this could be used again
9486            we have to point it back to where it 
9487            belongs */
9488     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9489         if (AOP_SIZE(result) > 1 &&
9490             !OP_SYMBOL(left)->remat &&
9491             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9492               ic->depth )) {
9493 //          int size = AOP_SIZE(result) - 1;
9494 //          while (size--)
9495 //              pic16_emitcode("dec","%s",rname);
9496         }
9497     }
9498
9499     /* done */
9500     pic16_freeAsmop(left,NULL,ic,TRUE);
9501     pic16_freeAsmop(result,NULL,ic,TRUE);
9502      
9503 }
9504
9505 /*-----------------------------------------------------------------*/
9506 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9507 /*-----------------------------------------------------------------*/
9508 static void genPagedPointerGet (operand *left, 
9509                                operand *result, 
9510                                iCode *ic)
9511 {
9512     asmop *aop = NULL;
9513     regs *preg = NULL ;
9514     char *rname ;
9515     sym_link *rtype, *retype;    
9516
9517     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9518
9519     rtype = operandType(result);
9520     retype= getSpec(rtype);
9521     
9522     pic16_aopOp(left,ic,FALSE);
9523
9524   /* if the value is already in a pointer register
9525        then don't need anything more */
9526     if (!AOP_INPREG(AOP(left))) {
9527         /* otherwise get a free pointer register */
9528         aop = newAsmop(0);
9529         preg = getFreePtr(ic,&aop,FALSE);
9530         pic16_emitcode("mov","%s,%s",
9531                 preg->name,
9532                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9533         rname = preg->name ;
9534     } else
9535         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9536     
9537     pic16_freeAsmop(left,NULL,ic,TRUE);
9538     pic16_aopOp (result,ic,FALSE);
9539
9540     /* if bitfield then unpack the bits */
9541     if (IS_BITFIELD(retype)) 
9542         genUnpackBits (result,rname,PPOINTER);
9543     else {
9544         /* we have can just get the values */
9545         int size = AOP_SIZE(result);
9546         int offset = 0 ;        
9547         
9548         while (size--) {
9549             
9550             pic16_emitcode("movx","a,@%s",rname);
9551             pic16_aopPut(AOP(result),"a",offset);
9552             
9553             offset++ ;
9554             
9555             if (size)
9556                 pic16_emitcode("inc","%s",rname);
9557         }
9558     }
9559
9560     /* now some housekeeping stuff */
9561     if (aop) {
9562         /* we had to allocate for this iCode */
9563         pic16_freeAsmop(NULL,aop,ic,TRUE);
9564     } else { 
9565         /* we did not allocate which means left
9566            already in a pointer register, then
9567            if size > 0 && this could be used again
9568            we have to point it back to where it 
9569            belongs */
9570         if (AOP_SIZE(result) > 1 &&
9571             !OP_SYMBOL(left)->remat &&
9572             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9573               ic->depth )) {
9574             int size = AOP_SIZE(result) - 1;
9575             while (size--)
9576                 pic16_emitcode("dec","%s",rname);
9577         }
9578     }
9579
9580     /* done */
9581     pic16_freeAsmop(result,NULL,ic,TRUE);
9582     
9583         
9584 }
9585
9586 /*-----------------------------------------------------------------*/
9587 /* genFarPointerGet - gget value from far space                    */
9588 /*-----------------------------------------------------------------*/
9589 static void genFarPointerGet (operand *left,
9590                               operand *result, iCode *ic)
9591 {
9592     int size, offset ;
9593     sym_link *retype = getSpec(operandType(result));
9594
9595     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9596
9597     pic16_aopOp(left,ic,FALSE);
9598
9599     /* if the operand is already in dptr 
9600     then we do nothing else we move the value to dptr */
9601     if (AOP_TYPE(left) != AOP_STR) {
9602         /* if this is remateriazable */
9603         if (AOP_TYPE(left) == AOP_IMMD)
9604             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9605         else { /* we need to get it byte by byte */
9606             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9607             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9608             if (options.model == MODEL_FLAT24)
9609             {
9610                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9611             }
9612         }
9613     }
9614     /* so dptr know contains the address */
9615     pic16_freeAsmop(left,NULL,ic,TRUE);
9616     pic16_aopOp(result,ic,FALSE);
9617
9618     /* if bit then unpack */
9619     if (IS_BITFIELD(retype)) 
9620         genUnpackBits(result,"dptr",FPOINTER);
9621     else {
9622         size = AOP_SIZE(result);
9623         offset = 0 ;
9624
9625         while (size--) {
9626             pic16_emitcode("movx","a,@dptr");
9627             pic16_aopPut(AOP(result),"a",offset++);
9628             if (size)
9629                 pic16_emitcode("inc","dptr");
9630         }
9631     }
9632
9633     pic16_freeAsmop(result,NULL,ic,TRUE);
9634 }
9635 #if 0
9636 /*-----------------------------------------------------------------*/
9637 /* genCodePointerGet - get value from code space                  */
9638 /*-----------------------------------------------------------------*/
9639 static void genCodePointerGet (operand *left,
9640                                 operand *result, iCode *ic)
9641 {
9642     int size, offset ;
9643     sym_link *retype = getSpec(operandType(result));
9644
9645     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9646
9647     pic16_aopOp(left,ic,FALSE);
9648
9649     /* if the operand is already in dptr 
9650     then we do nothing else we move the value to dptr */
9651     if (AOP_TYPE(left) != AOP_STR) {
9652         /* if this is remateriazable */
9653         if (AOP_TYPE(left) == AOP_IMMD)
9654             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9655         else { /* we need to get it byte by byte */
9656             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9657             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9658             if (options.model == MODEL_FLAT24)
9659             {
9660                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9661             }
9662         }
9663     }
9664     /* so dptr know contains the address */
9665     pic16_freeAsmop(left,NULL,ic,TRUE);
9666     pic16_aopOp(result,ic,FALSE);
9667
9668     /* if bit then unpack */
9669     if (IS_BITFIELD(retype)) 
9670         genUnpackBits(result,"dptr",CPOINTER);
9671     else {
9672         size = AOP_SIZE(result);
9673         offset = 0 ;
9674
9675         while (size--) {
9676             pic16_emitcode("clr","a");
9677             pic16_emitcode("movc","a,@a+dptr");
9678             pic16_aopPut(AOP(result),"a",offset++);
9679             if (size)
9680                 pic16_emitcode("inc","dptr");
9681         }
9682     }
9683
9684     pic16_freeAsmop(result,NULL,ic,TRUE);
9685 }
9686 #endif
9687 /*-----------------------------------------------------------------*/
9688 /* genGenPointerGet - gget value from generic pointer space        */
9689 /*-----------------------------------------------------------------*/
9690 static void genGenPointerGet (operand *left,
9691                               operand *result, iCode *ic)
9692 {
9693   int size, offset, lit;
9694   sym_link *retype = getSpec(operandType(result));
9695
9696         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9697         pic16_aopOp(left,ic,FALSE);
9698         pic16_aopOp(result,ic,FALSE);
9699         size = AOP_SIZE(result);
9700
9701         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9702
9703         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9704
9705                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9706                 // load FSR0 from immediate
9707                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9708
9709 //              pic16_loadFSR0( left );
9710
9711                 offset = 0;
9712                 while(size--) {
9713                         if(size) {
9714                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9715                         } else {
9716                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9717                         }
9718                         offset++;
9719                 }
9720                 goto release;
9721
9722         }
9723         else { /* we need to get it byte by byte */
9724                 // set up FSR0 with address from left
9725                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9726                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9727
9728                 offset = 0 ;
9729
9730                 while(size--) {
9731                         if(size) {
9732                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9733                         } else {
9734                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9735                         }
9736                         offset++;
9737                 }
9738                 goto release;
9739         }
9740
9741   /* if bit then unpack */
9742         if (IS_BITFIELD(retype)) 
9743                 genUnpackBits(result,"BAD",GPOINTER);
9744
9745         release:
9746         pic16_freeAsmop(left,NULL,ic,TRUE);
9747         pic16_freeAsmop(result,NULL,ic,TRUE);
9748
9749 }
9750
9751 /*-----------------------------------------------------------------*/
9752 /* genConstPointerGet - get value from const generic pointer space */
9753 /*-----------------------------------------------------------------*/
9754 static void genConstPointerGet (operand *left,
9755                                 operand *result, iCode *ic)
9756 {
9757   //sym_link *retype = getSpec(operandType(result));
9758   // symbol *albl = newiTempLabel(NULL);        // patch 15
9759   // symbol *blbl = newiTempLabel(NULL);        //
9760   // PIC_OPCODE poc;                            // patch 15
9761   int size;
9762   int offset = 0;
9763
9764   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9765   pic16_aopOp(left,ic,FALSE);
9766   pic16_aopOp(result,ic,TRUE);
9767   size = AOP_SIZE(result);
9768
9769   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9770
9771   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9772 #if 0                                                                   // patch 15
9773   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9774   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9775   pic16_emitpLabel(albl->key);
9776
9777   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9778     
9779   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9780   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9781   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9782   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9783   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9784
9785   pic16_emitpLabel(blbl->key);
9786
9787   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9788 #endif                                                                  // patch 15
9789
9790
9791   // set up table pointer
9792   if( (AOP_TYPE(left) == AOP_PCODE) 
9793       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9794           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9795     {
9796       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9797       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9798       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9799       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9800       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9801       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9802     }
9803   else
9804     {
9805       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9806       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9807       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9808     }
9809
9810
9811   while(size--)
9812     {
9813       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9814       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9815       offset++;
9816     }
9817     
9818   pic16_freeAsmop(left,NULL,ic,TRUE);
9819   pic16_freeAsmop(result,NULL,ic,TRUE);
9820
9821 }
9822
9823
9824 /*-----------------------------------------------------------------*/
9825 /* genPointerGet - generate code for pointer get                   */
9826 /*-----------------------------------------------------------------*/
9827 static void genPointerGet (iCode *ic)
9828 {
9829     operand *left, *result ;
9830     sym_link *type, *etype;
9831     int p_type;
9832
9833     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9834
9835     left = IC_LEFT(ic);
9836     result = IC_RESULT(ic) ;
9837
9838     /* depending on the type of pointer we need to
9839     move it to the correct pointer register */
9840     type = operandType(left);
9841     etype = getSpec(type);
9842
9843 #if 0
9844     if (IS_PTR_CONST(type))
9845 #else
9846     if (IS_CODEPTR(type))
9847 #endif
9848       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9849
9850     /* if left is of type of pointer then it is simple */
9851     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9852         p_type = DCL_TYPE(type);
9853     else {
9854         /* we have to go by the storage class */
9855         p_type = PTR_TYPE(SPEC_OCLS(etype));
9856
9857         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9858
9859         if (SPEC_OCLS(etype)->codesp ) {
9860           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9861           //p_type = CPOINTER ; 
9862         }
9863         else
9864             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9865               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9866                /*p_type = FPOINTER ;*/ 
9867             else
9868                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9869                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9870 /*                  p_type = PPOINTER; */
9871                 else
9872                     if (SPEC_OCLS(etype) == idata )
9873                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9874 /*                      p_type = IPOINTER; */
9875                     else
9876                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9877 /*                      p_type = POINTER ; */
9878     }
9879
9880     /* now that we have the pointer type we assign
9881     the pointer values */
9882     switch (p_type) {
9883
9884     case POINTER:       
9885     case IPOINTER:
9886         genNearPointerGet (left,result,ic);
9887         break;
9888
9889     case PPOINTER:
9890         genPagedPointerGet(left,result,ic);
9891         break;
9892
9893     case FPOINTER:
9894         genFarPointerGet (left,result,ic);
9895         break;
9896
9897     case CPOINTER:
9898         genConstPointerGet (left,result,ic);
9899         //pic16_emitcodePointerGet (left,result,ic);
9900         break;
9901
9902     case GPOINTER:
9903 #if 0
9904       if (IS_PTR_CONST(type))
9905         genConstPointerGet (left,result,ic);
9906       else
9907 #endif
9908         genGenPointerGet (left,result,ic);
9909       break;
9910
9911     default:
9912       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9913               "genPointerGet: illegal pointer type");
9914     
9915     }
9916
9917 }
9918
9919 /*-----------------------------------------------------------------*/
9920 /* genPackBits - generates code for packed bit storage             */
9921 /*-----------------------------------------------------------------*/
9922 static void genPackBits (sym_link    *etype ,
9923                          operand *right ,
9924                          char *rname, int p_type)
9925 {
9926   int shCnt = 0 ;
9927   int offset = 0  ;
9928   int rLen = 0 ;
9929   int blen, bstr ;   
9930   char *l ;
9931
9932         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9933         blen = SPEC_BLEN(etype);
9934         bstr = SPEC_BSTR(etype);
9935
9936         if(AOP_TYPE(right) == AOP_LIT) {
9937                 if((blen == 1) && (bstr < 8)) {
9938                   unsigned long lit;
9939                         /* it is a single bit, so use the appropriate bit instructions */
9940
9941                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9942
9943                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9944 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9945                         if(lit) {
9946                                 pic16_emitpcode(POC_BSF,
9947                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9948                         } else {
9949                                 pic16_emitpcode(POC_BCF,
9950                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9951                         }
9952         
9953                   return;
9954                 }
9955
9956                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9957                 offset++;
9958         } else
9959                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9960
9961         /* if the bit lenth is less than or    */
9962         /* it exactly fits a byte then         */
9963         if((shCnt=SPEC_BSTR(etype))
9964                 || SPEC_BLEN(etype) <= 8 )  {
9965
9966                 /* shift left acc */
9967                 AccLsh(shCnt);
9968
9969                 /* using PRODL as a temporary register here */
9970                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9971
9972                 switch (p_type) {
9973                         case FPOINTER:
9974                         case POINTER:
9975                         case GPOINTER:
9976                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9977 //                              pic16_emitcode ("mov","b,a");
9978 //                              pic16_emitcode("mov","a,@%s",rname);
9979                                 break;
9980                 }
9981 #if 1
9982                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9983                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9984                                         (unsigned char)(0xff >> (8-bstr))) ));
9985                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9986                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9987 #endif
9988
9989           return;
9990         }
9991
9992
9993         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9994         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9995         exit(-1);
9996
9997
9998     /* if we r done */
9999     if ( SPEC_BLEN(etype) <= 8 )
10000         return ;
10001
10002     pic16_emitcode("inc","%s",rname);
10003     rLen = SPEC_BLEN(etype) ;     
10004
10005
10006
10007     /* now generate for lengths greater than one byte */
10008     while (1) {
10009
10010         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
10011
10012         rLen -= 8 ;
10013         if (rLen <= 0 )
10014             break ;
10015
10016         switch (p_type) {
10017             case POINTER:
10018                 if (*l == '@') {
10019                     MOVA(l);
10020                     pic16_emitcode("mov","@%s,a",rname);
10021                 } else
10022                     pic16_emitcode("mov","@%s,%s",rname,l);
10023                 break;
10024
10025             case FPOINTER:
10026                 MOVA(l);
10027                 pic16_emitcode("movx","@dptr,a");
10028                 break;
10029
10030             case GPOINTER:
10031                 MOVA(l);
10032                 DEBUGpic16_emitcode(";lcall","__gptrput");
10033                 break;  
10034         }   
10035         pic16_emitcode ("inc","%s",rname);
10036     }
10037
10038     MOVA(l);
10039
10040     /* last last was not complete */
10041     if (rLen)   {
10042         /* save the byte & read byte */
10043         switch (p_type) {
10044             case POINTER:
10045                 pic16_emitcode ("mov","b,a");
10046                 pic16_emitcode("mov","a,@%s",rname);
10047                 break;
10048
10049             case FPOINTER:
10050                 pic16_emitcode ("mov","b,a");
10051                 pic16_emitcode("movx","a,@dptr");
10052                 break;
10053
10054             case GPOINTER:
10055                 pic16_emitcode ("push","b");
10056                 pic16_emitcode ("push","acc");
10057                 pic16_emitcode ("lcall","__gptrget");
10058                 pic16_emitcode ("pop","b");
10059                 break;
10060         }
10061
10062         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
10063         pic16_emitcode ("orl","a,b");
10064     }
10065
10066     if (p_type == GPOINTER)
10067         pic16_emitcode("pop","b");
10068
10069     switch (p_type) {
10070
10071     case POINTER:
10072         pic16_emitcode("mov","@%s,a",rname);
10073         break;
10074         
10075     case FPOINTER:
10076         pic16_emitcode("movx","@dptr,a");
10077         break;
10078         
10079     case GPOINTER:
10080         DEBUGpic16_emitcode(";lcall","__gptrput");
10081         break;                  
10082     }
10083 }
10084 /*-----------------------------------------------------------------*/
10085 /* genDataPointerSet - remat pointer to data space                 */
10086 /*-----------------------------------------------------------------*/
10087 static void genDataPointerSet(operand *right,
10088                               operand *result,
10089                               iCode *ic)
10090 {
10091     int size, offset = 0, resoffset=0 ;
10092
10093     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10094     pic16_aopOp(right,ic,FALSE);
10095
10096     size = AOP_SIZE(right);
10097
10098 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10099
10100 #if 0
10101     if ( AOP_TYPE(result) == AOP_PCODE) {
10102       fprintf(stderr,"genDataPointerSet   %s, %d\n",
10103               AOP(result)->aopu.pcop->name,
10104                 (AOP(result)->aopu.pcop->type == PO_DIR)?
10105               PCOR(AOP(result)->aopu.pcop)->instance:
10106               PCOI(AOP(result)->aopu.pcop)->offset);
10107     }
10108 #endif
10109
10110         if(AOP(result)->aopu.pcop->type == PO_DIR)
10111                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
10112
10113         while (size--) {
10114                 if (AOP_TYPE(right) == AOP_LIT) {
10115                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
10116
10117                         lit = lit >> (8*offset);
10118                         if(lit&0xff) {
10119                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
10120                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
10121                         } else {
10122                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
10123                         }
10124                 } else {
10125                         mov2w(AOP(right), offset);
10126                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
10127                 }
10128                 offset++;
10129                 resoffset++;
10130         }
10131
10132     pic16_freeAsmop(right,NULL,ic,TRUE);
10133 }
10134
10135
10136
10137 /*-----------------------------------------------------------------*/
10138 /* genNearPointerSet - pic16_emitcode for near pointer put         */
10139 /*-----------------------------------------------------------------*/
10140 static void genNearPointerSet (operand *right,
10141                                operand *result, 
10142                                iCode *ic)
10143 {
10144   asmop *aop = NULL;
10145   char *l;
10146   sym_link *retype;
10147   sym_link *ptype = operandType(result);
10148   sym_link *resetype;
10149     
10150         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10151         retype= getSpec(operandType(right));
10152         resetype = getSpec(operandType(result));
10153   
10154         pic16_aopOp(result,ic,FALSE);
10155     
10156         /* if the result is rematerializable &
10157          * in data space & not a bit variable */
10158         
10159         /* and result is not a bit variable */
10160         if (AOP_TYPE(result) == AOP_PCODE
10161 //              && AOP_TYPE(result) == AOP_IMMD
10162                 && DCL_TYPE(ptype) == POINTER
10163                 && !IS_BITFIELD(retype)
10164                 && !IS_BITFIELD(resetype)) {
10165
10166                 genDataPointerSet (right,result,ic);
10167                 pic16_freeAsmop(result,NULL,ic,TRUE);
10168           return;
10169         }
10170
10171         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10172         pic16_aopOp(right,ic,FALSE);
10173         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10174
10175         /* if the value is already in a pointer register
10176          * then don't need anything more */
10177         if (!AOP_INPREG(AOP(result))) {
10178                 /* otherwise get a free pointer register */
10179                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10180
10181                 if( (AOP_TYPE(result) == AOP_PCODE) 
10182                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
10183                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
10184                 {
10185                         pic16_loadFSR0( result );  // patch 10
10186                 } else {
10187                         // set up FSR0 with address of result
10188                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
10189                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
10190                 }
10191
10192         }
10193 //      else
10194 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10195
10196         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10197
10198         /* if bitfield then unpack the bits */
10199         if (IS_BITFIELD(resetype)) {
10200                 genPackBits (resetype, right, NULL, POINTER);
10201         } else {
10202                 /* we have can just get the values */
10203           int size = AOP_SIZE(right);
10204           int offset = 0 ;    
10205
10206                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10207                 while (size--) {
10208                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10209                         if (*l == '@' ) {
10210                                 //MOVA(l);
10211                                 //pic16_emitcode("mov","@%s,a",rname);
10212                                 pic16_emitcode("movf","indf0,w ;1");
10213                         } else {
10214
10215                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10216                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10217                                         if (size) {                                                                     // 
10218                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10219                                         } else {                                                                        // 
10220                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10221                                         }                                                                               // 
10222                                 } else { // no literal                                                                  // 
10223                                         if(size) {                                                                      // 
10224                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10225                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10226                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10227                                         } else {                                                                        // 
10228                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10229                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10230                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10231                                         }                                                                               //
10232                                 }                                                                                       // patch 10
10233                         }
10234                         offset++;
10235                 }
10236         }
10237
10238         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10239         /* now some housekeeping stuff */
10240         if (aop) {
10241                 /* we had to allocate for this iCode */
10242                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10243         } else { 
10244                 /* we did not allocate which means left
10245                  * already in a pointer register, then
10246                  * if size > 0 && this could be used again
10247                  * we have to point it back to where it 
10248                  * belongs */
10249                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10250                 if (AOP_SIZE(right) > 1
10251                         && !OP_SYMBOL(result)->remat
10252                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10253                                 || ic->depth )) {
10254
10255                   int size = AOP_SIZE(right) - 1;
10256
10257                         while (size--)
10258                                 pic16_emitcode("decf","fsr0,f");
10259                         //pic16_emitcode("dec","%s",rname);
10260                 }
10261         }
10262
10263         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10264         /* done */
10265 //release:
10266         pic16_freeAsmop(right,NULL,ic,TRUE);
10267         pic16_freeAsmop(result,NULL,ic,TRUE);
10268 }
10269
10270 /*-----------------------------------------------------------------*/
10271 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10272 /*-----------------------------------------------------------------*/
10273 static void genPagedPointerSet (operand *right,
10274                                operand *result, 
10275                                iCode *ic)
10276 {
10277     asmop *aop = NULL;
10278     regs *preg = NULL ;
10279     char *rname , *l;
10280     sym_link *retype;
10281        
10282     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10283
10284     retype= getSpec(operandType(right));
10285     
10286     pic16_aopOp(result,ic,FALSE);
10287     
10288     /* if the value is already in a pointer register
10289        then don't need anything more */
10290     if (!AOP_INPREG(AOP(result))) {
10291         /* otherwise get a free pointer register */
10292         aop = newAsmop(0);
10293         preg = getFreePtr(ic,&aop,FALSE);
10294         pic16_emitcode("mov","%s,%s",
10295                 preg->name,
10296                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10297         rname = preg->name ;
10298     } else
10299         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10300     
10301     pic16_freeAsmop(result,NULL,ic,TRUE);
10302     pic16_aopOp (right,ic,FALSE);
10303
10304     /* if bitfield then unpack the bits */
10305     if (IS_BITFIELD(retype)) 
10306         genPackBits (retype,right,rname,PPOINTER);
10307     else {
10308         /* we have can just get the values */
10309         int size = AOP_SIZE(right);
10310         int offset = 0 ;        
10311         
10312         while (size--) {
10313             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10314             
10315             MOVA(l);
10316             pic16_emitcode("movx","@%s,a",rname);
10317
10318             if (size)
10319                 pic16_emitcode("inc","%s",rname);
10320
10321             offset++;
10322         }
10323     }
10324     
10325     /* now some housekeeping stuff */
10326     if (aop) {
10327         /* we had to allocate for this iCode */
10328         pic16_freeAsmop(NULL,aop,ic,TRUE);
10329     } else { 
10330         /* we did not allocate which means left
10331            already in a pointer register, then
10332            if size > 0 && this could be used again
10333            we have to point it back to where it 
10334            belongs */
10335         if (AOP_SIZE(right) > 1 &&
10336             !OP_SYMBOL(result)->remat &&
10337             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10338               ic->depth )) {
10339             int size = AOP_SIZE(right) - 1;
10340             while (size--)
10341                 pic16_emitcode("dec","%s",rname);
10342         }
10343     }
10344
10345     /* done */
10346     pic16_freeAsmop(right,NULL,ic,TRUE);
10347     
10348         
10349 }
10350
10351 /*-----------------------------------------------------------------*/
10352 /* genFarPointerSet - set value from far space                     */
10353 /*-----------------------------------------------------------------*/
10354 static void genFarPointerSet (operand *right,
10355                               operand *result, iCode *ic)
10356 {
10357     int size, offset ;
10358     sym_link *retype = getSpec(operandType(right));
10359
10360     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10361     pic16_aopOp(result,ic,FALSE);
10362
10363     /* if the operand is already in dptr 
10364     then we do nothing else we move the value to dptr */
10365     if (AOP_TYPE(result) != AOP_STR) {
10366         /* if this is remateriazable */
10367         if (AOP_TYPE(result) == AOP_IMMD)
10368             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10369         else { /* we need to get it byte by byte */
10370             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10371             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10372             if (options.model == MODEL_FLAT24)
10373             {
10374                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10375             }
10376         }
10377     }
10378     /* so dptr know contains the address */
10379     pic16_freeAsmop(result,NULL,ic,TRUE);
10380     pic16_aopOp(right,ic,FALSE);
10381
10382     /* if bit then unpack */
10383     if (IS_BITFIELD(retype)) 
10384         genPackBits(retype,right,"dptr",FPOINTER);
10385     else {
10386         size = AOP_SIZE(right);
10387         offset = 0 ;
10388
10389         while (size--) {
10390             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10391             MOVA(l);
10392             pic16_emitcode("movx","@dptr,a");
10393             if (size)
10394                 pic16_emitcode("inc","dptr");
10395         }
10396     }
10397
10398     pic16_freeAsmop(right,NULL,ic,TRUE);
10399 }
10400
10401 /*-----------------------------------------------------------------*/
10402 /* genGenPointerSet - set value from generic pointer space         */
10403 /*-----------------------------------------------------------------*/
10404 static void genGenPointerSet (operand *right,
10405                               operand *result, iCode *ic)
10406 {
10407         int i, size, offset, lit;
10408         sym_link *retype = getSpec(operandType(right));
10409
10410         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10411
10412         pic16_aopOp(result,ic,FALSE);
10413         pic16_aopOp(right,ic,FALSE);
10414         size = AOP_SIZE(right);
10415         offset = 0;
10416
10417         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10418
10419         /* if the operand is already in dptr 
10420                 then we do nothing else we move the value to dptr */
10421         if (AOP_TYPE(result) != AOP_STR) {
10422                 /* if this is remateriazable */
10423                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10424                 // WARNING: anythig until "else" is untested!
10425                 if (AOP_TYPE(result) == AOP_IMMD) {
10426                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10427                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10428                         // load FSR0 from immediate
10429                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10430                         offset = 0;
10431                         while(size--) {
10432                                 if(size) {
10433                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10434                                 } else {
10435                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10436                                 }
10437                                 offset++;
10438                         }
10439                         goto release;
10440                 }
10441                 else { /* we need to get it byte by byte */
10442                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10443                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10444
10445                         // set up FSR0 with address of result
10446                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10447                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10448
10449                         /* hack hack! see if this the FSR. If so don't load W */
10450                         if(AOP_TYPE(right) != AOP_ACC) {
10451
10452                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10453
10454                                 if(AOP_TYPE(right) == AOP_LIT)
10455                                 {
10456                                         // copy literal
10457                                         // note: pic16_popGet handles sign extension
10458                                         for(i=0;i<size;i++) {
10459                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10460                                                 if(i < size-1)
10461                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10462                                                 else
10463                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10464                                         }
10465                                 } else {
10466                                         // copy regs
10467
10468                                         for(i=0;i<size;i++) {
10469                                                 if(i < size-1)
10470                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10471                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10472                                                 else
10473                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10474                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10475                                         }
10476                                 }
10477                                 goto release;
10478                         } 
10479                         // right = ACC
10480                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10481                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10482                         goto release;
10483         } // if (AOP_TYPE(result) != AOP_IMMD)
10484
10485         } // if (AOP_TYPE(result) != AOP_STR)
10486         /* so dptr know contains the address */
10487
10488
10489         /* if bit then unpack */
10490         if (IS_BITFIELD(retype)) 
10491                 genPackBits(retype,right,"dptr",GPOINTER);
10492         else {
10493                 size = AOP_SIZE(right);
10494                 offset = 0 ;
10495
10496                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10497
10498                 // set up FSR0 with address of result
10499                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10500                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10501         
10502                 while (size--) {
10503                         if (AOP_TYPE(right) == AOP_LIT) {
10504                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10505                                 if (size) {
10506                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10507                                 } else {
10508                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10509                                 }
10510                         } else { // no literal
10511                                 if(size) {
10512                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10513                                 } else {
10514                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10515                                 }
10516                         }
10517                         offset++;
10518                 }
10519         }
10520
10521         release:
10522         pic16_freeAsmop(right,NULL,ic,TRUE);
10523         pic16_freeAsmop(result,NULL,ic,TRUE);
10524 }
10525
10526 /*-----------------------------------------------------------------*/
10527 /* genPointerSet - stores the value into a pointer location        */
10528 /*-----------------------------------------------------------------*/
10529 static void genPointerSet (iCode *ic)
10530 {    
10531     operand *right, *result ;
10532     sym_link *type, *etype;
10533     int p_type;
10534
10535     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10536
10537     right = IC_RIGHT(ic);
10538     result = IC_RESULT(ic) ;
10539
10540     /* depending on the type of pointer we need to
10541     move it to the correct pointer register */
10542     type = operandType(result);
10543     etype = getSpec(type);
10544     /* if left is of type of pointer then it is simple */
10545     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10546         p_type = DCL_TYPE(type);
10547     }
10548     else {
10549         /* we have to go by the storage class */
10550         p_type = PTR_TYPE(SPEC_OCLS(etype));
10551
10552 /*      if (SPEC_OCLS(etype)->codesp ) { */
10553 /*          p_type = CPOINTER ;  */
10554 /*      } */
10555 /*      else */
10556 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10557 /*              p_type = FPOINTER ; */
10558 /*          else */
10559 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10560 /*                  p_type = PPOINTER ; */
10561 /*              else */
10562 /*                  if (SPEC_OCLS(etype) == idata ) */
10563 /*                      p_type = IPOINTER ; */
10564 /*                  else */
10565 /*                      p_type = POINTER ; */
10566     }
10567
10568     /* now that we have the pointer type we assign
10569     the pointer values */
10570     switch (p_type) {
10571
10572     case POINTER:
10573     case IPOINTER:
10574         genNearPointerSet (right,result,ic);
10575         break;
10576
10577     case PPOINTER:
10578         genPagedPointerSet (right,result,ic);
10579         break;
10580
10581     case FPOINTER:
10582         genFarPointerSet (right,result,ic);
10583         break;
10584
10585     case GPOINTER:
10586         genGenPointerSet (right,result,ic);
10587         break;
10588
10589     default:
10590       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10591               "genPointerSet: illegal pointer type");
10592     }
10593 }
10594
10595 /*-----------------------------------------------------------------*/
10596 /* genIfx - generate code for Ifx statement                        */
10597 /*-----------------------------------------------------------------*/
10598 static void genIfx (iCode *ic, iCode *popIc)
10599 {
10600   operand *cond = IC_COND(ic);
10601   int isbit =0;
10602
10603   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10604
10605   pic16_aopOp(cond,ic,FALSE);
10606
10607   /* get the value into acc */
10608   if (AOP_TYPE(cond) != AOP_CRY)
10609     pic16_toBoolean(cond);
10610   else
10611     isbit = 1;
10612   /* the result is now in the accumulator */
10613   pic16_freeAsmop(cond,NULL,ic,TRUE);
10614
10615   /* if there was something to be popped then do it */
10616   if (popIc)
10617     genIpop(popIc);
10618
10619   /* if the condition is  a bit variable */
10620   if (isbit && IS_ITEMP(cond) && 
10621       SPIL_LOC(cond)) {
10622     genIfxJump(ic,SPIL_LOC(cond)->rname);
10623     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10624   }
10625   else {
10626     if (isbit && !IS_ITEMP(cond))
10627       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10628     else
10629       genIfxJump(ic,"a");
10630   }
10631   ic->generated = 1;
10632
10633 }
10634
10635 /*-----------------------------------------------------------------*/
10636 /* genAddrOf - generates code for address of                       */
10637 /*-----------------------------------------------------------------*/
10638 static void genAddrOf (iCode *ic)
10639 {
10640   operand *result, *left;
10641   int size;
10642   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10643   pCodeOp *pcop0, *pcop1, *pcop2;
10644
10645         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10646
10647         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10648         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10649
10650         sym = OP_SYMBOL( left );
10651
10652         size = AOP_SIZE(IC_RESULT(ic));
10653
10654
10655         if(sym->onStack) {
10656                 DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
10657         
10658                 return;
10659         }
10660         
10661 //      if(pic16_debug_verbose) {
10662 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10663 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10664 //      }
10665         
10666         /* Assume that what we want the address of is in data space
10667          * since there is no stack on the PIC, yet! -- VR */
10668         /* low */
10669         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10670
10671         /* high */
10672         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10673         
10674         /* upper */
10675         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10676         
10677
10678         if (size == 3) {
10679                 pic16_emitpcode(POC_MOVLW, pcop0);
10680                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10681                 pic16_emitpcode(POC_MOVLW, pcop1);
10682                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10683                 pic16_emitpcode(POC_MOVLW, pcop2);
10684                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10685         } else
10686         if (size == 2) {
10687                 pic16_emitpcode(POC_MOVLW, pcop0);
10688                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10689                 pic16_emitpcode(POC_MOVLW, pcop1);
10690                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10691         } else {
10692                 pic16_emitpcode(POC_MOVLW, pcop0);
10693                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10694         }
10695
10696         pic16_freeAsmop(result,NULL,ic,TRUE);
10697         pic16_freeAsmop(left, NULL, ic, FALSE);
10698 }
10699
10700
10701 #if 0
10702 /*-----------------------------------------------------------------*/
10703 /* genFarFarAssign - assignment when both are in far space         */
10704 /*-----------------------------------------------------------------*/
10705 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10706 {
10707     int size = AOP_SIZE(right);
10708     int offset = 0;
10709     char *l ;
10710     /* first push the right side on to the stack */
10711     while (size--) {
10712         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10713         MOVA(l);
10714         pic16_emitcode ("push","acc");
10715     }
10716     
10717     pic16_freeAsmop(right,NULL,ic,FALSE);
10718     /* now assign DPTR to result */
10719     pic16_aopOp(result,ic,FALSE);
10720     size = AOP_SIZE(result);
10721     while (size--) {
10722         pic16_emitcode ("pop","acc");
10723         pic16_aopPut(AOP(result),"a",--offset);
10724     }
10725     pic16_freeAsmop(result,NULL,ic,FALSE);
10726         
10727 }
10728 #endif
10729
10730 /*-----------------------------------------------------------------*/
10731 /* genAssign - generate code for assignment                        */
10732 /*-----------------------------------------------------------------*/
10733 static void genAssign (iCode *ic)
10734 {
10735   operand *result, *right;
10736   int size, offset,know_W;
10737   unsigned long lit = 0L;
10738
10739   result = IC_RESULT(ic);
10740   right  = IC_RIGHT(ic) ;
10741
10742   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10743   
10744   /* if they are the same */
10745   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10746     return ;
10747
10748   pic16_aopOp(right,ic,FALSE);
10749   pic16_aopOp(result,ic,TRUE);
10750
10751   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10752
10753   /* if they are the same registers */
10754   if (pic16_sameRegs(AOP(right),AOP(result)))
10755     goto release;
10756
10757   /* if the result is a bit */
10758   if (AOP_TYPE(result) == AOP_CRY) {
10759     /* if the right size is a literal then
10760        we know what the value is */
10761     if (AOP_TYPE(right) == AOP_LIT) {
10762           
10763       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10764                   pic16_popGet(AOP(result),0));
10765
10766       if (((int) operandLitValue(right))) 
10767         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10768                        AOP(result)->aopu.aop_dir,
10769                        AOP(result)->aopu.aop_dir);
10770       else
10771         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10772                        AOP(result)->aopu.aop_dir,
10773                        AOP(result)->aopu.aop_dir);
10774       goto release;
10775     }
10776
10777     /* the right is also a bit variable */
10778     if (AOP_TYPE(right) == AOP_CRY) {
10779       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10780       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10781       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10782
10783       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10784                      AOP(result)->aopu.aop_dir,
10785                      AOP(result)->aopu.aop_dir);
10786       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10787                      AOP(right)->aopu.aop_dir,
10788                      AOP(right)->aopu.aop_dir);
10789       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10790                      AOP(result)->aopu.aop_dir,
10791                      AOP(result)->aopu.aop_dir);
10792       goto release ;
10793     }
10794
10795     /* we need to or */
10796     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10797     pic16_toBoolean(right);
10798     emitSKPZ;
10799     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10800     //pic16_aopPut(AOP(result),"a",0);
10801     goto release ;
10802   }
10803
10804   /* bit variables done */
10805   /* general case */
10806   size = AOP_SIZE(result);
10807   offset = 0 ;
10808
10809   if(AOP_TYPE(right) == AOP_LIT) {
10810         if(!IS_FLOAT(operandType( right )))
10811                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10812         else {
10813            union {
10814               unsigned long lit_int;
10815               float lit_float;
10816             } info;
10817         
10818                 /* take care if literal is a float */
10819                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10820                 lit = info.lit_int;
10821         }
10822   }
10823
10824 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10825 //                      sizeof(unsigned long int), sizeof(float));
10826
10827   if(AOP_TYPE(right) != AOP_LIT
10828         && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
10829         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
10830
10831         // set up table pointer
10832         if( (AOP_TYPE(right) == AOP_PCODE)
10833                 && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
10834                 || (AOP(right)->aopu.pcop->type == PO_DIR)))
10835         {
10836                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
10837                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
10838                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
10839                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
10840                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
10841                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
10842         } else {
10843                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
10844                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
10845                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
10846                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
10847                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
10848                                 pic16_popCopyReg(&pic16_pc_tblptru)));
10849         }
10850
10851         size = min(AOP_SIZE(right), AOP_SIZE(result));
10852         while(size--) {
10853                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
10854                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
10855                         pic16_popGet(AOP(result),offset)));
10856                 offset++;
10857         }
10858
10859         if(AOP_SIZE(result) > AOP_SIZE(right)) {
10860                 size = AOP_SIZE(result) - AOP_SIZE(right);
10861                 while(size--) {
10862                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
10863                         offset++;
10864                 }
10865         }
10866         goto release;
10867   }
10868
10869
10870
10871 /* VR - What is this?! */
10872   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10873   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10874     if(aopIdx(AOP(result),0) == 4) {
10875   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10876         assert(0);
10877       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10878       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10879       goto release;
10880     } else
10881 //      assert(0);
10882       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10883   }
10884
10885   know_W=-1;
10886   while (size--) {
10887   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10888     if(AOP_TYPE(right) == AOP_LIT) {
10889       if(lit&0xff) {
10890         if(know_W != (lit&0xff))
10891           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10892         know_W = lit&0xff;
10893         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10894       } else
10895         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10896
10897       lit >>= 8;
10898
10899     } else if (AOP_TYPE(right) == AOP_CRY) {
10900       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10901       if(offset == 0) {
10902         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10903         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10904       }
10905     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10906         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10907         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10908     } else {
10909   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10910
10911 #if 1
10912         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10913            normally should work, but mind that the W register live range
10914            is not checked, so if the code generator assumes that the W
10915            is already loaded after such a pair, wrong code will be generated.
10916            
10917            Checking the live range is the next step.
10918            This is experimental code yet and has not been fully tested yet.
10919            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10920            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10921            
10922         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10923 #else   
10924         /* This is the old code, which is assumed(?!) that works fine(!?) */
10925
10926         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10927         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10928 #endif
10929     }
10930             
10931     offset++;
10932   }
10933
10934     
10935  release:
10936   pic16_freeAsmop (right,NULL,ic,FALSE);
10937   pic16_freeAsmop (result,NULL,ic,TRUE);
10938 }   
10939
10940 /*-----------------------------------------------------------------*/
10941 /* genJumpTab - generates code for jump table                       */
10942 /*-----------------------------------------------------------------*/
10943 static void genJumpTab (iCode *ic)
10944 {
10945     symbol *jtab;
10946     char *l;
10947
10948     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10949
10950     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10951     /* get the condition into accumulator */
10952     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10953     MOVA(l);
10954     /* multiply by three */
10955     pic16_emitcode("add","a,acc");
10956     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10957
10958     jtab = newiTempLabel(NULL);
10959     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10960     pic16_emitcode("jmp","@a+dptr");
10961     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10962
10963     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10964     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10965     emitSKPNC;
10966     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10967     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10968     pic16_emitpLabel(jtab->key);
10969
10970     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10971
10972     /* now generate the jump labels */
10973     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10974          jtab = setNextItem(IC_JTLABELS(ic))) {
10975         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10976         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10977         
10978     }
10979
10980 }
10981
10982 /*-----------------------------------------------------------------*/
10983 /* genMixedOperation - gen code for operators between mixed types  */
10984 /*-----------------------------------------------------------------*/
10985 /*
10986   TSD - Written for the PIC port - but this unfortunately is buggy.
10987   This routine is good in that it is able to efficiently promote 
10988   types to different (larger) sizes. Unfortunately, the temporary
10989   variables that are optimized out by this routine are sometimes
10990   used in other places. So until I know how to really parse the 
10991   iCode tree, I'm going to not be using this routine :(.
10992 */
10993 static int genMixedOperation (iCode *ic)
10994 {
10995 #if 0
10996   operand *result = IC_RESULT(ic);
10997   sym_link *ctype = operandType(IC_LEFT(ic));
10998   operand *right = IC_RIGHT(ic);
10999   int ret = 0;
11000   int big,small;
11001   int offset;
11002
11003   iCode *nextic;
11004   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
11005
11006   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11007
11008   nextic = ic->next;
11009   if(!nextic)
11010     return 0;
11011
11012   nextright = IC_RIGHT(nextic);
11013   nextleft  = IC_LEFT(nextic);
11014   nextresult = IC_RESULT(nextic);
11015
11016   pic16_aopOp(right,ic,FALSE);
11017   pic16_aopOp(result,ic,FALSE);
11018   pic16_aopOp(nextright,  nextic, FALSE);
11019   pic16_aopOp(nextleft,   nextic, FALSE);
11020   pic16_aopOp(nextresult, nextic, FALSE);
11021
11022   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
11023
11024     operand *t = right;
11025     right = nextright;
11026     nextright = t; 
11027
11028     pic16_emitcode(";remove right +","");
11029
11030   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
11031 /*
11032     operand *t = right;
11033     right = nextleft;
11034     nextleft = t; 
11035 */
11036     pic16_emitcode(";remove left +","");
11037   } else
11038     return 0;
11039
11040   big = AOP_SIZE(nextleft);
11041   small = AOP_SIZE(nextright);
11042
11043   switch(nextic->op) {
11044
11045   case '+':
11046     pic16_emitcode(";optimize a +","");
11047     /* if unsigned or not an integral type */
11048     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
11049       pic16_emitcode(";add a bit to something","");
11050     } else {
11051
11052       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
11053
11054       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
11055         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
11056         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
11057       } else
11058         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
11059
11060       offset = 0;
11061       while(--big) {
11062
11063         offset++;
11064
11065         if(--small) {
11066           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11067             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11068             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11069           }
11070
11071           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11072           emitSKPNC;
11073           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11074                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
11075                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
11076           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11077           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
11078
11079         } else {
11080           pic16_emitcode("rlf","known_zero,w");
11081
11082           /*
11083             if right is signed
11084               btfsc  right,7
11085                addlw ff
11086           */
11087           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
11088             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
11089             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11090           } else {
11091             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
11092           }
11093         }
11094       }
11095       ret = 1;
11096     }
11097   }
11098   ret = 1;
11099
11100 release:
11101   pic16_freeAsmop(right,NULL,ic,TRUE);
11102   pic16_freeAsmop(result,NULL,ic,TRUE);
11103   pic16_freeAsmop(nextright,NULL,ic,TRUE);
11104   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
11105   if(ret)
11106     nextic->generated = 1;
11107
11108   return ret;
11109 #else
11110   return 0;
11111 #endif
11112 }
11113 /*-----------------------------------------------------------------*/
11114 /* genCast - gen code for casting                                  */
11115 /*-----------------------------------------------------------------*/
11116 static void genCast (iCode *ic)
11117 {
11118   operand *result = IC_RESULT(ic);
11119   sym_link *ctype = operandType(IC_LEFT(ic));
11120   sym_link *rtype = operandType(IC_RIGHT(ic));
11121   operand *right = IC_RIGHT(ic);
11122   int size, offset ;
11123
11124         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11125         /* if they are equivalent then do nothing */
11126         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
11127                 return ;
11128
11129         pic16_aopOp(right,ic,FALSE) ;
11130         pic16_aopOp(result,ic,FALSE);
11131
11132         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11133
11134         /* if the result is a bit */
11135         if (AOP_TYPE(result) == AOP_CRY) {
11136         
11137                 /* if the right size is a literal then
11138                  * we know what the value is */
11139                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11140
11141                 if (AOP_TYPE(right) == AOP_LIT) {
11142                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
11143                                 pic16_popGet(AOP(result),0));
11144
11145                         if (((int) operandLitValue(right))) 
11146                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
11147                                         AOP(result)->aopu.aop_dir,
11148                                         AOP(result)->aopu.aop_dir);
11149                         else
11150                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
11151                                         AOP(result)->aopu.aop_dir,
11152                                         AOP(result)->aopu.aop_dir);
11153                         goto release;
11154                 }
11155
11156                 /* the right is also a bit variable */
11157                 if (AOP_TYPE(right) == AOP_CRY) {
11158                         emitCLRC;
11159                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11160
11161                         pic16_emitcode("clrc","");
11162                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
11163                                 AOP(right)->aopu.aop_dir,
11164                                 AOP(right)->aopu.aop_dir);
11165                         pic16_aopPut(AOP(result),"c",0);
11166                         goto release ;
11167                 }
11168
11169                 /* we need to or */
11170                 if (AOP_TYPE(right) == AOP_REG) {
11171                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
11172                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
11173                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
11174                 }
11175                 pic16_toBoolean(right);
11176                 pic16_aopPut(AOP(result),"a",0);
11177                 goto release ;
11178         }
11179
11180         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
11181           int offset = 1;
11182
11183                 size = AOP_SIZE(result);
11184
11185                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11186
11187                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
11188                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
11189                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
11190
11191                 while (size--)
11192                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11193
11194                 goto release;
11195         }
11196
11197         /* if they are the same size : or less */
11198         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
11199
11200                 /* if they are in the same place */
11201                 if (pic16_sameRegs(AOP(right),AOP(result)))
11202                         goto release;
11203
11204                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11205 #if 0
11206                 if (IS_PTR_CONST(rtype))
11207 #else
11208                 if (IS_CODEPTR(rtype))
11209 #endif
11210                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
11211
11212 #if 0
11213                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
11214 #else
11215                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
11216 #endif
11217                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
11218
11219 #if 0
11220                 if(AOP_TYPE(right) == AOP_IMMD) {
11221                   pCodeOp *pcop0, *pcop1, *pcop2;
11222                   symbol *sym = OP_SYMBOL( right );
11223
11224                         size = AOP_SIZE(result);
11225                         /* low */
11226                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11227                         /* high */
11228                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11229                         /* upper */
11230                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
11231         
11232                         if (size == 3) {
11233                                 pic16_emitpcode(POC_MOVLW, pcop0);
11234                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
11235                                 pic16_emitpcode(POC_MOVLW, pcop1);
11236                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
11237                                 pic16_emitpcode(POC_MOVLW, pcop2);
11238                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
11239                         } else
11240                         if (size == 2) {
11241                                 pic16_emitpcode(POC_MOVLW, pcop0);
11242                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11243                                 pic16_emitpcode(POC_MOVLW, pcop1);
11244                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11245                         } else {
11246                                 pic16_emitpcode(POC_MOVLW, pcop0);
11247                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11248                         }
11249                 } else
11250 #endif
11251                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11252                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
11253                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
11254                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
11255                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
11256                         if(AOP_SIZE(result) <2)
11257                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
11258                 } else {
11259                         /* if they in different places then copy */
11260                         size = AOP_SIZE(result);
11261                         offset = 0 ;
11262                         while (size--) {
11263                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11264                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11265                                 offset++;
11266                         }
11267                 }
11268                 goto release;
11269         }
11270
11271         /* if the result is of type pointer */
11272         if (IS_PTR(ctype)) {
11273           int p_type;
11274           sym_link *type = operandType(right);
11275           sym_link *etype = getSpec(type);
11276
11277                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11278
11279                 /* pointer to generic pointer */
11280                 if (IS_GENPTR(ctype)) {
11281                   char *l = zero;
11282             
11283                         if (IS_PTR(type)) 
11284                                 p_type = DCL_TYPE(type);
11285                         else {
11286                 /* we have to go by the storage class */
11287                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11288
11289 /*              if (SPEC_OCLS(etype)->codesp )  */
11290 /*                  p_type = CPOINTER ;  */
11291 /*              else */
11292 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11293 /*                      p_type = FPOINTER ; */
11294 /*                  else */
11295 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11296 /*                          p_type = PPOINTER; */
11297 /*                      else */
11298 /*                          if (SPEC_OCLS(etype) == idata ) */
11299 /*                              p_type = IPOINTER ; */
11300 /*                          else */
11301 /*                              p_type = POINTER ; */
11302             }
11303                 
11304             /* the first two bytes are known */
11305       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11306             size = GPTRSIZE - 1; 
11307             offset = 0 ;
11308             while (size--) {
11309               if(offset < AOP_SIZE(right)) {
11310       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11311                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11312                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11313                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11314                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11315                 } else { 
11316                   pic16_aopPut(AOP(result),
11317                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11318                          offset);
11319                 }
11320               } else 
11321                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11322               offset++;
11323             }
11324             /* the last byte depending on type */
11325             switch (p_type) {
11326             case IPOINTER:
11327             case POINTER:
11328                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11329                 break;
11330             case FPOINTER:
11331               pic16_emitcode(";BUG!? ","%d",__LINE__);
11332                 l = one;
11333                 break;
11334             case CPOINTER:
11335               pic16_emitcode(";BUG!? ","%d",__LINE__);
11336                 l = "#0x02";
11337                 break;                          
11338             case PPOINTER:
11339               pic16_emitcode(";BUG!? ","%d",__LINE__);
11340                 l = "#0x03";
11341                 break;
11342                 
11343             default:
11344                 /* this should never happen */
11345                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11346                        "got unknown pointer type");
11347                 exit(1);
11348             }
11349             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11350             goto release ;
11351         }
11352         
11353         /* just copy the pointers */
11354         size = AOP_SIZE(result);
11355         offset = 0 ;
11356         while (size--) {
11357             pic16_aopPut(AOP(result),
11358                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11359                    offset);
11360             offset++;
11361         }
11362         goto release ;
11363     }
11364     
11365
11366
11367     /* so we now know that the size of destination is greater
11368     than the size of the source.
11369     Now, if the next iCode is an operator then we might be
11370     able to optimize the operation without performing a cast.
11371     */
11372     if(genMixedOperation(ic))
11373       goto release;
11374
11375     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11376     
11377     /* we move to result for the size of source */
11378     size = AOP_SIZE(right);
11379     offset = 0 ;
11380     while (size--) {
11381       pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
11382 //      pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11383 //      pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11384       offset++;
11385     }
11386
11387     /* now depending on the sign of the destination */
11388     size = AOP_SIZE(result) - AOP_SIZE(right);
11389     /* if unsigned or not an integral type */
11390     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11391       while (size--)
11392         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11393     } else {
11394       /* we need to extend the sign :( */
11395
11396       if(size == 1) {
11397         /* Save one instruction of casting char to int */
11398         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11399         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11400         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11401       } else {
11402         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11403
11404         if(offset)
11405           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11406         else
11407           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
11408         
11409         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11410
11411         while (size--)
11412           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11413       }
11414     }
11415
11416 release:
11417     pic16_freeAsmop(right,NULL,ic,TRUE);
11418     pic16_freeAsmop(result,NULL,ic,TRUE);
11419
11420 }
11421
11422 /*-----------------------------------------------------------------*/
11423 /* genDjnz - generate decrement & jump if not zero instrucion      */
11424 /*-----------------------------------------------------------------*/
11425 static int genDjnz (iCode *ic, iCode *ifx)
11426 {
11427     symbol *lbl, *lbl1;
11428     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11429
11430     if (!ifx)
11431         return 0;
11432     
11433     /* if the if condition has a false label
11434        then we cannot save */
11435     if (IC_FALSE(ifx))
11436         return 0;
11437
11438     /* if the minus is not of the form 
11439        a = a - 1 */
11440     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11441         !IS_OP_LITERAL(IC_RIGHT(ic)))
11442         return 0;
11443
11444     if (operandLitValue(IC_RIGHT(ic)) != 1)
11445         return 0;
11446
11447     /* if the size of this greater than one then no
11448        saving */
11449     if (getSize(operandType(IC_RESULT(ic))) > 1)
11450         return 0;
11451
11452     /* otherwise we can save BIG */
11453     lbl = newiTempLabel(NULL);
11454     lbl1= newiTempLabel(NULL);
11455
11456     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11457     
11458     if (IS_AOP_PREG(IC_RESULT(ic))) {
11459         pic16_emitcode("dec","%s",
11460                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11461         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11462         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11463     } else {    
11464
11465
11466       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11467       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11468
11469       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11470       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
11471
11472     }
11473 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11474 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11475 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11476 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11477
11478     
11479     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11480     ifx->generated = 1;
11481     return 1;
11482 }
11483
11484 /*-----------------------------------------------------------------*/
11485 /* genReceive - generate code for a receive iCode                  */
11486 /*-----------------------------------------------------------------*/
11487 static void genReceive (iCode *ic)
11488 {    
11489         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11490
11491 #if 0
11492         fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
11493                 OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
11494 #endif
11495 //      pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
11496
11497         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11498                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11499                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11500
11501           int size = getSize(operandType(IC_RESULT(ic)));
11502           int offset =  pic16_fReturnSizePic - size;
11503
11504                 assert( 0 );
11505                 while (size--) {
11506                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11507                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11508                         offset++;
11509                 }
11510
11511                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11512
11513                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11514                 size = AOP_SIZE(IC_RESULT(ic));
11515                 offset = 0;
11516                 while (size--) {
11517                         pic16_emitcode ("pop","acc");
11518                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11519                 }
11520         } else {
11521                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11522
11523                 _G.accInUse++;
11524                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11525                 _G.accInUse--;
11526                 assignResultValue(IC_RESULT(ic), 0);
11527         }
11528
11529         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11530 }
11531
11532 /*-----------------------------------------------------------------*/
11533 /* genDummyRead - generate code for dummy read of volatiles        */
11534 /*-----------------------------------------------------------------*/
11535 static void
11536 genDummyRead (iCode * ic)
11537 {
11538   pic16_emitcode ("; genDummyRead","");
11539   pic16_emitcode ("; not implemented","");
11540
11541   ic = ic;
11542 }
11543
11544 /*-----------------------------------------------------------------*/
11545 /* genpic16Code - generate code for pic16 based controllers        */
11546 /*-----------------------------------------------------------------*/
11547 /*
11548  * At this point, ralloc.c has gone through the iCode and attempted
11549  * to optimize in a way suitable for a PIC. Now we've got to generate
11550  * PIC instructions that correspond to the iCode.
11551  *
11552  * Once the instructions are generated, we'll pass through both the
11553  * peep hole optimizer and the pCode optimizer.
11554  *-----------------------------------------------------------------*/
11555
11556 void genpic16Code (iCode *lic)
11557 {
11558     iCode *ic;
11559     int cln = 0;
11560
11561     lineHead = lineCurr = NULL;
11562
11563     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11564     pic16_addpBlock(pb);
11565
11566 #if 0
11567     /* if debug information required */
11568     if (options.debug && currFunc) {
11569       if (currFunc) {
11570         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11571       }
11572     }
11573 #endif
11574
11575     for (ic = lic ; ic ; ic = ic->next ) {
11576
11577       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11578         if ( cln != ic->lineno ) {
11579             if ( options.debug ) {
11580               debugFile->writeCLine (ic);
11581             }
11582             
11583             if(!options.noCcodeInAsm) {
11584                 pic16_addpCode2pBlock(pb,
11585                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11586                                 printCLine(ic->filename, ic->lineno)));
11587             }
11588
11589             cln = ic->lineno ;
11590         }
11591         
11592         if(options.iCodeInAsm) {
11593                 char *l;
11594                 /* insert here code to print iCode as comment */
11595                 l = Safe_strdup(printILine(ic));
11596                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11597         }
11598         
11599         /* if the result is marked as
11600            spilt and rematerializable or code for
11601            this has already been generated then
11602            do nothing */
11603         if (resultRemat(ic) || ic->generated ) 
11604             continue ;
11605         
11606         /* depending on the operation */
11607         switch (ic->op) {
11608         case '!' :
11609             pic16_genNot(ic);
11610             break;
11611             
11612         case '~' :
11613             pic16_genCpl(ic);
11614             break;
11615             
11616         case UNARYMINUS:
11617             genUminus (ic);
11618             break;
11619             
11620         case IPUSH:
11621             genIpush (ic);
11622             break;
11623             
11624         case IPOP:
11625             /* IPOP happens only when trying to restore a 
11626                spilt live range, if there is an ifx statement
11627                following this pop then the if statement might
11628                be using some of the registers being popped which
11629                would destroy the contents of the register so
11630                we need to check for this condition and handle it */
11631             if (ic->next            && 
11632                 ic->next->op == IFX &&
11633                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11634                 genIfx (ic->next,ic);
11635             else
11636                 genIpop (ic);
11637             break; 
11638             
11639         case CALL:
11640             genCall (ic);
11641             break;
11642             
11643         case PCALL:
11644             genPcall (ic);
11645             break;
11646             
11647         case FUNCTION:
11648             genFunction (ic);
11649             break;
11650             
11651         case ENDFUNCTION:
11652             genEndFunction (ic);
11653             break;
11654             
11655         case RETURN:
11656             genRet (ic);
11657             break;
11658             
11659         case LABEL:
11660             genLabel (ic);
11661             break;
11662             
11663         case GOTO:
11664             genGoto (ic);
11665             break;
11666             
11667         case '+' :
11668             pic16_genPlus (ic) ;
11669             break;
11670             
11671         case '-' :
11672             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11673                 pic16_genMinus (ic);
11674             break;
11675             
11676         case '*' :
11677             genMult (ic);
11678             break;
11679             
11680         case '/' :
11681             genDiv (ic) ;
11682             break;
11683             
11684         case '%' :
11685             genMod (ic);
11686             break;
11687             
11688         case '>' :
11689             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11690             break;
11691             
11692         case '<' :
11693             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11694             break;
11695             
11696         case LE_OP:
11697         case GE_OP:
11698         case NE_OP:
11699             
11700             /* note these two are xlated by algebraic equivalence
11701                during parsing SDCC.y */
11702             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11703                    "got '>=' or '<=' shouldn't have come here");
11704             break;      
11705             
11706         case EQ_OP:
11707             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11708             break;          
11709             
11710         case AND_OP:
11711             genAndOp (ic);
11712             break;
11713             
11714         case OR_OP:
11715             genOrOp (ic);
11716             break;
11717             
11718         case '^' :
11719             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11720             break;
11721             
11722         case '|' :
11723                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11724             break;
11725             
11726         case BITWISEAND:
11727             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11728             break;
11729             
11730         case INLINEASM:
11731             genInline (ic);
11732             break;
11733             
11734         case RRC:
11735             genRRC (ic);
11736             break;
11737             
11738         case RLC:
11739             genRLC (ic);
11740             break;
11741             
11742         case GETHBIT:
11743             genGetHbit (ic);
11744             break;
11745             
11746         case LEFT_OP:
11747             genLeftShift (ic);
11748             break;
11749             
11750         case RIGHT_OP:
11751             genRightShift (ic);
11752             break;
11753             
11754         case GET_VALUE_AT_ADDRESS:
11755             genPointerGet(ic);
11756             break;
11757             
11758         case '=' :
11759             if (POINTER_SET(ic))
11760                 genPointerSet(ic);
11761             else
11762                 genAssign(ic);
11763             break;
11764             
11765         case IFX:
11766             genIfx (ic,NULL);
11767             break;
11768             
11769         case ADDRESS_OF:
11770             genAddrOf (ic);
11771             break;
11772             
11773         case JUMPTABLE:
11774             genJumpTab (ic);
11775             break;
11776             
11777         case CAST:
11778             genCast (ic);
11779             break;
11780             
11781         case RECEIVE:
11782             genReceive(ic);
11783             break;
11784             
11785         case SEND:
11786             addSet(&_G.sendSet,ic);
11787             break;
11788
11789         case DUMMY_READ_VOLATILE:
11790           genDummyRead (ic);
11791           break;
11792
11793         default :
11794             ic = ic;
11795         }
11796     }
11797
11798
11799     /* now we are ready to call the
11800        peep hole optimizer */
11801     if (!options.nopeep) {
11802       peepHole (&lineHead);
11803     }
11804     /* now do the actual printing */
11805     printLine (lineHead,codeOutFile);
11806
11807 #ifdef PCODE_DEBUG
11808     DFPRINTF((stderr,"printing pBlock\n\n"));
11809     pic16_printpBlock(stdout,pb);
11810 #endif
11811
11812     return;
11813 }
11814