#include "common.h"
+#define ENABLE_MICHAELH_REGPARM_HACK 0
+
bucket *SymbolTab [256] ; /* the symbol table */
bucket *StructTab [256] ; /* the structure table */
bucket *TypedefTab[256] ; /* the typedef table */
/* if any of the arguments is an aggregate */
/* change it to pointer to the same type */
while (val) {
-
/* mark it as a register parameter if
the function does not have VA_ARG
and as port dictates
SPEC_REGPARM(val->etype) = 1;
}
+
+#if ENABLE_MICHAELH_REGPARM_HACK
+ /* HACK: pull out later */
+ if (
+ (
+ !strcmp(func->name, "memcpy") ||
+ !strcmp(func->name, "strcpy") ||
+ !strcmp(func->name, "strcmp") ||
+ 0
+ ) &&
+ port->reg_parm(val->type)) {
+ SPEC_REGPARM(val->etype) = 1;
+ }
+#endif
if ( IS_AGGREGATE(val->type)) {
/* if this is a structure */
link *floatType;
+static void _makeRegParam(symbol *sym)
+{
+ value *val ;
+
+ val = sym->args; /* loop thru all the arguments */
+
+ /* reset regparm for the port */
+ (*port->reset_regparms)();
+ while (val) {
+ SPEC_REGPARM(val->etype) = 1;
+ sym->argStack -= getSize(val->type);
+ val = val->next ;
+ }
+}
+
/*-----------------------------------------------------------------*/
/* initCSupport - create functions for C support routines */
/*-----------------------------------------------------------------*/
ssu[su],
sbwd[bwd]);
__muldiv[muldivmod][bwd][su] = funcOfType(buffer, __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
+#if ENABLE_MICHAELH_REGPARM_HACK
+ if (bwd < 2)
+ _makeRegParam(__muldiv[muldivmod][bwd][su]);
+#endif
}
}
}
5/3/00 17741 185 17B6
Michael Hope <michaelh@earthling.net> 2000
- Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
- and - Jean-Louis VERN.jlvern@writeme.com (1999)
+ Based on the mcs51 generator -
+ Sandeep Dutta . sandeep.dutta@usa.net (1998)
+ and - Jean-Louis VERN.jlvern@writeme.com (1999)
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
static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool requires_a)
{
asmop *aop;
- memmap *space= SPEC_OCLS(sym->etype);
+ memmap *space;
+
+ wassert(ic);
+ wassert(sym);
+ wassert(sym->etype);
+
+ space = SPEC_OCLS(sym->etype);
/* if already has one */
if (sym->aop)
/* if this is a true symbol */
if (IS_TRUE_SYMOP(op)) {
- op->aop = aopForSym(ic,OP_SYMBOL(op),result, requires_a);
+ op->aop = aopForSym(ic, OP_SYMBOL(op), result, requires_a);
return ;
}
freeAsmop(IC_RESULT(ic),NULL,ic);
}
+static void _push(PAIR_ID pairId)
+{
+ emit2("push %s", _pairs[pairId].name);
+ _G.stack.pushed += 2;
+}
+
+static void _pop(PAIR_ID pairId)
+{
+ emit2("pop %s", _pairs[pairId].name);
+ _G.stack.pushed -= 2;
+}
+
+
/*-----------------------------------------------------------------*/
/* assignResultValue - */
/*-----------------------------------------------------------------*/
#endif
if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
/* We do it the hard way here. */
- emitcode("push", "hl");
- _G.stack.pushed += 2;
+ _push(PAIR_HL);
aopPut(AOP(oper), _fReturn[0], 0);
aopPut(AOP(oper), _fReturn[1], 1);
emitcode("pop", "de");
int size, offset = 0 ;
char *l;
-
/* if this is not a parm push : ie. it is spill push
and spill push is always done on the local stack */
if (!ic->parmPush) {
freeAsmop(IC_LEFT(ic),NULL,ic);
}
+static int _isPairUsed(iCode *ic, PAIR_ID pairId)
+{
+ int ret = 0;
+ switch (pairId) {
+ case PAIR_DE:
+ if (bitVectBitValue(ic->rUsed, D_IDX))
+ ret++;
+ if (bitVectBitValue(ic->rUsed, E_IDX))
+ ret++;
+ break;
+ default:
+ wassert(0);
+ }
+ return ret;
+}
+
+static int _opUsesPair(operand *op, iCode *ic, PAIR_ID pairId)
+{
+ int ret = 0;
+ asmop *aop;
+ symbol *sym = OP_SYMBOL(op);
+
+ if (sym->isspilt || sym->nRegs == 0)
+ return 0;
+
+ aopOp(op, ic, FALSE, FALSE);
+
+ aop = AOP(op);
+ if (aop->type == AOP_REG) {
+ int i;
+ for (i=0; i < aop->size; i++) {
+ if (pairId == PAIR_DE) {
+ emit2("; name %s", aop->aopu.aop_reg[i]->name);
+ if (!strcmp(aop->aopu.aop_reg[i]->name, "e"))
+ ret++;
+ if (!strcmp(aop->aopu.aop_reg[i]->name, "d"))
+ ret++;
+ }
+ else {
+ wassert(0);
+ }
+ }
+ }
+
+ freeAsmop(IC_LEFT(ic),NULL,ic);
+ return ret;
+}
+
/** Emit the code for a call statement
*/
-static void emitCall (iCode *ic, bool ispcall)
+static void emitCall(iCode *ic, bool ispcall)
{
+ int pushed_de = 0;
+
/* if caller saves & we have not saved then */
if (!ic->regsSaved) {
/* PENDING */
}
-
+
/* if send set is not empty then assign */
if (sendSet) {
- iCode *sic ;
- for (sic = setFirstItem(sendSet) ; sic ;
- sic = setNextItem(sendSet)) {
- int size, offset = 0;
- aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
- size = AOP_SIZE(IC_LEFT(sic));
- while (size--) {
- char *l = aopGet(AOP(IC_LEFT(sic)),offset,
- FALSE);
- if (strcmp(l, _fReturn[offset]))
- emitcode("ld","%s,%s",
- _fReturn[offset],
- l);
- offset++;
+ iCode *sic;
+ int send = 0;
+ int n = elementsInSet(sendSet);
+ if (IS_Z80 && n == 2 && _isPairUsed(ic, PAIR_DE)) {
+ /* Only push de if it is used and if it's not used
+ in the return value */
+ /* Panic if partly used */
+ if (_opUsesPair(IC_RESULT(ic), ic, PAIR_DE) == 1) {
+ emit2("; Warning: de crossover");
+ }
+ else if (!_opUsesPair(IC_RESULT(ic), ic, PAIR_DE)) {
+ /* Store away de */
+ _push(PAIR_DE);
+ pushed_de = 1;
}
+ }
+ /* PENDING: HACK */
+ if (IS_Z80 && n == 2 ) {
+ /* Want to load HL first, then DE as HL may = DE */
+ sic = setFirstItem(sendSet);
+ sic = setNextItem(sendSet);
+ aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+ fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+ send++;
+ freeAsmop (IC_LEFT(sic),NULL,sic);
+ sic = setFirstItem(sendSet);
+ aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+ fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
+ send++;
freeAsmop (IC_LEFT(sic),NULL,sic);
}
+ else {
+ for (sic = setFirstItem(sendSet) ; sic ;
+ sic = setNextItem(sendSet)) {
+ int size;
+ aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+ size = AOP_SIZE(IC_LEFT(sic));
+ wassert(size <= 2);
+ /* Always send in pairs */
+ switch (send) {
+ case 0:
+ if (IS_Z80 && n == 1)
+ fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+ else
+ fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
+ break;
+ case 1:
+ fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+ break;
+ default:
+ /* Send set too big */
+ wassert(0);
+ }
+ send++;
+ freeAsmop (IC_LEFT(sic),NULL,sic);
+ }
+ }
sendSet = NULL;
+ if (pushed_de) {
+ }
}
if (ispcall) {
spillCached();
}
}
-
+ if (pushed_de)
+ _pop(PAIR_DE);
}
/*-----------------------------------------------------------------*/
symbol *tlbl , *tlbl1;
char *l;
+ tlbl = newiTempLabel(NULL);
+ tlbl1 = newiTempLabel(NULL);
+
/* Left is already in result - so now do the shift */
if (shCount>1) {
emit2("ld a,!immedbyte+1", shCount);
- tlbl = newiTempLabel(NULL);
- tlbl1 = newiTempLabel(NULL);
emit2("!shortjp !tlabel", tlbl1->key+100);
emitLabel(tlbl->key+100);
}
symbol *tlbl , *tlbl1;
char *l;
+ tlbl = newiTempLabel(NULL);
+ tlbl1 = newiTempLabel(NULL);
+
/* Left is already in result - so now do the shift */
if (shCount>1) {
emit2("ld a,!immedbyte+1", shCount);
- tlbl = newiTempLabel(NULL);
- tlbl1 = newiTempLabel(NULL);
emit2("!shortjp !tlabel", tlbl1->key+100);
emitLabel(tlbl->key+100);
}
/*-----------------------------------------------------------------*/
static void AccLsh (int shCount)
{
- if(shCount != 0){
- if(shCount == 1)
- emitcode("add","a,a");
- else
- if(shCount == 2) {
- emitcode("add","a,a");
+ if(shCount != 0) {
+ if(shCount == 1) {
emitcode("add","a,a");
- } else {
- /* rotate left accumulator */
- AccRol(shCount);
- /* and kill the lower order bits */
- emit2("and a,!immedbyte", SLMask[shCount]);
- }
+ }
+ else if(shCount == 2) {
+ emitcode("add","a,a");
+ emitcode("add","a,a");
+ } else {
+ /* rotate left accumulator */
+ AccRol(shCount);
+ /* and kill the lower order bits */
+ emit2("and a,!immedbyte", SLMask[shCount]);
+ }
}
}
/* if shCount >= 8 */
if (shCount >= 8) {
shCount -= 8 ;
-
if (size > 1){
if (shCount) {
movLeft2Result(left, LSB, result, MSB16, 0);
aopPut(AOP(result),zero, 0);
- shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
+ shiftL1Left2Result(left, MSB16, result, MSB16, shCount);
}
else {
movLeft2Result(left, LSB, result, MSB16, 0);
aopPut(AOP(result),zero, 0);
}
}
- aopPut(AOP(result),zero,LSB);
+ else {
+ aopPut(AOP(result),zero,LSB);
+ }
}
/* 1 <= shCount <= 7 */
else {
}
/*-----------------------------------------------------------------*/
-/* genlshTwo - left shift two bytes by known amount != 0 */
+/* genrshOne - left shift two bytes by known amount != 0 */
/*-----------------------------------------------------------------*/
static void genrshOne (operand *result,operand *left, int shCount)
{
static void AccRsh (int shCount)
{
if(shCount != 0){
- if(shCount == 1){
- CLRC;
- emitcode("rr","a");
- } else {
- /* rotate right accumulator */
- AccRol(8 - shCount);
- /* and kill the higher order bits */
- emit2("and a,!immedbyte", SRMask[shCount]);
- }
+ /* rotate right accumulator */
+ AccRol(8 - shCount);
+ /* and kill the higher order bits */
+ emit2("and a,!immedbyte", SRMask[shCount]);
}
}
{
/* if shCount >= 8 */
if (shCount >= 8) {
- shCount -= 8 ;
+ shCount -= 8;
if (shCount) {
shiftR1Left2Result(left, MSB16, result, LSB,
shCount, sign);
}
else {
movLeft2Result(left, MSB16, result, LSB, sign);
- aopPut(AOP(result),zero,1);
}
+ aopPut(AOP(result),zero,1);
}
/* 1 <= shCount <= 7 */
else {
}
/*-----------------------------------------------------------------*/
-/* genGenPointerGet - gget value from generic pointer space */
+/* genGenPointerGet - get value from generic pointer space */
/*-----------------------------------------------------------------*/
static void genGenPointerGet (operand *left,
operand *result, iCode *ic)
static int _reg_parm(link *l)
{
- /* for this processor it is simple
- can pass only the first parameter in a register */
- if (regParmFlg)
+ if (regParmFlg == 2)
return 0;
-
- regParmFlg = 1;
+
+ regParmFlg++;
return 1;
-
}
static bool _startsWith(const char *sz, const char *key)
enum {
DISABLE_PACK_ACC = 0,
DISABLE_PACK_ASSIGN = 0,
- LIMITED_PACK_ACC = 1
+ DISABLE_PACK_ONE_USE = 0,
+ DISABLE_PACK_HL = 0,
+ LIMITED_PACK_ACC = 1,
};
-#define D_ALLOC 1
+enum {
+ D_ALLOC = 0,
+ D_ALLOC2 = 0
+};
-#if 0
+#if 1
#define D(_a, _s) if (_a) { printf _s; fflush(stdout); }
#else
#define D(_a, _s)
if (currFunc)
currFunc->regsUsed =
bitVectSetBit(currFunc->regsUsed,i);
- D(D_ALLOC, ("allocReg: alloced %zr\n", ®sZ80[i]));
+ D(D_ALLOC, ("allocReg: alloced %p\n", ®sZ80[i]));
return ®sZ80[i];
}
}
{
wassert(!reg->isFree);
reg->isFree = 1;
- D(D_ALLOC, ("freeReg: freed %zr\n", reg));
+ D(D_ALLOC, ("freeReg: freed %p\n", reg));
}
{
symbol *sloc= NULL;
- D(D_ALLOC, ("createStackSpil: for sym %zs\n", sym));
+ D(D_ALLOC, ("createStackSpil: for sym %p\n", sym));
/* first go try and find a free one that is already
existing on the stack */
{
int i;
- D(D_ALLOC, ("spillThis: spilling %zs\n", sym));
+ D(D_ALLOC, ("spillThis: spilling %p\n", sym));
/* if this is rematerializable or has a spillLocation
we are okay, else we need to create a spillLocation
set *selectS ;
symbol *sym;
- D(D_ALLOC, ("selectSpil: finding spill for ic %zi\n", ic));
+ D(D_ALLOC, ("selectSpil: finding spill for ic %p\n", ic));
/* get the spillable live ranges */
lrcs = computeSpillable (ic);
symbol *ssym;
int i ;
- D(D_ALLOC, ("spilSomething: spilling on ic %zi\n", ic));
+ D(D_ALLOC, ("spilSomething: spilling on ic %p\n", ic));
/* get something we can spil */
ssym = selectSpil(ic,ebp,forSym);
{
regs *reg;
- D(D_ALLOC, ("getRegGpr: on ic %zi\n"));
+ D(D_ALLOC, ("getRegGpr: on ic %p\n", ic));
tryAgain:
/* try for gpr type */
if ((reg = allocReg(REG_GPR))) {
!OP_SYMBOL(IC_LEFT(ic->prev))->isspilt)
psym = OP_SYMBOL(IC_LEFT(ic->prev));
- D(D_ALLOC, ("deassignLRs: in loop on sym %zs", sym));
+ D(D_ALLOC, ("deassignLRs: in loop on sym %p nregs %u\n", sym, sym->nRegs));
if (sym->nRegs) {
int i = 0;
symbol *sym = OP_SYMBOL(op);
int i;
- D(D_ALLOC, ("reassingLR: on sym %zs\n", sym));
+ D(D_ALLOC, ("reassingLR: on sym %p\n", sym));
/* not spilt any more */
sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
int count = min(result->nRegs,opsym->nRegs);
int i , j = 0, shared = 0;
- D(D_ALLOC, ("positionRegs: on result %zs opsum %zs line %u\n", result, opsym, lineno));
+ D(D_ALLOC, ("positionRegs: on result %p opsum %p line %u\n", result, opsym, lineno));
/* if the result has been spilt then cannot share */
if (opsym->isspilt)
currFunc->regsUsed =
bitVectSetBit(currFunc->regsUsed,i+1);
}
- D(D_ALLOC, ("tryAllocRegPair: succeded for sym %zs\n", sym));
+ D(D_ALLOC, ("tryAllocRegPair: succeded for sym %p\n", sym));
return TRUE;
}
}
- D(D_ALLOC, ("tryAllocRegPair: failed on sym %zs\n", sym));
+ D(D_ALLOC, ("tryAllocRegPair: failed on sym %p\n", sym));
return FALSE;
}
int willCS ;
int j;
- D(D_ALLOC, ("serialRegAssign: in loop on result %zs\n", sym));
+ D(D_ALLOC, ("serialRegAssign: in loop on result %p\n", sym));
/* if it does not need or is spilt
or is already assigned to registers
/* if the allocation falied which means
this was spilt then break */
if (!sym->regs[j]) {
+ D(D_ALLOC, ("Couldnt alloc (spill)\n"))
break;
}
}
if ((sym->liveTo - sym->liveFrom) == 0)
continue ;
- D(D_ALLOC, ("regTypeNum: loop on sym %zs\n", sym));
+ D(D_ALLOC, ("regTypeNum: loop on sym %p\n", sym));
/* if the live range is a temporary */
if (sym->isitmp) {
}
/* if not then we require registers */
+ D(D_ALLOC, ("regTypeNum: isagg %u nRegs %u type %p\n", IS_AGGREGATE(sym->type) || sym->isptr, sym->nRegs, sym->type));
sym->nRegs = ((IS_AGGREGATE(sym->type) || sym->isptr ) ?
getSize(sym->type = aggrToPtr(sym->type,FALSE)) :
getSize(sym->type));
+ D(D_ALLOC, ("regTypeNum: setting nRegs of %s (%p) to %u\n", sym->name, sym, sym->nRegs));
- D(D_ALLOC, ("regTypeNum: setup to assign regs sym %zs\n", sym));
+ D(D_ALLOC, ("regTypeNum: setup to assign regs sym %p\n", sym));
if (sym->nRegs > 4) {
fprintf(stderr,"allocated more than 4 or 0 registers for type ");
/* Always general purpose */
sym->regType = REG_GPR ;
- } else
+ } else {
/* for the first run we don't provide */
/* registers for true symbols we will */
/* see how things go */
- sym->nRegs = 0 ;
+ D(D_ALLOC, ("regTypeNum: #2 setting num of %p to 0\n", sym, 0));
+ sym->nRegs = 0;
+ }
}
}
{
iCode *dic, *sic;
- D(D_ALLOC, ("packRegsForAssing: running on ic %zi\n", ic));
+ D(D_ALLOC, ("packRegsForAssing: running on ic %p\n", ic));
if (
/* !IS_TRUE_SYMOP(IC_RESULT(ic)) ||*/
/* for the left & right operand :- look to see if the
left was assigned a true symbol in far space in that
case replace them */
- D(D_ALLOC, ("packRegsForSupport: running on ic %zi\n", ic));
+ D(D_ALLOC, ("packRegsForSupport: running on ic %p\n", ic));
if (IS_ITEMP(IC_LEFT(ic)) &&
OP_SYMBOL(IC_LEFT(ic))->liveTo <= ic->seq) {
bitVect *uses ;
iCode *dic, *sic;
- D(D_ALLOC, ("packRegsForOneUse: running on ic %zi\n", ic));
+ D(D_ALLOC, ("packRegsForOneUse: running on ic %p\n", ic));
/* if returning a literal then do nothing */
if (!IS_SYMOP(op))
{
iCode *uic;
- D(D_ALLOC, ("packRegsForAccUse2: running on ic %zi\n", ic));
+ D(D_ALLOC, ("packRegsForAccUse2: running on ic %p\n", ic));
/* Filter out all but those 'good' commands */
if (
/* Safe: address of a true sym is always constant. */
/* if this is an itemp & result of a address of a true sym
then mark this as rematerialisable */
-
- D(D_ALLOC, ("packRegisters: looping on ic %zi\n", ic));
+ D(D_ALLOC, ("packRegisters: looping on ic %p\n", ic));
if (ic->op == ADDRESS_OF &&
IS_ITEMP(IC_RESULT(ic)) &&
!isOperandInFarSpace(IC_RIGHT(ic)) && */
!OP_SYMBOL(IC_RESULT(ic))->remat &&
!IS_OP_RUONLY(IC_RIGHT(ic)) &&
- getSize(aggrToPtr(operandType(IC_RESULT(ic)),FALSE)) > 1 )
+ getSize(aggrToPtr(operandType(IC_RESULT(ic)),FALSE)) > 1 ) {
packRegsForOneuse (ic,IC_RESULT(ic),ebp);
+ }
/* if pointer get */
- if (POINTER_GET(ic) &&
+ if (!DISABLE_PACK_ONE_USE &&
+ POINTER_GET(ic) &&
/* MLH: dont have far space
!isOperandInFarSpace(IC_RESULT(ic))&& */
!OP_SYMBOL(IC_LEFT(ic))->remat &&
!IS_OP_RUONLY(IC_RESULT(ic)) &&
- getSize(aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) > 1 )
+ getSize(aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) > 1 ) {
+
packRegsForOneuse (ic,IC_LEFT(ic),ebp);
+ }
/* pack registers for accumulator use, when the result of an
arithmetic or bit wise operation has only one use, that use is
immediately following the defintion and the using iCode has
result of that operation is not on stack then we can leave the
result of this operation in acc:b combination */
- if (IS_ITEMP(IC_RESULT(ic))) {
+ if (!DISABLE_PACK_HL && IS_ITEMP(IC_RESULT(ic))) {
packRegsForHLUse(ic);
}
#if 0
packRegsForAccUse (ic);
#else
if (!DISABLE_PACK_ACC && IS_ITEMP(IC_RESULT(ic)) &&
- getSize(operandType(IC_RESULT(ic))) == 1)
+ getSize(operandType(IC_RESULT(ic))) == 1) {
packRegsForAccUse2(ic);
+ }
#endif
}
}