* src/pic16/device.c (Pics16[]): added devices 18F2550, 18F4331,
[fw/sdcc] / src / pic16 / genutils.c
1 /*-------------------------------------------------------------------------
2  genutils.c - source file for code generation for pic16
3         code generation utility functions
4
5         Created by Vangelis Rokas (vrokas@otenet.gr) [Nov-2003]
6
7         Based on :
8
9   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
10          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
11   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
12   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
13   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
14   
15   This program is free software; you can redistribute it and/or modify it
16   under the terms of the GNU General Public License as published by the
17   Free Software Foundation; either version 2, or (at your option) any
18   later version.
19   
20   This program is distributed in the hope that it will be useful,
21   but WITHOUT ANY WARRANTY; without even the implied warranty of
22   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23   GNU General Public License for more details.
24   
25   You should have received a copy of the GNU General Public License
26   along with this program; if not, write to the Free Software
27   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28   
29   In other words, you are welcome to use, share and improve this program.
30   You are forbidden to forbid anyone else to use, share and improve
31   what you give them.   Help stamp out software-hoarding!
32   
33   Notes:
34   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
35                 Made everything static
36 -------------------------------------------------------------------------*/
37
38 /**********************************************************
39  * Here is a list with completed genXXXXX functions
40  *
41  * genNot
42  *
43  */
44
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <ctype.h>
50 #include "SDCCglobl.h"
51 #include "newalloc.h"
52
53 #include "common.h"
54 #include "SDCCpeeph.h"
55 #include "ralloc.h"
56 #include "pcode.h"
57 #include "device.h"
58 #include "gen.h"
59
60 #include "genutils.h"
61
62 #if 1
63 #define pic16_emitcode  DEBUGpic16_emitcode
64 #endif
65
66 #if defined(GEN_Not)
67 /*-----------------------------------------------------------------*/
68 /* pic16_genNot - generate code for ! operation                    */
69 /*-----------------------------------------------------------------*/
70 void pic16_genNot (iCode *ic)
71 {
72   int size;
73 //  symbol *tlbl;
74
75 /*
76  * result[AOP_CRY,AOP_REG]  = ! left[AOP_CRY, AOP_REG]
77  */
78
79     FENTRY;
80    
81     /* assign asmOps to operand & result */
82     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
83     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
84     DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
85
86     /* if in bit space then a special case */
87     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
88       if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
89         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
90         pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
91       } else {
92         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
93         pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
94         pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
95       }
96       goto release;
97     }
98
99     size = AOP_SIZE(IC_LEFT(ic));
100 #if 0
101     if(size == 1) {
102       pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
103       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
104       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
105       goto release;
106     }
107 #endif
108
109     pic16_toBoolean( IC_LEFT(ic) );
110     emitSETC;
111     pic16_emitpcode(POC_TSTFSZ, pic16_popCopyReg( &pic16_pc_wreg ));
112     emitCLRC;
113     pic16_outBitC( IC_RESULT(ic) );
114
115 release:    
116     /* release the aops */
117     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
118     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
119 }
120
121 #endif  /* defined(GEN_Not) */
122
123
124
125 #if defined(GEN_Cpl)
126 /*-----------------------------------------------------------------*/
127 /* pic16_genCpl - generate code for complement                     */
128 /*-----------------------------------------------------------------*/
129 void pic16_genCpl (iCode *ic)
130 {
131   int offset = 0;
132   int size ;
133
134 /*
135  * result[CRY,REG] = ~left[CRY,REG]
136  */
137     FENTRY;
138
139     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
140     /* assign asmOps to operand & result */
141     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
142     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
143     DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
144
145     /* if both are in bit space then 
146      * a special case */
147     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
148       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
149
150         /* FIXME */
151         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
152         pic16_emitcode("cpl","c"); 
153         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
154         goto release; 
155     } 
156
157     size = AOP_SIZE(IC_RESULT(ic));
158     while (size--) {
159       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
160         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
161       } else {
162         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
163         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
164       }
165       offset++;
166     }
167
168 release:
169     /* release the aops */
170     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
171     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
172 }
173 #endif  /* defined(GEN_Cpl) */
174
175
176
177 /*-----------------------------------------------------------------*/
178 /* Helper function to dump operand into comment lines              */
179 /*-----------------------------------------------------------------*/
180
181 void pic16_DumpValue(char *prefix, value *val)
182 {
183 //      char s[INITIAL_INLINEASM];  
184         if(!val) return;
185
186         DEBUGpic16_emitcode (";", " %s Dump value",prefix);
187         DEBUGpic16_emitcode (";", " %s name:%s",prefix,val->name);
188 }
189
190 void pic16_DumpPcodeOp(char *prefix, pCodeOp *pcop)
191 {
192 //      char s[INITIAL_INLINEASM];  
193         if(!pcop) return;
194
195         DEBUGpic16_emitcode (";", " %s Dump pCodeOp",prefix);
196         DEBUGpic16_emitcode (";", " %s name:%s",prefix,pcop->name);
197         if(pcop->type == PO_NONE) {
198                 DEBUGpic16_emitcode (";", " %s type:PO_NONE",prefix);
199         }
200         if(pcop->type == PO_W) {
201                 DEBUGpic16_emitcode (";", " %s type:PO_W",prefix);
202         }
203         if(pcop->type == PO_WREG) {
204                 DEBUGpic16_emitcode (";", " %s type:PO_WREG",prefix);
205         }
206         if(pcop->type == PO_STATUS) {
207                 DEBUGpic16_emitcode (";", " %s type:PO_STATUS",prefix);
208         }
209         if(pcop->type == PO_BSR) {
210                 DEBUGpic16_emitcode (";", " %s type:PO_BSR",prefix);
211         }
212         if(pcop->type == PO_FSR0) {
213                 DEBUGpic16_emitcode (";", " %s type:PO_FSR0",prefix);
214         }
215         if(pcop->type == PO_INDF0) {
216                 DEBUGpic16_emitcode (";", " %s type:PO_INDF0",prefix);
217         }
218         if(pcop->type == PO_INTCON) {
219                 DEBUGpic16_emitcode (";", " %s type:PO_INTCON",prefix);
220         }
221         if(pcop->type == PO_GPR_REGISTER) {
222                 DEBUGpic16_emitcode (";", " %s type:PO_GPR_REGISTER",prefix);
223         }
224         if(pcop->type == PO_GPR_BIT) {
225                 DEBUGpic16_emitcode (";", " %s type:PO_GPR_BIT",prefix);
226         }
227         if(pcop->type == PO_GPR_TEMP) {
228                 DEBUGpic16_emitcode (";", " %s type:PO_GPR_TEMP",prefix);
229         }
230         if(pcop->type == PO_SFR_REGISTER) {
231                 DEBUGpic16_emitcode (";", " %s type:PO_SFR_REGISTER",prefix);
232         }
233         if(pcop->type == PO_PCL) {
234                 DEBUGpic16_emitcode (";", " %s type:PO_PCL",prefix);
235         }
236         if(pcop->type == PO_PCLATH) {
237                 DEBUGpic16_emitcode (";", " %s type:PO_PCLATH",prefix);
238         }
239         if(pcop->type == PO_LITERAL) {
240                 DEBUGpic16_emitcode (";", " %s type:PO_LITERAL",prefix);
241                 DEBUGpic16_emitcode (";", " %s lit:%s",prefix,PCOL(pcop)->lit);
242         }
243         if(pcop->type == PO_REL_ADDR) {
244                 DEBUGpic16_emitcode (";", " %s type:PO_REL_ADDR",prefix);
245         }
246         if(pcop->type == PO_IMMEDIATE) {
247                 DEBUGpic16_emitcode (";", " %s type:PO_IMMEDIATE",prefix);
248         }
249         if(pcop->type == PO_DIR) {
250                 DEBUGpic16_emitcode (";", " %s type:PO_DIR",prefix);
251         }
252         if(pcop->type == PO_CRY) {
253                 DEBUGpic16_emitcode (";", " %s type:PO_CRY",prefix);
254         }
255         if(pcop->type == PO_BIT) {
256                 DEBUGpic16_emitcode (";", " %s type:PO_BIT",prefix);
257         }
258         if(pcop->type == PO_STR) {
259                 DEBUGpic16_emitcode (";", " %s type:PO_STR",prefix);
260         }
261         if(pcop->type == PO_LABEL) {
262                 DEBUGpic16_emitcode (";", " %s type:PO_LABEL",prefix);
263         }
264         if(pcop->type == PO_WILD) {
265                 DEBUGpic16_emitcode (";", " %s type:PO_WILD",prefix);
266         }
267 }
268
269
270
271 void pic16_DumpAop(char *prefix, asmop *aop)
272 {
273         char s[INITIAL_INLINEASM];  
274         if(!aop) return;
275
276         DEBUGpic16_emitcode (";", " %s Dump asmop",prefix);
277         if (aop->type == AOP_LIT)
278         {
279                 DEBUGpic16_emitcode (";", " %s type:AOP_LIT",prefix);
280                 sprintf(s,"%s (aopu.aop_lit)",prefix);
281                 pic16_DumpValue(s,aop->aopu.aop_lit);
282         }
283         if (aop->type == AOP_REG)
284                 DEBUGpic16_emitcode (";", " %s type:AOP_REG",prefix);
285         if (aop->type == AOP_DIR)
286         {
287                 DEBUGpic16_emitcode (";", " %s type:AOP_DIR",prefix);
288                 DEBUGpic16_emitcode (";", " %s aopu.aop_dir:%s",prefix,aop->aopu.aop_dir);
289         }
290         if (aop->type == AOP_DPTR)
291                 DEBUGpic16_emitcode (";", " %s type:AOP_DPTR",prefix);
292         if (aop->type == AOP_DPTR2)
293                 DEBUGpic16_emitcode (";", " %s type:AOP_DPTR2",prefix);
294         if (aop->type == AOP_R0)
295                 DEBUGpic16_emitcode (";", " %s type:AOP_R0",prefix);
296         if (aop->type == AOP_R1)
297                 DEBUGpic16_emitcode (";", " %s type:AOP_R1",prefix);
298         if (aop->type == AOP_STK)
299                 DEBUGpic16_emitcode (";", " %s type:AOP_STK",prefix);
300         if (aop->type == AOP_STA)
301                 DEBUGpic16_emitcode (";", " %s type:AOP_STA",prefix);
302         if (aop->type == AOP_IMMD)
303         {
304                 DEBUGpic16_emitcode (";", " %s type:AOP_IMMD",prefix);
305                 DEBUGpic16_emitcode (";", " %s aopu.aop_immd:%s",prefix,aop->aopu.aop_immd);
306         }
307         if (aop->type == AOP_STR)
308         {
309                 DEBUGpic16_emitcode (";", " %s type:AOP_STR",prefix);
310                 DEBUGpic16_emitcode (";", " %s aopu.aop_str:%s/%s/%s/%s",prefix,aop->aopu.aop_str[0],
311                                 aop->aopu.aop_str[1],aop->aopu.aop_str[2],aop->aopu.aop_str[3]);
312         }
313         if (aop->type == AOP_CRY)
314                 DEBUGpic16_emitcode (";", " %s type:AOP_CRY",prefix);
315         if (aop->type == AOP_ACC)
316                 DEBUGpic16_emitcode (";", " %s type:AOP_ACC",prefix);
317         if (aop->type == AOP_PCODE)
318         {
319                 DEBUGpic16_emitcode (";", " %s type:AOP_PCODE",prefix);
320                 sprintf(s,"%s (aopu.pcop)",prefix);
321                 pic16_DumpPcodeOp(s,aop->aopu.pcop);
322         }
323
324
325         DEBUGpic16_emitcode (";", " %s coff:%d",prefix,aop->coff);
326         DEBUGpic16_emitcode (";", " %s size:%d",prefix,aop->size);
327         DEBUGpic16_emitcode (";", " %s code:%d",prefix,aop->code);
328         DEBUGpic16_emitcode (";", " %s paged:%d",prefix,aop->paged);
329         DEBUGpic16_emitcode (";", " %s freed:%d",prefix,aop->freed);
330
331 }
332
333 void pic16_DumpSymbol(char *prefix, symbol *sym)
334 {
335         char s[INITIAL_INLINEASM];  
336         if(!sym) return;
337
338         DEBUGpic16_emitcode (";", " %s Dump symbol",prefix);
339         DEBUGpic16_emitcode (";", " %s name:%s",prefix,sym->name);
340         DEBUGpic16_emitcode (";", " %s rname:%s",prefix,sym->rname);
341         DEBUGpic16_emitcode (";", " %s level:%d",prefix,sym->level);
342         DEBUGpic16_emitcode (";", " %s block:%d",prefix,sym->block);
343         DEBUGpic16_emitcode (";", " %s key:%d",prefix,sym->key);
344         DEBUGpic16_emitcode (";", " %s implicit:%d",prefix,sym->implicit);
345         DEBUGpic16_emitcode (";", " %s undefined:%d",prefix,sym->undefined);
346         DEBUGpic16_emitcode (";", " %s _isparm:%d",prefix,sym->_isparm);
347         DEBUGpic16_emitcode (";", " %s ismyparm:%d",prefix,sym->ismyparm);
348         DEBUGpic16_emitcode (";", " %s isitmp:%d",prefix,sym->isitmp);
349         DEBUGpic16_emitcode (";", " %s islbl:%d",prefix,sym->islbl);
350         DEBUGpic16_emitcode (";", " %s isref:%d",prefix,sym->isref);
351         DEBUGpic16_emitcode (";", " %s isind:%d",prefix,sym->isind);
352         DEBUGpic16_emitcode (";", " %s isinvariant:%d",prefix,sym->isinvariant);
353         DEBUGpic16_emitcode (";", " %s cdef:%d",prefix,sym->cdef);
354         DEBUGpic16_emitcode (";", " %s addrtaken:%d",prefix,sym->addrtaken);
355         DEBUGpic16_emitcode (";", " %s isreqv:%d",prefix,sym->isreqv);
356         DEBUGpic16_emitcode (";", " %s udChked:%d",prefix,sym->udChked);
357         DEBUGpic16_emitcode (";", " %s isLiveFcall:%d",prefix,sym->isLiveFcall);
358         DEBUGpic16_emitcode (";", " %s isspilt:%d",prefix,sym->isspilt);
359         DEBUGpic16_emitcode (";", " %s spillA:%d",prefix,sym->spillA);
360         DEBUGpic16_emitcode (";", " %s remat:%d",prefix,sym->remat);
361         DEBUGpic16_emitcode (";", " %s isptr:%d",prefix,sym->isptr);
362         DEBUGpic16_emitcode (";", " %s uptr:%d",prefix,sym->uptr);
363         DEBUGpic16_emitcode (";", " %s isFree:%d",prefix,sym->isFree);
364         DEBUGpic16_emitcode (";", " %s islocal:%d",prefix,sym->islocal);
365         DEBUGpic16_emitcode (";", " %s blockSpil:%d",prefix,sym->blockSpil);
366         DEBUGpic16_emitcode (";", " %s remainSpil:%d",prefix,sym->remainSpil);
367         DEBUGpic16_emitcode (";", " %s stackSpil:%d",prefix,sym->stackSpil);
368         DEBUGpic16_emitcode (";", " %s onStack:%d",prefix,sym->onStack);
369         DEBUGpic16_emitcode (";", " %s iaccess:%d",prefix,sym->iaccess);
370         DEBUGpic16_emitcode (";", " %s ruonly:%d",prefix,sym->ruonly);
371         DEBUGpic16_emitcode (";", " %s spildir:%d",prefix,sym->spildir);
372         DEBUGpic16_emitcode (";", " %s ptrreg:%d",prefix,sym->ptrreg);
373         DEBUGpic16_emitcode (";", " %s noSpilLoc:%d",prefix,sym->noSpilLoc);
374         DEBUGpic16_emitcode (";", " %s isstrlit:%d",prefix,sym->isstrlit);
375         DEBUGpic16_emitcode (";", " %s accuse:%d",prefix,sym->accuse);
376         DEBUGpic16_emitcode (";", " %s dptr:%d",prefix,sym->dptr);
377         DEBUGpic16_emitcode (";", " %s allocreq:%d",prefix,sym->allocreq);
378         DEBUGpic16_emitcode (";", " %s stack:%d",prefix,sym->stack);
379         DEBUGpic16_emitcode (";", " %s xstack:%d",prefix,sym->xstack);
380         DEBUGpic16_emitcode (";", " %s nRegs:%d",prefix,sym->nRegs);
381         DEBUGpic16_emitcode (";", " %s regType:%d",prefix,sym->regType);
382
383         // struct regs !!!
384
385         if(sym->aop)
386         {
387                 sprintf(s,"%s (aop)",prefix);
388                 pic16_DumpAop(s,sym->aop);
389         } else {
390                 DEBUGpic16_emitcode (";", " %s aop:NULL",prefix);
391         }
392 }
393
394 void pic16_DumpOp(char *prefix, operand *op)
395 {
396         char s[INITIAL_INLINEASM];  
397         if(!op) return;
398
399         DEBUGpic16_emitcode (";", " %s Dump operand",prefix);
400         if(IS_SYMOP(op))
401                 DEBUGpic16_emitcode (";", " %s type: SYMBOL",prefix);
402         if(IS_VALOP(op))
403                 DEBUGpic16_emitcode (";", " %s type: VALUE",prefix);
404         if(IS_TYPOP(op))
405                 DEBUGpic16_emitcode (";", " %s type: TYPE",prefix);
406         DEBUGpic16_emitcode (";", " %s isaddr:%d",prefix,op->isaddr);
407         DEBUGpic16_emitcode (";", " %s isvolatile:%d",prefix,op->isvolatile);
408         DEBUGpic16_emitcode (";" ," %s isGlobal:%d",prefix,op->isGlobal);
409         DEBUGpic16_emitcode (";", " %s isPtr:%d",prefix,op->isPtr);
410         DEBUGpic16_emitcode (";", " %s isGptr:%d",prefix,op->isGptr);
411         DEBUGpic16_emitcode (";", " %s isParm:%d",prefix,op->isParm);
412         DEBUGpic16_emitcode (";", " %s isLiteral:%d",prefix,op->isLiteral);
413         DEBUGpic16_emitcode (";", " %s key:%d",prefix,op->key);
414         if(IS_SYMOP(op)) {
415                 sprintf(s,"%s (symOperand)",prefix);
416                 pic16_DumpSymbol(s,op->operand.symOperand);
417         }
418
419 }
420
421 void _debugf(char *f, int l, char *frm, ...)
422 {
423   va_list ap;
424   
425     va_start(ap, frm);
426     fprintf(stderr, "%s:%d ", f, l);
427     vfprintf(stderr, frm, ap);
428     va_end(ap);
429 }
430
431
432
433 void gpsimio2_pcop(pCodeOp *pcop)
434 {
435   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_gpsimio2)));
436 }
437
438 void gpsimio2_lit(unsigned char lit)
439 {
440   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit));
441   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_wreg), pic16_popCopyReg(&pic16_pc_gpsimio2)));
442 }
443
444 void gpsimio2_str(char *buf)
445 {
446   while(*buf) {
447     gpsimio2_lit(*buf);
448     buf++;
449   }
450 }
451
452 void gpsimDebug_StackDump(char *fname, int line, char *info)
453 {
454   pic16_emitpcomment("; gpsim debug stack dump; %s @ %d\tinfo: ", fname, line, info);
455   
456   gpsimio2_str("&c[S:");
457   gpsimio2_str(info);
458   gpsimio2_str("] &h");
459   
460   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_fsr1h),
461                 pic16_popCopyReg(&pic16_pc_gpsimio2)));
462   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_fsr1l),
463                 pic16_popCopyReg(&pic16_pc_gpsimio2)));
464
465   gpsimio2_lit('\n');
466 }
467
468 const char *gptr_fns[4][2] = {
469   { "_gptrget1", "_gptrput1" },
470   { "_gptrget2", "_gptrput2" },
471   { "_gptrget3", "_gptrput3" },
472   { "_gptrget4", "_gptrput4" } };
473
474 extern set *externs;
475   
476 /* generate a call to the generic pointer read/write functions */
477 void pic16_callGenericPointerRW(int rw, int size)
478 {
479   char buf[32];
480   symbol *sym;
481
482     if(size>4) {
483       werror(W_POSSBUG2, __FILE__, __LINE__);
484       abort();
485     }
486
487     strcpy(buf, port->fun_prefix);
488     strcat(buf, gptr_fns[size-1][rw]);
489     
490     pic16_emitpcode (POC_CALL, pic16_popGetWithString (buf));
491     
492     sym = newSymbol( buf, 0 );
493     sym->used++;
494     strcpy(sym->rname, buf);
495     checkAddSym(&externs, sym);
496 }
497
498
499
500 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
501 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
502         operand *result, int offset, int invert_op)
503 {
504   /* add code here */
505   
506   /* check condition, > or < ?? */
507   if(rIfx->condition != 0)invert_op ^= 1;
508   
509   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
510
511   if(!ifx)invert_op ^= 1;
512
513   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
514       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
515   
516   /* do selection */
517   if(!invert_op)return POC_CPFSGT;
518   else return POC_CPFSLT;
519 }
520
521 /* return 1 if function handles compare, 0 otherwise */
522 /* this functions handles special cases like:
523  * reg vs. zero
524  * reg vs. one
525  */
526 int pic16_genCmp_special(operand *left, operand *right, operand *result,
527                     iCode *ifx, resolvedIfx *rIfx, int sign)
528 {
529   int size;
530   int offs=0;
531   symbol *tmplbl;
532   unsigned long lit;
533   int op, cmp_op=0, cond_pre;
534
535     FENTRY;
536     
537     if(!(pic16_options.opt_flags & OF_OPTIMIZE_CMP))return 0;
538
539     size = max(AOP_SIZE(left), AOP_SIZE(right));
540
541     cond_pre = rIfx->condition; // must restore old value on return with 0!!!
542     
543     if(!isAOP_REGlike(left)) {
544       operand *dummy;
545
546         dummy = left;
547         left = right;
548         right = dummy;
549         
550         /* invert comparing operand */
551 //        cmp_op ^= 1;
552         rIfx->condition ^= 1;
553     }
554     
555     
556     if(isAOP_REGlike(left) && isAOP_LIT(right)) {
557       /* comparing register vs. literal */
558       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
559       
560       
561       if(size == 1) {
562         op = selectCompareOp(rIfx, ifx, result, offs, cmp_op);
563         
564         DEBUGpic16_emitcode("%%", "comparing operand %s, condition: %d", (op==POC_CPFSLT?"POC_CPFSLT":"POC_CPFSGT"), rIfx->condition);
565
566         if(!sign) {
567           /* unsigned compare */
568           switch( lit ) {
569             case 0:
570               if(ifx && IC_FALSE(ifx)) {
571                 tmplbl = newiTempLabel( NULL );
572                 pic16_emitpcode(POC_TSTFSZ, pic16_popGet(AOP(left), 0));
573                 pic16_emitpcode(POC_BRA, pic16_popGetLabel(tmplbl->key));
574                 pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx->lbl->key));
575                 pic16_emitpLabel(tmplbl->key);
576
577                 ifx->generated = 1;
578                 return 1;
579               }
580               break;
581           }     /* switch */
582
583         }       /* if(!sign) */
584
585       }         /* if(size==1) */
586
587     }           /* */
588       
589   rIfx->condition = cond_pre;
590   return 0;
591 }