1 /*-------------------------------------------------------------------------
2 genutils.c - source file for code generation for pic16
3 code generation utility functions
5 Created by Vangelis Rokas (vrokas@otenet.gr) [Nov-2003]
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)
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
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.
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.
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!
34 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
35 Made everything static
36 -------------------------------------------------------------------------*/
38 /**********************************************************
39 * Here is a list with completed genXXXXX functions
50 #include "SDCCglobl.h"
54 #include "SDCCpeeph.h"
63 #define pic16_emitcode DEBUGpic16_emitcode
67 /*-----------------------------------------------------------------*/
68 /* pic16_genNot - generate code for ! operation */
69 /*-----------------------------------------------------------------*/
70 void pic16_genNot (iCode *ic)
76 * result[AOP_CRY,AOP_REG] = ! left[AOP_CRY, AOP_REG]
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));
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));
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));
99 size = AOP_SIZE(IC_LEFT(ic));
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));
109 pic16_toBoolean( IC_LEFT(ic) );
111 pic16_emitpcode(POC_TSTFSZ, pic16_popCopyReg( &pic16_pc_wreg ));
113 pic16_outBitC( IC_RESULT(ic) );
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);
121 #endif /* defined(GEN_Not) */
126 /*-----------------------------------------------------------------*/
127 /* pic16_genCpl - generate code for complement */
128 /*-----------------------------------------------------------------*/
129 void pic16_genCpl (iCode *ic)
135 * result[CRY,REG] = ~left[CRY,REG]
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));
145 /* if both are in bit space then
147 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
148 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
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);
157 size = AOP_SIZE(IC_RESULT(ic));
159 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
160 pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset));
162 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
163 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
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);
173 #endif /* defined(GEN_Cpl) */
177 /*-----------------------------------------------------------------*/
178 /* Helper function to dump operand into comment lines */
179 /*-----------------------------------------------------------------*/
181 void pic16_DumpValue(char *prefix, value *val)
183 // char s[INITIAL_INLINEASM];
186 DEBUGpic16_emitcode (";", " %s Dump value",prefix);
187 DEBUGpic16_emitcode (";", " %s name:%s",prefix,val->name);
190 void pic16_DumpPcodeOp(char *prefix, pCodeOp *pcop)
192 // char s[INITIAL_INLINEASM];
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);
200 if(pcop->type == PO_W) {
201 DEBUGpic16_emitcode (";", " %s type:PO_W",prefix);
203 if(pcop->type == PO_WREG) {
204 DEBUGpic16_emitcode (";", " %s type:PO_WREG",prefix);
206 if(pcop->type == PO_STATUS) {
207 DEBUGpic16_emitcode (";", " %s type:PO_STATUS",prefix);
209 if(pcop->type == PO_BSR) {
210 DEBUGpic16_emitcode (";", " %s type:PO_BSR",prefix);
212 if(pcop->type == PO_FSR0) {
213 DEBUGpic16_emitcode (";", " %s type:PO_FSR0",prefix);
215 if(pcop->type == PO_INDF0) {
216 DEBUGpic16_emitcode (";", " %s type:PO_INDF0",prefix);
218 if(pcop->type == PO_INTCON) {
219 DEBUGpic16_emitcode (";", " %s type:PO_INTCON",prefix);
221 if(pcop->type == PO_GPR_REGISTER) {
222 DEBUGpic16_emitcode (";", " %s type:PO_GPR_REGISTER",prefix);
224 if(pcop->type == PO_GPR_BIT) {
225 DEBUGpic16_emitcode (";", " %s type:PO_GPR_BIT",prefix);
227 if(pcop->type == PO_GPR_TEMP) {
228 DEBUGpic16_emitcode (";", " %s type:PO_GPR_TEMP",prefix);
230 if(pcop->type == PO_SFR_REGISTER) {
231 DEBUGpic16_emitcode (";", " %s type:PO_SFR_REGISTER",prefix);
233 if(pcop->type == PO_PCL) {
234 DEBUGpic16_emitcode (";", " %s type:PO_PCL",prefix);
236 if(pcop->type == PO_PCLATH) {
237 DEBUGpic16_emitcode (";", " %s type:PO_PCLATH",prefix);
239 if(pcop->type == PO_LITERAL) {
240 DEBUGpic16_emitcode (";", " %s type:PO_LITERAL",prefix);
241 DEBUGpic16_emitcode (";", " %s lit:%s",prefix,PCOL(pcop)->lit);
243 if(pcop->type == PO_REL_ADDR) {
244 DEBUGpic16_emitcode (";", " %s type:PO_REL_ADDR",prefix);
246 if(pcop->type == PO_IMMEDIATE) {
247 DEBUGpic16_emitcode (";", " %s type:PO_IMMEDIATE",prefix);
249 if(pcop->type == PO_DIR) {
250 DEBUGpic16_emitcode (";", " %s type:PO_DIR",prefix);
252 if(pcop->type == PO_CRY) {
253 DEBUGpic16_emitcode (";", " %s type:PO_CRY",prefix);
255 if(pcop->type == PO_BIT) {
256 DEBUGpic16_emitcode (";", " %s type:PO_BIT",prefix);
258 if(pcop->type == PO_STR) {
259 DEBUGpic16_emitcode (";", " %s type:PO_STR",prefix);
261 if(pcop->type == PO_LABEL) {
262 DEBUGpic16_emitcode (";", " %s type:PO_LABEL",prefix);
264 if(pcop->type == PO_WILD) {
265 DEBUGpic16_emitcode (";", " %s type:PO_WILD",prefix);
271 void pic16_DumpAop(char *prefix, asmop *aop)
273 char s[INITIAL_INLINEASM];
276 DEBUGpic16_emitcode (";", " %s Dump asmop",prefix);
277 if (aop->type == AOP_LIT)
279 DEBUGpic16_emitcode (";", " %s type:AOP_LIT",prefix);
280 sprintf(s,"%s (aopu.aop_lit)",prefix);
281 pic16_DumpValue(s,aop->aopu.aop_lit);
283 if (aop->type == AOP_REG)
284 DEBUGpic16_emitcode (";", " %s type:AOP_REG",prefix);
285 if (aop->type == AOP_DIR)
287 DEBUGpic16_emitcode (";", " %s type:AOP_DIR",prefix);
288 DEBUGpic16_emitcode (";", " %s aopu.aop_dir:%s",prefix,aop->aopu.aop_dir);
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)
304 DEBUGpic16_emitcode (";", " %s type:AOP_IMMD",prefix);
305 DEBUGpic16_emitcode (";", " %s aopu.aop_immd:%s",prefix,aop->aopu.aop_immd);
307 if (aop->type == AOP_STR)
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]);
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)
319 DEBUGpic16_emitcode (";", " %s type:AOP_PCODE",prefix);
320 sprintf(s,"%s (aopu.pcop)",prefix);
321 pic16_DumpPcodeOp(s,aop->aopu.pcop);
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);
333 void pic16_DumpSymbol(char *prefix, symbol *sym)
335 char s[INITIAL_INLINEASM];
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);
387 sprintf(s,"%s (aop)",prefix);
388 pic16_DumpAop(s,sym->aop);
390 DEBUGpic16_emitcode (";", " %s aop:NULL",prefix);
394 void pic16_DumpOp(char *prefix, operand *op)
396 char s[INITIAL_INLINEASM];
399 DEBUGpic16_emitcode (";", " %s Dump operand",prefix);
401 DEBUGpic16_emitcode (";", " %s type: SYMBOL",prefix);
403 DEBUGpic16_emitcode (";", " %s type: VALUE",prefix);
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);
415 sprintf(s,"%s (symOperand)",prefix);
416 pic16_DumpSymbol(s,op->operand.symOperand);
421 void _debugf(char *f, int l, char *frm, ...)
426 fprintf(stderr, "%s:%d ", f, l);
427 vfprintf(stderr, frm, ap);
433 void gpsimio2_pcop(pCodeOp *pcop)
435 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_gpsimio2)));
438 void gpsimio2_lit(unsigned char lit)
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)));
444 void gpsimio2_str(char *buf)
452 void gpsimDebug_StackDump(char *fname, int line, char *info)
454 pic16_emitpcomment("; gpsim debug stack dump; %s @ %d\tinfo: ", fname, line, info);
456 gpsimio2_str("&c[S:");
458 gpsimio2_str("] &h");
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)));
468 const char *gptr_fns[4][2] = {
469 { "_gptrget1", "_gptrput1" },
470 { "_gptrget2", "_gptrput2" },
471 { "_gptrget3", "_gptrput3" },
472 { "_gptrget4", "_gptrput4" } };
476 /* generate a call to the generic pointer read/write functions */
477 void pic16_callGenericPointerRW(int rw, int size)
483 werror(W_POSSBUG2, __FILE__, __LINE__);
487 strcpy(buf, port->fun_prefix);
488 strcat(buf, gptr_fns[size-1][rw]);
490 pic16_emitpcode (POC_CALL, pic16_popGetWithString (buf));
492 sym = newSymbol( buf, 0 );
494 strcpy(sym->rname, buf);
495 checkAddSym(&externs, sym);
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)
506 /* check condition, > or < ?? */
507 if(rIfx->condition != 0)invert_op ^= 1;
509 if(ifx && IC_FALSE(ifx))invert_op ^= 1;
511 if(!ifx)invert_op ^= 1;
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);
517 if(!invert_op)return POC_CPFSGT;
518 else return POC_CPFSLT;
521 /* return 1 if function handles compare, 0 otherwise */
522 /* this functions handles special cases like:
526 int pic16_genCmp_special(operand *left, operand *right, operand *result,
527 iCode *ifx, resolvedIfx *rIfx, int sign)
533 int op, cmp_op=0, cond_pre;
537 if(!(pic16_options.opt_flags & OF_OPTIMIZE_CMP))return 0;
539 size = max(AOP_SIZE(left), AOP_SIZE(right));
541 cond_pre = rIfx->condition; // must restore old value on return with 0!!!
543 if(!isAOP_REGlike(left)) {
550 /* invert comparing operand */
552 rIfx->condition ^= 1;
556 if(isAOP_REGlike(left) && isAOP_LIT(right)) {
557 /* comparing register vs. literal */
558 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
562 op = selectCompareOp(rIfx, ifx, result, offs, cmp_op);
564 DEBUGpic16_emitcode("%%", "comparing operand %s, condition: %d", (op==POC_CPFSLT?"POC_CPFSLT":"POC_CPFSGT"), rIfx->condition);
567 /* unsigned compare */
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);
589 rIfx->condition = cond_pre;