/*-------------------------------------------------------------------------
- SDCCgen51.c - source file for code generation for 8051
+ gen.c - Z80 specific code generator.
+
+ Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
+ ticks dhry size
+ Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
+ Improved WORD push 22784 144 19AE
+ With label1 on 22694 144 197E
+ With label2 on 22743 144 198A
+ With label3 on 22776 144 1999
+ With label4 on 22776 144 1999
+ With all 'label' on 22661 144 196F
+ With loopInvariant on 20919 156 19AB
+ With loopInduction on Breaks 198B
+ With all working on 20796 158 196C
+ Slightly better genCmp(signed) 20597 159 195B
+ Better reg packing, first peephole 20038 163 1873
+ With assign packing 19281 165 1849
+
+ 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)
+
+ 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
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
- Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
- and - Jean-Louis VERN.jlvern@writeme.com (1999)
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
- 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
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- In other words, you are welcome to use, share and improve this program.
- You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding!
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
/* if they are the same */
if (sym1 == sym2)
- return TRUE ;
+ return 1;
if (strcmp(sym1->rname,sym2->rname) == 0)
- return TRUE;
+ return 2;
/* if left is a tmp & right is not */
!IS_ITEMP(op2) &&
sym1->isspilt &&
(sym1->usl.spillLoc == sym2))
- return TRUE;
+ return 3;
if (IS_ITEMP(op2) &&
!IS_ITEMP(op1) &&
sym2->isspilt &&
+ sym1->level > 0 &&
(sym2->usl.spillLoc == sym1))
- return TRUE ;
+ return 4;
- return FALSE ;
+ return FALSE;
}
/*-----------------------------------------------------------------*/
}
}
-char *aopGetWord(asmop *aop, int offset)
+char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
{
char *s = buffer ;
char *rs;
- assert(aop->size == 2);
+ if (aop->size != 2)
+ return NULL;
assert(offset == 0);
/* depending on type */
switch (aop->type) {
case AOP_IMMD:
- sprintf (s,"#%s",aop->aopu.aop_immd);
+ sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
ALLOC_ATOMIC(rs,strlen(s)+1);
strcpy(rs,s);
return rs;
if (!IS_FLOAT(val->type)) {
unsigned long v = floatFromVal(val);
- sprintf(buffer,"#0x%04lx", v);
+ sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
ALLOC_ATOMIC(rs,strlen(buffer)+1);
return strcpy (rs,buffer);
}
return NULL;
}
+char *aopGetWord(asmop *aop, int offset)
+{
+ return aopGetWordLong(aop, offset, TRUE);
+}
+
/*-----------------------------------------------------------------*/
/* aopGet - for fetching value of the aop */
/*-----------------------------------------------------------------*/
if (!offset && (strcmp(s,"acc") == 0))
break;
if (offset>0) {
+
emitcode("", "; Error aopPut AOP_ACC");
}
else {
/*-----------------------------------------------------------------*/
static void genUminus (iCode *ic)
{
- assert(0);
+ int offset ,size ;
+ link *optype, *rtype;
+
+ /* assign asmops */
+ aopOp(IC_LEFT(ic),ic,FALSE);
+ aopOp(IC_RESULT(ic),ic,TRUE);
+
+ /* if both in bit space then special
+ case */
+ if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
+ AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
+ assert(0);
+ goto release;
+ }
+
+ optype = operandType(IC_LEFT(ic));
+ rtype = operandType(IC_RESULT(ic));
+
+ /* if float then do float stuff */
+ if (IS_FLOAT(optype)) {
+ assert(0);
+ goto release;
+ }
+
+ /* otherwise subtract from zero */
+ size = AOP_SIZE(IC_LEFT(ic));
+ offset = 0 ;
+ CLRC ;
+ while(size--) {
+ char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
+ emitcode("ld", "a,#0");
+ emitcode("sbc","a,%s",l);
+ aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+ }
+
+ /* if any remaining bytes in the result */
+ /* we just need to propagate the sign */
+ if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
+ emitcode("rlc","a");
+ emitcode("sbc","a,a");
+ while (size--)
+ aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+ }
+
+release:
+ /* release the aops */
+ freeAsmop(IC_LEFT(ic),NULL,ic);
+ freeAsmop(IC_RESULT(ic),NULL,ic);
}
if (s) {
emitcode("ld", "hl,%s", s);
emitcode("push", "hl");
- goto release;
}
+ else {
+ /* Optimise here - load into HL then push HL */
+ emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0, FALSE));
+ emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1, FALSE));
+ emitcode("push", "hl");
+ }
+ goto release;
}
offset = size;
while (size--) {
/* adjust the stack for parameters if required */
if (IC_LEFT(ic)->parmBytes) {
int i = IC_LEFT(ic)->parmBytes;
- /* PENDING: do better */
- while (i>1) {
- emitcode("pop", "hl");
- i-=2;
+ if (i>6) {
+ emitcode("ld", "hl,#%d", i);
+ emitcode("add", "hl,sp");
+ emitcode("ld", "sp,hl");
+ }
+ else {
+ while (i>1) {
+ emitcode("pop", "hl");
+ i-=2;
+ }
+ if (i)
+ emitcode("inc", "sp");
}
- if (i)
- emitcode("inc", "sp");
}
}
if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
return FALSE;
+ emitcode("", "; genPlusIncr");
+
+ icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+
+ /* If result is a pair */
+ if (isPair(AOP(IC_RESULT(ic)))) {
+ char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
+ if (left) {
+ /* Both a lit on the right and a true symbol on the left */
+ emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
+ return TRUE;
+ }
+ }
+
/* if the literal value of the right hand side
is greater than 4 then it is not worth it */
- if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
+ if (icount > 4)
return FALSE ;
/* Inc a pair */
if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
isPair(AOP(IC_RESULT(ic)))) {
while (icount--) {
- emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
+ emitcode("inc", "%s ; 1", getPairName(AOP(IC_RESULT(ic))));
}
return TRUE;
}
size = getDataSize(IC_RESULT(ic));
+ /* Special case when left and right are constant */
+ if (isPair(AOP(IC_RESULT(ic)))) {
+ char *left, *right;
+
+ left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
+ right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
+ if (left && right) {
+ /* It's a pair */
+ /* PENDING: fix */
+ char buffer[100];
+ sprintf(buffer, "#(%s + %s)", left, right);
+ emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
+ goto release;
+ }
+ }
+
while(size--) {
if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
size = getDataSize(IC_RESULT(ic));
if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
- CLRC;
}
else{
lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
/* if literal, add a,#-lit, else normal subb */
while (size--) {
MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
- if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
- emitcode("sbc","a,%s",
- aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+ if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
+ if (!offset)
+ emitcode("sub","a,%s",
+ aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+ else
+ emitcode("sbc","a,%s",
+ aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+ }
else{
/* first add without previous c */
if (!offset)
size = max(AOP_SIZE(left),AOP_SIZE(right));
/* if unsigned char cmp with lit, just compare */
- if((size == 1) && !sign &&
+ if((size == 1) &&
(AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
- emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
+ if (sign) {
+ emitcode("xor", "a,#0x80");
+ emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
+ }
+ else
+ emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
}
else {
if(AOP_TYPE(right) == AOP_LIT) {
/* Just load in the top most bit */
MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
- assert(0);
- genIfxJump (ifx,"acc.7");
+ genIfxJump (ifx,"7");
return;
}
else
goto release;
}
}
+ if (sign) {
+ /* First setup h and l contaning the top most bytes XORed */
+ bool fDidXor = FALSE;
+ if (AOP_TYPE(left) == AOP_LIT){
+ unsigned long lit = (unsigned long)
+ floatFromVal(AOP(left)->aopu.aop_lit);
+ emitcode("ld", "l,#0x%02x",
+ 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
+ }
+ else {
+ emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
+ emitcode("xor", "a,#0x80");
+ emitcode("ld", "l,a");
+ fDidXor = TRUE;
+ }
+ if (AOP_TYPE(right) == AOP_LIT) {
+ unsigned long lit = (unsigned long)
+ floatFromVal(AOP(right)->aopu.aop_lit);
+ emitcode("ld", "h,#0x%02x",
+ 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
+ }
+ else {
+ emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
+ emitcode("xor", "a,#0x80");
+ emitcode("ld", "h,a");
+ fDidXor = TRUE;
+ }
+ if (!fDidXor)
+ CLRC;
+ }
+ else {
+ CLRC;
+ }
while (size--) {
/* Do a long subtract */
- MOVA(aopGet(AOP(left),offset,FALSE));
+ if (!sign || size)
+ MOVA(aopGet(AOP(left),offset,FALSE));
if (sign && size == 0) {
- /* Case where it's signed and we've hit the end */
- assert(0);
- } else {
+ emitcode("ld", "a,l");
+ emitcode("sbc", "a,h");
+ }
+ else {
/* Subtract through, propagating the carry */
- if (offset==0) {
- emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
- }
- else
- emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
+ emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
}
}
}
offset++;
}
} else {
- assert(0);
+ /* right is a pointer reg need both a & b */
+ /* PENDING: is this required? */
+ while(size--) {
+ char *l = aopGet(AOP(left),offset,FALSE);
+ MOVA(aopGet(AOP(right),offset,FALSE));
+ emitcode("cp", "%s", l);
+ emitcode("jr", "nz," LABEL_STR, lbl->key+100);
+ offset++;
+ }
}
}
aopOp((right= IC_RIGHT(ic)),ic,FALSE);
aopOp((result=IC_RESULT(ic)),ic,TRUE);
-#ifdef DEBUG_TYPE
+#if 1
emitcode("","; Type res[%d] = l[%d]&r[%d]",
AOP_TYPE(result),
AOP_TYPE(left), AOP_TYPE(right));
if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
continue;
else
- emitcode("or","%s,%s",
+ emitcode("or","%s,%s; 5",
aopGet(AOP(left),offset,FALSE),
aopGet(AOP(right),offset,FALSE));
} else {
if (AOP_TYPE(left) == AOP_ACC)
- emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
+ emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
else {
MOVA(aopGet(AOP(right),offset,FALSE));
- emitcode("or","a,%s",
+ emitcode("or","a,%s ; 7",
aopGet(AOP(left),offset,FALSE));
- aopPut(AOP(result),"a",0);
+ aopPut(AOP(result),"a ; 8",0);
}
}
}
MOVA(aopGet(AOP(right),offset,FALSE));
emitcode("or","a,%s",
aopGet(AOP(left),offset,FALSE));
- aopPut(AOP(result),"a",0);
}
aopPut(AOP(result),"a",offset);
+ /* PENDING: something weird is going on here. Add exception. */
+ if (AOP_TYPE(result) == AOP_ACC)
+ break;
}
}
assert(0);
} else {
/* Copy left into result */
- movLeft2Result(left,offl, result, offr, 0);
+ movLeft2Result(left, offl, result, offr, 0);
+ movLeft2Result(left, offl+1, result, offr+1, 0);
}
- if (AOP(result)->type == AOP_REG) {
+ /* PENDING: for now just see if it'll work. */
+ /*if (AOP(result)->type == AOP_REG) { */
+ {
int size = 2;
int offset = 0;
symbol *tlbl , *tlbl1;
emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
}
}
- else {
- /* PENDING: do something */
- assert(0);
- }
}
/*-----------------------------------------------------------------*/
if (AOP_TYPE(left) == AOP_IMMD)
emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
else { /* we need to get it byte by byte */
+
emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
}
result = IC_RESULT(ic);
right = IC_RIGHT(ic) ;
+#if 1
/* Dont bother assigning if they are the same */
if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
- emitcode("", "; (operands are equal)");
+ emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
return;
}
+#endif
aopOp(right,ic,FALSE);
aopOp(result,ic,TRUE);
(AOP_TYPE(result) != AOP_REG) &&
(AOP_TYPE(right) == AOP_LIT) &&
!IS_FLOAT(operandType(right)) &&
- (lit < 256L)){
- emitcode("xor","a,a");
+ (lit < 256L)) {
+ bool fXored = FALSE;
+ offset = 0;
/* Work from the top down.
Done this way so that we can use the cached copy of 0
in A for a fast clear */
while (size--) {
- if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
- aopPut(AOP(result),"a",size);
+ if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
+ if (!fXored && size>1) {
+ emitcode("xor", "a,a");
+ fXored = TRUE;
+ }
+ if (fXored) {
+ aopPut(AOP(result),"a",offset);
+ }
+ else {
+ aopPut(AOP(result), "#0", offset);
+ }
+ }
else
aopPut(AOP(result),
- aopGet(AOP(right),size,FALSE),
- size);
+ aopGet(AOP(right),offset,FALSE),
+ offset);
+ offset++;
}
} else {
while (size--) {
/*-----------------------------------------------------------------*/
static void genJumpTab (iCode *ic)
{
- assert(0);
+ symbol *jtab;
+ char *l;
+
+ aopOp(IC_JTCOND(ic),ic,FALSE);
+ /* get the condition into accumulator */
+ l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
+ MOVA(l);
+ emitcode("push", "de");
+ emitcode("ld", "e,%s", l);
+ emitcode("ld", "d,#0");
+ jtab = newiTempLabel(NULL);
+ emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
+ emitcode("add", "hl,de");
+ emitcode("add", "hl,de");
+ freeAsmop(IC_JTCOND(ic),NULL,ic);
+ emitcode("pop", "de");
+ emitcode("jp", "(hl)");
+ emitcode("","%05d$:",jtab->key+100);
+ /* now generate the jump labels */
+ for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
+ jtab = setNextItem(IC_JTLABELS(ic)))
+ emitcode("jp", LABEL_STR, jtab->key+100);
}
/*-----------------------------------------------------------------*/
/* now we are ready to call the
peep hole optimizer */
- /* if (!options.nopeep)
- peepHole (&lineHead); */
+ if (!options.nopeep)
+ peepHole (&lineHead);
/* now do the actual printing */
printLine (lineHead,codeOutFile);