* applied patch from bug-report #1076292,
[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 "gen.h"
58
59 #include "genutils.h"
60
61 #if 1
62 #define pic16_emitcode  DEBUGpic16_emitcode
63 #endif
64
65 #if defined(GEN_Not)
66 /*-----------------------------------------------------------------*/
67 /* pic16_genNot - generate code for ! operation                    */
68 /*-----------------------------------------------------------------*/
69 void pic16_genNot (iCode *ic)
70 {
71   int size;
72 //  symbol *tlbl;
73
74 /*
75  * result[AOP_CRY,AOP_REG]  = ! left[AOP_CRY, AOP_REG]
76  */
77
78     FENTRY;
79    
80     /* assign asmOps to operand & result */
81     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
82     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
83     DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
84
85     /* if in bit space then a special case */
86     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
87       if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
88         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
89         pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
90       } else {
91         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
92         pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
93         pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
94       }
95       goto release;
96     }
97
98     size = AOP_SIZE(IC_LEFT(ic));
99 #if 0
100     if(size == 1) {
101       pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
102       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
103       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
104       goto release;
105     }
106 #endif
107
108     pic16_toBoolean( IC_LEFT(ic) );
109     emitSETC;
110     pic16_emitpcode(POC_TSTFSZ, pic16_popCopyReg( &pic16_pc_wreg ));
111     emitCLRC;
112     pic16_outBitC( IC_RESULT(ic) );
113
114 release:    
115     /* release the aops */
116     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
117     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
118 }
119
120 #endif  /* defined(GEN_Not) */
121
122
123
124 #if defined(GEN_Cpl)
125 /*-----------------------------------------------------------------*/
126 /* pic16_genCpl - generate code for complement                     */
127 /*-----------------------------------------------------------------*/
128 void pic16_genCpl (iCode *ic)
129 {
130   int offset = 0;
131   int size ;
132
133 /*
134  * result[CRY,REG] = ~left[CRY,REG]
135  */
136     FENTRY;
137
138     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
139     /* assign asmOps to operand & result */
140     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
141     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
142     DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
143
144     /* if both are in bit space then 
145      * a special case */
146     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
147       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
148
149         /* FIXME */
150         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
151         pic16_emitcode("cpl","c"); 
152         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
153         goto release; 
154     } 
155
156     size = AOP_SIZE(IC_RESULT(ic));
157     while (size--) {
158       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
159         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
160       } else {
161         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
162         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
163       }
164       offset++;
165     }
166
167 release:
168     /* release the aops */
169     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
170     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
171 }
172 #endif  /* defined(GEN_Cpl) */
173
174
175
176 /*-----------------------------------------------------------------*/
177 /* Helper function to dump operand into comment lines              */
178 /*-----------------------------------------------------------------*/
179
180 void pic16_DumpValue(char *prefix, value *val)
181 {
182 //      char s[INITIAL_INLINEASM];  
183         if(!val) return;
184
185         DEBUGpic16_emitcode (";", " %s Dump value",prefix);
186         DEBUGpic16_emitcode (";", " %s name:%s",prefix,val->name);
187 }
188
189 void pic16_DumpPcodeOp(char *prefix, pCodeOp *pcop)
190 {
191 //      char s[INITIAL_INLINEASM];  
192         if(!pcop) return;
193
194         DEBUGpic16_emitcode (";", " %s Dump pCodeOp",prefix);
195         DEBUGpic16_emitcode (";", " %s name:%s",prefix,pcop->name);
196         if(pcop->type == PO_NONE) {
197                 DEBUGpic16_emitcode (";", " %s type:PO_NONE",prefix);
198         }
199         if(pcop->type == PO_W) {
200                 DEBUGpic16_emitcode (";", " %s type:PO_W",prefix);
201         }
202         if(pcop->type == PO_WREG) {
203                 DEBUGpic16_emitcode (";", " %s type:PO_WREG",prefix);
204         }
205         if(pcop->type == PO_STATUS) {
206                 DEBUGpic16_emitcode (";", " %s type:PO_STATUS",prefix);
207         }
208         if(pcop->type == PO_BSR) {
209                 DEBUGpic16_emitcode (";", " %s type:PO_BSR",prefix);
210         }
211         if(pcop->type == PO_FSR0) {
212                 DEBUGpic16_emitcode (";", " %s type:PO_FSR0",prefix);
213         }
214         if(pcop->type == PO_INDF0) {
215                 DEBUGpic16_emitcode (";", " %s type:PO_INDF0",prefix);
216         }
217         if(pcop->type == PO_INTCON) {
218                 DEBUGpic16_emitcode (";", " %s type:PO_INTCON",prefix);
219         }
220         if(pcop->type == PO_GPR_REGISTER) {
221                 DEBUGpic16_emitcode (";", " %s type:PO_GPR_REGISTER",prefix);
222         }
223         if(pcop->type == PO_GPR_BIT) {
224                 DEBUGpic16_emitcode (";", " %s type:PO_GPR_BIT",prefix);
225         }
226         if(pcop->type == PO_GPR_TEMP) {
227                 DEBUGpic16_emitcode (";", " %s type:PO_GPR_TEMP",prefix);
228         }
229         if(pcop->type == PO_SFR_REGISTER) {
230                 DEBUGpic16_emitcode (";", " %s type:PO_SFR_REGISTER",prefix);
231         }
232         if(pcop->type == PO_PCL) {
233                 DEBUGpic16_emitcode (";", " %s type:PO_PCL",prefix);
234         }
235         if(pcop->type == PO_PCLATH) {
236                 DEBUGpic16_emitcode (";", " %s type:PO_PCLATH",prefix);
237         }
238         if(pcop->type == PO_LITERAL) {
239                 DEBUGpic16_emitcode (";", " %s type:PO_LITERAL",prefix);
240                 DEBUGpic16_emitcode (";", " %s lit:%s",prefix,PCOL(pcop)->lit);
241         }
242         if(pcop->type == PO_REL_ADDR) {
243                 DEBUGpic16_emitcode (";", " %s type:PO_REL_ADDR",prefix);
244         }
245         if(pcop->type == PO_IMMEDIATE) {
246                 DEBUGpic16_emitcode (";", " %s type:PO_IMMEDIATE",prefix);
247         }
248         if(pcop->type == PO_DIR) {
249                 DEBUGpic16_emitcode (";", " %s type:PO_DIR",prefix);
250         }
251         if(pcop->type == PO_CRY) {
252                 DEBUGpic16_emitcode (";", " %s type:PO_CRY",prefix);
253         }
254         if(pcop->type == PO_BIT) {
255                 DEBUGpic16_emitcode (";", " %s type:PO_BIT",prefix);
256         }
257         if(pcop->type == PO_STR) {
258                 DEBUGpic16_emitcode (";", " %s type:PO_STR",prefix);
259         }
260         if(pcop->type == PO_LABEL) {
261                 DEBUGpic16_emitcode (";", " %s type:PO_LABEL",prefix);
262         }
263         if(pcop->type == PO_WILD) {
264                 DEBUGpic16_emitcode (";", " %s type:PO_WILD",prefix);
265         }
266 }
267
268
269
270 void pic16_DumpAop(char *prefix, asmop *aop)
271 {
272         char s[INITIAL_INLINEASM];  
273         if(!aop) return;
274
275         DEBUGpic16_emitcode (";", " %s Dump asmop",prefix);
276         if (aop->type == AOP_LIT)
277         {
278                 DEBUGpic16_emitcode (";", " %s type:AOP_LIT",prefix);
279                 sprintf(s,"%s (aopu.aop_lit)",prefix);
280                 pic16_DumpValue(s,aop->aopu.aop_lit);
281         }
282         if (aop->type == AOP_REG)
283                 DEBUGpic16_emitcode (";", " %s type:AOP_REG",prefix);
284         if (aop->type == AOP_DIR)
285         {
286                 DEBUGpic16_emitcode (";", " %s type:AOP_DIR",prefix);
287                 DEBUGpic16_emitcode (";", " %s aopu.aop_dir:%s",prefix,aop->aopu.aop_dir);
288         }
289         if (aop->type == AOP_DPTR)
290                 DEBUGpic16_emitcode (";", " %s type:AOP_DPTR",prefix);
291         if (aop->type == AOP_DPTR2)
292                 DEBUGpic16_emitcode (";", " %s type:AOP_DPTR2",prefix);
293         if (aop->type == AOP_R0)
294                 DEBUGpic16_emitcode (";", " %s type:AOP_R0",prefix);
295         if (aop->type == AOP_R1)
296                 DEBUGpic16_emitcode (";", " %s type:AOP_R1",prefix);
297         if (aop->type == AOP_STK)
298                 DEBUGpic16_emitcode (";", " %s type:AOP_STK",prefix);
299         if (aop->type == AOP_STA)
300                 DEBUGpic16_emitcode (";", " %s type:AOP_STA",prefix);
301         if (aop->type == AOP_IMMD)
302         {
303                 DEBUGpic16_emitcode (";", " %s type:AOP_IMMD",prefix);
304                 DEBUGpic16_emitcode (";", " %s aopu.aop_immd:%s",prefix,aop->aopu.aop_immd);
305         }
306         if (aop->type == AOP_STR)
307         {
308                 DEBUGpic16_emitcode (";", " %s type:AOP_STR",prefix);
309                 DEBUGpic16_emitcode (";", " %s aopu.aop_str:%s/%s/%s/%s",prefix,aop->aopu.aop_str[0],
310                                 aop->aopu.aop_str[1],aop->aopu.aop_str[2],aop->aopu.aop_str[3]);
311         }
312         if (aop->type == AOP_CRY)
313                 DEBUGpic16_emitcode (";", " %s type:AOP_CRY",prefix);
314         if (aop->type == AOP_ACC)
315                 DEBUGpic16_emitcode (";", " %s type:AOP_ACC",prefix);
316         if (aop->type == AOP_PCODE)
317         {
318                 DEBUGpic16_emitcode (";", " %s type:AOP_PCODE",prefix);
319                 sprintf(s,"%s (aopu.pcop)",prefix);
320                 pic16_DumpPcodeOp(s,aop->aopu.pcop);
321         }
322
323
324         DEBUGpic16_emitcode (";", " %s coff:%d",prefix,aop->coff);
325         DEBUGpic16_emitcode (";", " %s size:%d",prefix,aop->size);
326         DEBUGpic16_emitcode (";", " %s code:%d",prefix,aop->code);
327         DEBUGpic16_emitcode (";", " %s paged:%d",prefix,aop->paged);
328         DEBUGpic16_emitcode (";", " %s freed:%d",prefix,aop->freed);
329
330 }
331
332 void pic16_DumpSymbol(char *prefix, symbol *sym)
333 {
334         char s[INITIAL_INLINEASM];  
335         if(!sym) return;
336
337         DEBUGpic16_emitcode (";", " %s Dump symbol",prefix);
338         DEBUGpic16_emitcode (";", " %s name:%s",prefix,sym->name);
339         DEBUGpic16_emitcode (";", " %s rname:%s",prefix,sym->rname);
340         DEBUGpic16_emitcode (";", " %s level:%d",prefix,sym->level);
341         DEBUGpic16_emitcode (";", " %s block:%d",prefix,sym->block);
342         DEBUGpic16_emitcode (";", " %s key:%d",prefix,sym->key);
343         DEBUGpic16_emitcode (";", " %s implicit:%d",prefix,sym->implicit);
344         DEBUGpic16_emitcode (";", " %s undefined:%d",prefix,sym->undefined);
345         DEBUGpic16_emitcode (";", " %s _isparm:%d",prefix,sym->_isparm);
346         DEBUGpic16_emitcode (";", " %s ismyparm:%d",prefix,sym->ismyparm);
347         DEBUGpic16_emitcode (";", " %s isitmp:%d",prefix,sym->isitmp);
348         DEBUGpic16_emitcode (";", " %s islbl:%d",prefix,sym->islbl);
349         DEBUGpic16_emitcode (";", " %s isref:%d",prefix,sym->isref);
350         DEBUGpic16_emitcode (";", " %s isind:%d",prefix,sym->isind);
351         DEBUGpic16_emitcode (";", " %s isinvariant:%d",prefix,sym->isinvariant);
352         DEBUGpic16_emitcode (";", " %s cdef:%d",prefix,sym->cdef);
353         DEBUGpic16_emitcode (";", " %s addrtaken:%d",prefix,sym->addrtaken);
354         DEBUGpic16_emitcode (";", " %s isreqv:%d",prefix,sym->isreqv);
355         DEBUGpic16_emitcode (";", " %s udChked:%d",prefix,sym->udChked);
356         DEBUGpic16_emitcode (";", " %s isLiveFcall:%d",prefix,sym->isLiveFcall);
357         DEBUGpic16_emitcode (";", " %s isspilt:%d",prefix,sym->isspilt);
358         DEBUGpic16_emitcode (";", " %s spillA:%d",prefix,sym->spillA);
359         DEBUGpic16_emitcode (";", " %s remat:%d",prefix,sym->remat);
360         DEBUGpic16_emitcode (";", " %s isptr:%d",prefix,sym->isptr);
361         DEBUGpic16_emitcode (";", " %s uptr:%d",prefix,sym->uptr);
362         DEBUGpic16_emitcode (";", " %s isFree:%d",prefix,sym->isFree);
363         DEBUGpic16_emitcode (";", " %s islocal:%d",prefix,sym->islocal);
364         DEBUGpic16_emitcode (";", " %s blockSpil:%d",prefix,sym->blockSpil);
365         DEBUGpic16_emitcode (";", " %s remainSpil:%d",prefix,sym->remainSpil);
366         DEBUGpic16_emitcode (";", " %s stackSpil:%d",prefix,sym->stackSpil);
367         DEBUGpic16_emitcode (";", " %s onStack:%d",prefix,sym->onStack);
368         DEBUGpic16_emitcode (";", " %s iaccess:%d",prefix,sym->iaccess);
369         DEBUGpic16_emitcode (";", " %s ruonly:%d",prefix,sym->ruonly);
370         DEBUGpic16_emitcode (";", " %s spildir:%d",prefix,sym->spildir);
371         DEBUGpic16_emitcode (";", " %s ptrreg:%d",prefix,sym->ptrreg);
372         DEBUGpic16_emitcode (";", " %s noSpilLoc:%d",prefix,sym->noSpilLoc);
373         DEBUGpic16_emitcode (";", " %s isstrlit:%d",prefix,sym->isstrlit);
374         DEBUGpic16_emitcode (";", " %s accuse:%d",prefix,sym->accuse);
375         DEBUGpic16_emitcode (";", " %s dptr:%d",prefix,sym->dptr);
376         DEBUGpic16_emitcode (";", " %s allocreq:%d",prefix,sym->allocreq);
377         DEBUGpic16_emitcode (";", " %s stack:%d",prefix,sym->stack);
378         DEBUGpic16_emitcode (";", " %s xstack:%d",prefix,sym->xstack);
379         DEBUGpic16_emitcode (";", " %s nRegs:%d",prefix,sym->nRegs);
380         DEBUGpic16_emitcode (";", " %s regType:%d",prefix,sym->regType);
381
382         // struct regs !!!
383
384         if(sym->aop)
385         {
386                 sprintf(s,"%s (aop)",prefix);
387                 pic16_DumpAop(s,sym->aop);
388         } else {
389                 DEBUGpic16_emitcode (";", " %s aop:NULL",prefix);
390         }
391 }
392
393 void pic16_DumpOp(char *prefix, operand *op)
394 {
395         char s[INITIAL_INLINEASM];  
396         if(!op) return;
397
398         DEBUGpic16_emitcode (";", " %s Dump operand",prefix);
399         if(IS_SYMOP(op))
400                 DEBUGpic16_emitcode (";", " %s type: SYMBOL",prefix);
401         if(IS_VALOP(op))
402                 DEBUGpic16_emitcode (";", " %s type: VALUE",prefix);
403         if(IS_TYPOP(op))
404                 DEBUGpic16_emitcode (";", " %s type: TYPE",prefix);
405         DEBUGpic16_emitcode (";", " %s isaddr:%d",prefix,op->isaddr);
406         DEBUGpic16_emitcode (";", " %s isvolatile:%d",prefix,op->isvolatile);
407         DEBUGpic16_emitcode (";" ," %s isGlobal:%d",prefix,op->isGlobal);
408         DEBUGpic16_emitcode (";", " %s isPtr:%d",prefix,op->isPtr);
409         DEBUGpic16_emitcode (";", " %s isGptr:%d",prefix,op->isGptr);
410         DEBUGpic16_emitcode (";", " %s isParm:%d",prefix,op->isParm);
411         DEBUGpic16_emitcode (";", " %s isLiteral:%d",prefix,op->isLiteral);
412         DEBUGpic16_emitcode (";", " %s key:%d",prefix,op->key);
413         if(IS_SYMOP(op)) {
414                 sprintf(s,"%s (symOperand)",prefix);
415                 pic16_DumpSymbol(s,op->operand.symOperand);
416         }
417
418 }
419
420 void _debugf(char *f, int l, char *frm, ...)
421 {
422   va_list ap;
423   
424     va_start(ap, frm);
425     fprintf(stderr, "%s:%d ", f, l);
426     vfprintf(stderr, frm, ap);
427     va_end(ap);
428 }
429
430
431
432 void gpsimio2_pcop(pCodeOp *pcop)
433 {
434   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_gpsimio2)));
435 }
436
437 void gpsimio2_lit(unsigned char lit)
438 {
439   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit));
440   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_wreg), pic16_popCopyReg(&pic16_pc_gpsimio2)));
441 }
442
443 void gpsimio2_str(char *buf)
444 {
445   while(*buf) {
446     gpsimio2_lit(*buf);
447     buf++;
448   }
449 }
450
451 void gpsimDebug_StackDump(char *fname, int line, char *info)
452 {
453   pic16_emitpcomment("; gpsim debug stack dump; %s @ %d\tinfo: ", fname, line, info);
454   
455   gpsimio2_str("&c[S:");
456   gpsimio2_str(info);
457   gpsimio2_str("] &h");
458   
459   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_fsr1h),
460                 pic16_popCopyReg(&pic16_pc_gpsimio2)));
461   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_fsr1l),
462                 pic16_popCopyReg(&pic16_pc_gpsimio2)));
463
464   gpsimio2_lit('\n');
465 }