and - Jean-Louis VERN.jlvern@writeme.com (1999)
Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
PIC port - Scott Dattalo scott@dattalo.com (2000)
- cont'd - Raphael Neider rneider@web.de (2005)
+ cont'd - Raphael Neider <rneider AT web.de> (2005)
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
#include <string.h>
#include <ctype.h>
#include "SDCCglobl.h"
-#include "newalloc.h"
+#include "newalloc.h"
#include "common.h"
#include "SDCCpeeph.h"
#include "ralloc.h"
#include "pcode.h"
#include "gen.h"
+#include "glue.h"
-/* When changing these, you must also update the assembler template
- * in device/lib/libsdcc/macros.inc */
-#define GPTRTAG_DATA 0x00
-#define GPTRTAG_CODE 0x80
+/* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
+#define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x))
+#define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x))
extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
static int labelOffset=0;
extern int debug_verbose;
+extern int pic14_hasInterrupt;
//static int optimized_for_speed = 0;
/* max_key keeps track of the largest label number used in
*/
static int max_key=0;
static int GpsuedoStkPtr=0;
+static int pic14_inISR = 0;
pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
-unsigned int pic14aopLiteral (value *val, int offset);
const char *AopType(short type);
#define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
CODE GENERATION for a specific MCU . some of the
routines may be reusable, will have to see */
-static char *zero = "#0x00";
-static char *one = "#0x01";
+static char *zero = "0x00";
+static char *one = "0x01";
static char *spname = "sp";
char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
extern int pic14_ptrRegReq ;
extern int pic14_nRegs;
-extern FILE *codeOutFile;
+extern struct dbuf_s *codeOutBuf;
static void saverbank (int, iCode *,bool);
static lineNode *lineHead = NULL;
{
va_list ap;
char lb[INITIAL_INLINEASM];
- unsigned char *lbp = lb;
+ unsigned char *lbp = (unsigned char *)lb;
if(!debug_verbose && !options.debug)
return;
{
if(pcop)
addpCode2pBlock(pb,newpCode(poc,pcop));
- else
+ else {
+ static int has_warned = 0;
+
DEBUGpic14_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
+ if (!has_warned) {
+ has_warned = 1;
+ fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
+ }
+ }
}
void emitpcodeNULLop(PIC_OPCODE poc)
{
va_list ap;
char lb[INITIAL_INLINEASM];
- unsigned char *lbp = lb;
+ char *lbp = lb;
va_start(ap,fmt);
(lineHead = newLineNode(lb)));
lineCurr->isInline = _G.inLine;
lineCurr->isDebug = _G.debugLine;
+ lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
if(debug_verbose)
addpCode2pBlock(pb,newpCodeCharP(lb));
if (sym->aop)
return sym->aop;
-#if 0
- /* assign depending on the storage class */
- /* if it is on the stack or indirectly addressable */
- /* space we need to assign either r0 or r1 to it */
- if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
- sym->aop = aop = newAsmop(0);
- aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
- aop->size = getSize(sym->type);
-
- /* now assign the address of the variable to
- the pointer register */
- if (aop->type != AOP_STK) {
-
- if (sym->onStack) {
- if ( _G.accInUse )
- pic14_emitcode("push","acc");
-
- pic14_emitcode("mov","a,_bp");
- pic14_emitcode("add","a,#0x%02x",
- ((sym->stack < 0) ?
- ((char)(sym->stack - _G.nRegsSaved )) :
- ((char)sym->stack)) & 0xff);
- pic14_emitcode("mov","%s,a",
- aop->aopu.aop_ptr->name);
-
- if ( _G.accInUse )
- pic14_emitcode("pop","acc");
- } else
- pic14_emitcode("mov","%s,#%s",
- aop->aopu.aop_ptr->name,
- sym->rname);
- aop->paged = space->paged;
- } else
- aop->aopu.aop_stk = sym->stack;
- return aop;
- }
-
- if (sym->onStack && options.stack10bit)
- {
- /* It's on the 10 bit stack, which is located in
- * far data space.
- */
-
- //DEBUGpic14_emitcode(";","%d",__LINE__);
-
- if ( _G.accInUse )
- pic14_emitcode("push","acc");
-
- pic14_emitcode("mov","a,_bp");
- pic14_emitcode("add","a,#0x%02x",
- ((sym->stack < 0) ?
- ((char)(sym->stack - _G.nRegsSaved )) :
- ((char)sym->stack)) & 0xff);
-
- genSetDPTR(1);
- pic14_emitcode ("mov","dpx1,#0x40");
- pic14_emitcode ("mov","dph1,#0x00");
- pic14_emitcode ("mov","dpl1, a");
- genSetDPTR(0);
-
- if ( _G.accInUse )
- pic14_emitcode("pop","acc");
-
- sym->aop = aop = newAsmop(AOP_DPTR2);
- aop->size = getSize(sym->type);
- return aop;
- }
-#endif
-
//DEBUGpic14_emitcode(";","%d",__LINE__);
- /* if in bit space */
- if (IN_BITSPACE(space)) {
- sym->aop = aop = newAsmop (AOP_CRY);
- aop->aopu.aop_dir = sym->rname ;
- aop->size = getSize(sym->type);
- //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
- return aop;
- }
/* if it is in direct space */
if (IN_DIRSPACE(space)) {
sym->aop = aop = newAsmop (AOP_DIR);
/* else spill location */
if (sym->usl.spillLoc)
{
+ asmop *oldAsmOp = NULL;
+
if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
{
/* force a new aop if sizes differ */
+ oldAsmOp = sym->usl.spillLoc->aop;
sym->usl.spillLoc->aop = NULL;
}
DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
sym->rname, sym->usl.spillLoc->offset);
sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
+ if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
+ {
+ /* Don't reuse the new aop, go with the last one */
+ sym->usl.spillLoc->aop = oldAsmOp;
+ }
//aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname,
getSize(sym->type),
//DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
/* offset is greater than
size then zero */
+ assert(aop);
if (offset > (aop->size - 1) &&
aop->type != AOP_LIT)
return zero;
return "AOP_accumulator_bug";
case AOP_LIT:
- sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
- rs = Safe_calloc(1,strlen(s)+1);
- strcpy(rs,s);
+ sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
+ rs = Safe_strdup(s);
return rs;
case AOP_STR:
pCodeOp *pcop = aop->aopu.pcop;
DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
if(pcop->name) {
+ if (pcop->type == PO_IMMEDIATE) {
+ offset += PCOI(pcop)->index;
+ }
if (offset) {
DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
sprintf(s,"(%s+%d)", pcop->name,offset);
return pcop;
}
-pCodeOp *popGetExternal (char *str)
+pCodeOp *popGetExternal (char *str, int isReg)
{
- pCodeOp *pcop = popGetWithString (str, 1);
+ pCodeOp *pcop;
+
+ if (isReg) {
+ pcop = newpCodeOpRegFromStr(str);
+ } else {
+ pcop = popGetWithString (str, 1);
+ }
if (str) {
symbol *sym;
- bool found = 0;
- for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
+ for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
{
- if (!strcmp (str, sym->rname))
- found = 1;
+ if (!strcmp (str, sym->rname)) break;
}
- if (!found)
+ if (!sym)
{
sym = newSymbol(str, 0);
strncpy(sym->rname, str, SDCC_NAME_MAX);
addSet (&externs, sym);
} // if
+ sym->used++;
}
return pcop;
}
assert (aop);
+
/* XXX: still needed for BIT operands (AOP_CRY) */
if (offset > (aop->size - 1) &&
- aop->type != AOP_LIT)
+ aop->type != AOP_LIT &&
+ aop->type != AOP_PCODE)
+ {
+ printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
return NULL; //zero;
+ }
/* depending on type */
switch (aop->type) {
static void call_libraryfunc (char *name)
{
- /* library code might reside in different page... */
- emitpcode (POC_PAGESEL, popGetWithString (name, 1));
- /* call the library function */
- emitpcode (POC_CALL, popGetExternal (name));
- /* might return from different page... */
- emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
+ symbol *sym;
+
+ /* library code might reside in different page... */
+ emitpcode (POC_PAGESEL, popGetWithString (name, 1));
+ /* call the library function */
+ emitpcode (POC_CALL, popGetExternal (name, 0));
+ /* might return from different page... */
+ emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
+
+ /* create symbol, mark it as `extern' */
+ sym = findSym(SymbolTab, NULL, name);
+ if (!sym) {
+ sym = newSymbol(name, 0);
+ strncpy(sym->rname, name, SDCC_NAME_MAX);
+ addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
+ addSet(&externs, sym);
+ } // if
+ sym->used++;
}
+
#if 0
/*-----------------------------------------------------------------*/
/* reAdjustPreg - points a register back to where it should */
{
sym_link *dtype;
symbol *sym;
- unsigned char *name;
+ char *name;
int isExtern;
FENTRY;
/* make the call */
sym = OP_SYMBOL(IC_LEFT(ic));
name = sym->rname[0] ? sym->rname : sym->name;
- isExtern = IS_EXTERN(sym->etype);
+ /*
+ * As SDCC emits code as soon as it reaches the end of each
+ * function's definition, prototyped functions that are implemented
+ * after the current one are always considered EXTERN, which
+ * introduces many unneccessary PAGESEL instructions.
+ * XXX: Use a post pass to iterate over all `CALL _name' statements
+ * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
+ * only iff there is no definition of the function in the whole
+ * file (might include this in the PAGESEL pass).
+ */
+ isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
if (isExtern) {
- emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
+ /* Extern functions and ISRs maybe on a different page;
+ * must call pagesel */
+ emitpcode(POC_PAGESEL,popGetWithString(name,1));
}
emitpcode(POC_CALL,popGetWithString(name,isExtern));
if (isExtern) {
- emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
+ /* May have returned from a different page;
+ * must use pagesel to restore PCLATH before next
+ * goto or call instruction */
+ emitpcode(POC_PAGESEL,popGetWithString("$",0));
}
GpsuedoStkPtr=0;
/* if we need assign a result value */
*/
emitpcode(POC_CALL,popGetLabel(albl->key));
pcop = popGetLabel(blbl->key);
- emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
+ emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
emitpcode(POC_GOTO,pcop);
emitpLabel(albl->key);
return 0;
}
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
-
#if 0
/*-----------------------------------------------------------------*/
/* inExcludeList - return 1 if the string is in exclude Reg list */
pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
pic14_emitcode(";","-----------------------------------------");
+ /* prevent this symbol from being emitted as 'extern' */
+ pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
+
pic14_emitcode("","%s:",sym->rname);
addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
+
+ /* mark symbol as NOT extern (even if it was declared so previously) */
+ assert(IS_SPEC(sym->etype));
+ SPEC_EXTR(sym->etype) = 0;
+ sym->cdef = 0;
+ if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
+ addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
ftype = operandType(IC_LEFT(ic));
#endif
/* if this is an interrupt service routine */
+ pic14_inISR = 0;
if (IFFUNC_ISISR(sym->type)) {
- /* already done in pic14createInterruptVect() - delete me
- addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
- emitpcodeNULLop(POC_NOP);
- emitpcodeNULLop(POC_NOP);
- emitpcodeNULLop(POC_NOP);
- */
+ pic14_inISR = 1;
emitpcode(POC_MOVWF, popCopyReg(&pc_wsave));
emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
+ /* XXX: Why? Does this assume that ssave and psave reside
+ * in a shared bank or bank0? We cannot guarantee the
+ * latter...
+ */
emitpcode(POC_CLRF, popCopyReg(&pc_status));
emitpcode(POC_MOVWF, popCopyReg(&pc_ssave));
+ //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_status",1 ));
emitpcode(POC_MOVFW, popCopyReg(&pc_pclath));
+ /* during an interrupt PCLATH must be cleared before a goto or call statement */
+ emitpcode(POC_CLRF, popCopyReg(&pc_pclath));
emitpcode(POC_MOVWF, popCopyReg(&pc_psave));
- emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
+ //emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_pclath", 1));
+ emitpcode(POC_MOVFW, popCopyReg(&pc_fsr));
+ emitpcode(POC_MOVWF, popGetExternal("___sdcc_saved_fsr", 1));
pBlockConvert2ISR(pb);
-#if 0
- if (!inExcludeList("acc"))
- pic14_emitcode ("push","acc");
- if (!inExcludeList("b"))
- pic14_emitcode ("push","b");
- if (!inExcludeList("dpl"))
- pic14_emitcode ("push","dpl");
- if (!inExcludeList("dph"))
- pic14_emitcode ("push","dph");
- if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
- {
- pic14_emitcode ("push", "dpx");
- /* Make sure we're using standard DPTR */
- pic14_emitcode ("push", "dps");
- pic14_emitcode ("mov", "dps, #0x00");
- if (options.stack10bit)
- {
- /* This ISR could conceivably use DPTR2. Better save it. */
- pic14_emitcode ("push", "dpl1");
- pic14_emitcode ("push", "dph1");
- pic14_emitcode ("push", "dpx1");
- }
- }
- /* if this isr has no bank i.e. is going to
- run with bank 0 , then we need to save more
- registers :-) */
- if (!FUNC_REGBANK(sym->type)) {
-
- /* if this function does not call any other
- function then we can be economical and
- save only those registers that are used */
- if (! IFFUNC_HASFCALL(sym->type)) {
- int i;
-
- /* if any registers used */
- if (sym->regsUsed) {
- /* save the registers used */
- for ( i = 0 ; i < sym->regsUsed->size ; i++) {
- if (bitVectBitValue(sym->regsUsed,i) ||
- (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
- pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);
- }
- }
-
- } else {
- /* this function has a function call cannot
- determines register usage so we will have the
- entire bank */
- saverbank(0,ic,FALSE);
- }
- }
-#endif
+ pic14_hasInterrupt = 1;
} else {
/* if callee-save to be used for this function
then save the registers being used in this function */
unsaverbank(0,ic,FALSE);
}
}
-#if 0
- if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
- {
- if (options.stack10bit)
- {
- pic14_emitcode ("pop", "dpx1");
- pic14_emitcode ("pop", "dph1");
- pic14_emitcode ("pop", "dpl1");
- }
- pic14_emitcode ("pop", "dps");
- pic14_emitcode ("pop", "dpx");
- }
- if (!inExcludeList("dph"))
- pic14_emitcode ("pop","dph");
- if (!inExcludeList("dpl"))
- pic14_emitcode ("pop","dpl");
- if (!inExcludeList("b"))
- pic14_emitcode ("pop","b");
- if (!inExcludeList("acc"))
- pic14_emitcode ("pop","acc");
-
- if (IFFUNC_ISCRITICAL(sym->type))
- pic14_emitcode("setb","ea");
-#endif
/* if debug then send end of function */
- /* if (options.debug && currFunc) { */
- if (currFunc) {
+ if (options.debug && debugFile && currFunc) {
debugFile->writeEndFunction (currFunc, ic, 1);
}
- pic14_emitcode ("reti","");
+ emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_fsr", 1));
+ emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
+ //emitpcode(POC_MOVFW, popGetExternal("___sdcc_saved_pclath", 1));
emitpcode(POC_MOVFW, popCopyReg(&pc_psave));
emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
- emitpcode(POC_CLRF, popCopyReg(&pc_status));
+ emitpcode(POC_CLRF, popCopyReg(&pc_status)); // see genFunction
+ //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
emitpcode(POC_MOVWF, popCopyReg(&pc_status));
emitpcode(POC_SWAPF, popCopyReg(&pc_wsave));
}
/* if debug then send end of function */
- if (currFunc) {
+ if (options.debug && debugFile && currFunc) {
debugFile->writeEndFunction (currFunc, ic, 1);
}
operand *result)
{
int size;
+ int sign;
FENTRY;
DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
- assert (AOP_SIZE(result) == 1);
assert (AOP_SIZE(right) == 1);
assert (AOP_SIZE(left) == 1);
size = min(AOP_SIZE(result),AOP_SIZE(left));
+ sign = !(SPEC_USIGN(operandType(left))
+ && SPEC_USIGN(operandType(right)));
if (AOP_TYPE(right) == AOP_LIT)
{
/* XXX: might add specialized code */
}
- if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
+ if (!sign)
{
/* unsigned division */
#if 1
emitSKPNC;
emitpcode(POC_GOTO, popGetLabel(lbl->key));
emitpcode(POC_DECF, popGet(AOP(result),0));
+ popReleaseTempReg(temp);
#endif
}
else
}
/* now performed the signed/unsigned division -- extend result */
- addSign(result, 1, !SPEC_USIGN(operandType(result)));
+ addSign(result, 1, sign);
}
/*-----------------------------------------------------------------*/
freeAsmop(result,NULL,ic,TRUE);
}
-/*-----------------------------------------------------------------*/
-/* genModbits :- modulus of bits */
-/*-----------------------------------------------------------------*/
-static void genModbits (operand *left,
- operand *right,
- operand *result)
-{
-
- char *l;
-
- FENTRY;
- /* the result must be bit */
- pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
- l = aopGet(AOP(left),0,FALSE,FALSE);
-
- MOVA(l);
-
- pic14_emitcode("div","ab");
- pic14_emitcode("mov","a,b");
- pic14_emitcode("rrc","a");
- aopPut(AOP(result),"c",0);
-}
-
/*-----------------------------------------------------------------*/
/* genModOneByte : 8 bit modulus */
/*-----------------------------------------------------------------*/
operand *result)
{
int size;
+ int sign;
FENTRY;
DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
- assert (AOP_SIZE(result) == 1);
assert (AOP_SIZE(right) == 1);
assert (AOP_SIZE(left) == 1);
size = min(AOP_SIZE(result),AOP_SIZE(left));
+ sign = !(SPEC_USIGN(operandType(left))
+ && SPEC_USIGN(operandType(right)));
if (AOP_TYPE(right) == AOP_LIT)
{
/* XXX: might add specialized code */
}
- if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
+ if (!sign)
{
/* unsigned division */
#if 1
}
/* now we performed the signed/unsigned modulus -- extend result */
- addSign(result, 1, !SPEC_USIGN(operandType(result)));
+ addSign(result, 1, sign);
}
/*-----------------------------------------------------------------*/
aopOp (right,ic,FALSE);
aopOp (result,ic,TRUE);
- /* special cases first */
- /* both are bits */
- if (AOP_TYPE(left) == AOP_CRY &&
- AOP_TYPE(right)== AOP_CRY) {
- genModbits(left,right,result);
- goto release ;
- }
-
/* if both are of size == 1 */
if (AOP_SIZE(left) == 1 &&
AOP_SIZE(right) == 1 ) {
FENTRY;
DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
if(IC_TRUE(ic))
- pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
+ {
+ // Why +100?!?
+ emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
+ pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
+ }
ic->generated = 1;
}
FENTRY;
DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
if(!IC_TRUE(ic))
+ {
+ // Why +100?!?
+ emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
+ }
ic->generated = 1;
}
pic14_emitcode("setb","c");
while(sizel--){
if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
- MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
+ mov2w( AOP(left), offset);
// byte == 2^n ?
- if((posbit = isLiteralBit(bytelit)) != 0)
+ if((posbit = isLiteralBit(bytelit)) != 0) {
+ emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
+ newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
+ }
else{
+ emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
+ if (rIfx.condition) emitSKPZ;
+ else emitSKPNZ;
+
if(bytelit != 0x0FFL)
+ {
pic14_emitcode("anl","a,%s",
aopGet(AOP(right),offset,FALSE,TRUE));
+ }
pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
}
+
+ emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
+ ifx->generated = 1;
+
}
offset++;
}
static void genInline (iCode *ic)
{
char *buffer, *bp, *bp1;
+ bool inComment = FALSE;
FENTRY;
DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
_G.inLine += (!options.asmpeep);
- buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
- strcpy(buffer,IC_INLINE(ic));
+ buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
- /* emit each line as a code */
- while (*bp) {
- if (*bp == '\n') {
- *bp++ = '\0';
-
- if(*bp1)
- addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
- bp1 = bp;
- } else {
- if (*bp == ':') {
- bp++;
- *bp = '\0';
- bp++;
-
- /* print label, use this special format with NULL directive
- * to denote that the argument should not be indented with tab */
- addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
-
- bp1 = bp;
- } else
- bp++;
+ while (*bp)
+ {
+ switch (*bp)
+ {
+ case ';':
+ inComment = TRUE;
+ ++bp;
+ break;
+
+ case '\n':
+ inComment = FALSE;
+ *bp++ = '\0';
+ if (*bp1)
+ addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
+ bp1 = bp;
+ break;
+
+ default:
+ /* Add \n for labels, not dirs such as c:\mydir */
+ if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
+ {
+ ++bp;
+ *bp = '\0';
+ ++bp;
+ /* print label, use this special format with NULL directive
+ * to denote that the argument should not be indented with tab */
+ addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
+ bp1 = bp;
+ }
+ else
+ ++bp;
+ break;
+ }
}
- }
if ((bp1 != bp) && *bp1)
addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
- Safe_free(buffer);
+ Safe_free (buffer);
_G.inLine -= (!options.asmpeep);
}
switch (p_type)
{
case POINTER:
+ case FPOINTER:
if (!alreadyAddressed) setup_fsr (src);
emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
break;
switch (p_type)
{
case POINTER:
+ case FPOINTER:
if (!alreadyAddressed) setup_fsr (dst);
emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
break;
break;
case POINTER:
+ case FPOINTER:
case GPOINTER:
case CPOINTER:
emitPtrByteGet (left, ptype, FALSE);
break;
case POINTER:
+ case FPOINTER:
case GPOINTER:
case CPOINTER:
emitPtrByteGet (left, ptype, FALSE);
lower 128 bytes of space */
if (AOP_TYPE(left) == AOP_PCODE && //AOP_TYPE(left) == AOP_IMMD &&
!IS_BITVAR(retype) &&
- DCL_TYPE(ltype) == POINTER) {
+ PIC_IS_DATA_PTR(ltype)) {
genDataPointerGet (left,result,ic);
return ;
}
switch (p_type) {
case POINTER:
+ case FPOINTER:
//case IPOINTER:
genNearPointerGet (left,result,ic);
break;
break;
case POINTER:
+ case FPOINTER:
setup_fsr (result);
emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
break;
break;
case POINTER:
+ case FPOINTER:
case GPOINTER:
emitPtrByteGet(result, p_type, FALSE);
if ((litval|mask) != 0x00ff)
break;
case POINTER:
+ case FPOINTER:
case GPOINTER:
emitPtrByteGet (result, p_type, FALSE);
emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
break;
case POINTER:
+ case FPOINTER:
case GPOINTER:
emitPtrByteGet (result, p_type, FALSE);
emitpcode(POC_ANDLW, popGetLit (mask));
assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
}
-unsigned long
-bitpatternFromVal (value *val)
-{
- union {
- float d;
- unsigned long l;
- } float_long;
-
- assert (sizeof (float) == sizeof (long));
-
- //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
-
- switch (SPEC_NOUN(val->type))
- {
- case V_INT:
- case V_CHAR:
- return (unsigned long)floatFromVal (val);
-
- case V_FLOAT:
- case V_DOUBLE:
- float_long.d = floatFromVal (val);
- return float_long.l;
-
- default:
- assert( !"unhandled value type" );
- break;
- }
-
- float_long.d = floatFromVal (val);
- return float_long.l;
-}
-
/*-----------------------------------------------------------------*/
/* genDataPointerSet - remat pointer to data space */
/*-----------------------------------------------------------------*/
assert (IS_SYMOP(result));
assert (IS_PTR(OP_SYM_TYPE(result)));
- size = AOP_SIZE(right);
+ if (AOP_TYPE(right) == AOP_LIT)
+ size = 4;
+ else
+ size = AOP_SIZE(right);
ressize = getSize(OP_SYM_ETYPE(result));
if (size > ressize) size = ressize;
//fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
// tsd, was l+1 - the underline `_' prefix was being stripped
while (size--) {
- emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
+ emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
if (AOP_TYPE(right) == AOP_LIT) {
- /* XXX: might be float... */
- unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
- lit = lit >> (8*offset);
+ unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
//fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
if(lit&0xff) {
emitpcode(POC_MOVLW, popGetLit(lit&0xff));
- emitpcode(POC_MOVWF, popGet(AOP(result),offset));
+ emitpcode(POC_MOVWF, popGet(AOP(result), offset));
} else {
- emitpcode(POC_CLRF, popGet(AOP(result),offset));
+ emitpcode(POC_CLRF, popGet(AOP(result), offset));
}
} else {
//fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
- emitpcode(POC_MOVFW, popGet(AOP(right),offset));
- emitpcode(POC_MOVWF, popGet(AOP(result),offset));
+ emitpcode(POC_MOVFW, popGet(AOP(right), offset));
+ emitpcode(POC_MOVWF, popGet(AOP(result), offset));
}
offset++;
in data space & not a bit variable */
//if (AOP_TYPE(result) == AOP_IMMD &&
if (AOP_TYPE(result) == AOP_PCODE &&
- DCL_TYPE(ptype) == POINTER &&
+ PIC_IS_DATA_PTR(ptype) &&
!IS_BITVAR (retype) &&
!IS_BITVAR (letype)) {
genDataPointerSet (right,result,ic);
int size = AOP_SIZE(right);
int idx = 0;
- assert (size == getSize(OP_SYM_ETYPE(result)));
+ /* The following assertion fails for
+ * struct foo { char a; char b; } bar;
+ * void demo(struct foo *dst, char c) { dst->b = c; }
+ * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
+ * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
+ * of size 2.
+ * The frontend seems to guarantee that IC_LEFT has the correct size,
+ * it works fine both for larger and smaller types of `char c'.
+ * */
+ //assert (size == getSize(OP_SYM_ETYPE(result)));
assert (size > 0 && size <= 4);
/* pass arguments */
switch (p_type) {
case POINTER:
+ case FPOINTER:
//case IPOINTER:
genNearPointerSet (right,result,ic);
break;
pic14_toBoolean(cond);
else
isbit = 1;
- /* the result is now in the accumulator */
- freeAsmop(cond,NULL,ic,TRUE);
/* if there was something to be popped then do it */
if (popIc)
if (isbit)
{
- assert (!"genIfx not implemented for bit variables...");
+ /* This assumes that CARRY is set iff cond is true */
+ if (IC_TRUE(ic))
+ {
+ assert (!IC_FALSE(ic));
+ emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
+ //emitSKPNC;
+ emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
+ } else {
+ assert (IC_FALSE(ic));
+ emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
+ //emitSKPC;
+ emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
+ }
+ if (0)
+ {
+ static int hasWarned = 0;
+ if (!hasWarned)
+ {
+ fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
+ hasWarned = 1;
+ }
+ }
}
else
{
- /* now Z if set iff !cond */
+ /* now Z is set iff !cond */
if (IC_TRUE(ic))
{
assert (!IC_FALSE(ic));
ic->generated = 1;
+ /* the result is now in the accumulator */
+ freeAsmop(cond,NULL,ic,TRUE);
}
/*-----------------------------------------------------------------*/
/* general case */
size = AOP_SIZE(result);
offset = 0 ;
- if(AOP_TYPE(right) == AOP_LIT)
- lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
-
if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) {
DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
if(aopIdx(AOP(result),0) == 4) {
know_W=-1;
while (size--) {
+
DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
if(AOP_TYPE(right) == AOP_LIT) {
+ lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
if(lit&0xff) {
if(know_W != (int)(lit&0xff))
emitpcode(POC_MOVLW,popGetLit(lit&0xff));
} else
emitpcode(POC_CLRF, popGet(AOP(result),offset));
- lit >>= 8;
-
} else if (AOP_TYPE(right) == AOP_CRY) {
emitpcode(POC_CLRF, popGet(AOP(result),offset));
if(offset == 0) {
_G.accInUse++;
aopOp(IC_RESULT(ic),ic,FALSE);
_G.accInUse--;
+ GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
assignResultValue(IC_RESULT(ic));
}
addpBlock(pb);
/* if debug information required */
- if (options.debug && currFunc) {
- if (currFunc) {
- debugFile->writeFunction (currFunc, lic);
- }
+ if (options.debug && debugFile && currFunc) {
+ debugFile->writeFunction (currFunc, lic);
}
}
if (options.iCodeInAsm) {
+ char *iLine = printILine(ic);
emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
+ dbuf_free(iLine);
}
/* if the result is marked as
spilt and rematerializable or code for
peepHole (&lineHead);
}
/* now do the actual printing */
- printLine (lineHead,codeOutFile);
+ printLine (lineHead,codeOutBuf);
#ifdef PCODE_DEBUG
DFPRINTF((stderr,"printing pBlock\n\n"));
if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
return 0;
}
+