Better reg packing, first peephole 20038 163 1873
With assign packing 19281 165 1849
5/3/00 17741 185 17B6
+ With reg params for mul and div 16234 202 162D
Michael Hope <michaelh@earthling.net> 2000
Based on the mcs51 generator -
#endif
#include "z80.h"
+#include "SDCCglobl.h"
#include "SDCCpeeph.h"
#include "gen.h"
#include "SDCCglue.h"
+#include "newalloc.h"
/* this is the down and dirty file with all kinds of kludgy & hacky
stuff. This is what it is all about CODE GENERATION for a specific MCU.
{
asmop *aop;
- ALLOC(aop,sizeof(asmop));
+ aop = Safe_calloc(sizeof(asmop));
aop->type = type;
return aop;
}
/* special case for a function */
if (IS_FUNC(sym->type)) {
sym->aop = aop = newAsmop(AOP_IMMD);
- ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
+ aop->aopu.aop_immd = Safe_calloc(strlen(sym->rname)+1);
strcpy(aop->aopu.aop_immd,sym->rname);
aop->size = 2;
return aop;
break;
}
- ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
+ aop->aopu.aop_immd = Safe_calloc(strlen(buffer)+1);
strcpy(aop->aopu.aop_immd,buffer);
return aop;
}
tsprintf(s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
else
tsprintf(s, "%s + %d", aop->aopu.aop_immd, offset);
- ALLOC_ATOMIC(rs,strlen(s)+1);
+ rs = Safe_calloc(strlen(s)+1);
strcpy(rs,s);
return rs;
case AOP_LIT: {
/* otherwise it is fairly simple */
if (!IS_FLOAT(val->type)) {
unsigned long v = floatFromVal(val);
+
if (offset == 2)
v >>= 16;
+
if (with_hash)
tsprintf(buffer, "!immedword", v);
else
tsprintf(buffer, "!constword", v);
- ALLOC_ATOMIC(rs,strlen(buffer)+1);
+ rs = Safe_calloc(strlen(buffer)+1);
return strcpy (rs,buffer);
}
else {
tsprintf(buffer, "!immedword", f.w[offset/2]);
else
tsprintf(buffer, "!constword", f.w[offset/2]);
- ALLOC_ATOMIC(rs,strlen(buffer)+1);
+ rs = Safe_calloc(strlen(buffer)+1);
return strcpy (rs,buffer);
}
}
}
}
+static char *fetchLitSpecial(asmop *aop, bool negate, bool xor)
+{
+ unsigned long v;
+ value * val = aop->aopu.aop_lit;
+
+ wassert(aop->type == AOP_LIT);
+ wassert(!IS_FLOAT(val->type));
+
+ v = floatFromVal(val);
+
+ if (xor)
+ v ^= 0x8000;
+ if (negate)
+ v = -v;
+ v &= 0xFFFF;
+
+ tsprintf(buffer, "!immedword", v);
+ return gc_strdup(buffer);
+}
+
static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
{
const char *l;
_G.pairs[pairId].lit = gc_strdup(l);
_G.pairs[pairId].offset = offset;
}
- if (IS_GB && pairId == PAIR_DE) {
+ if (IS_GB && pairId == PAIR_DE && 0) {
if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
if (abs(_G.pairs[pairId].offset - offset) < 3) {
adjustPair(pair, &_G.pairs[pairId].offset, offset);
default:
wassert(0);
}
- ALLOC_ATOMIC(rs,strlen(s)+1);
+ rs = Safe_calloc(strlen(s)+1);
strcpy(rs,s);
return rs;
wassert(IS_GB);
emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
sprintf(s, "a");
- ALLOC_ATOMIC(rs,strlen(s)+1);
+ rs = Safe_calloc(strlen(s)+1);
strcpy(rs,s);
return rs;
wassert(IS_GB);
emitcode("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
sprintf(s, "a");
- ALLOC_ATOMIC(rs,strlen(s)+1);
+ rs = Safe_calloc(strlen(s)+1);
strcpy(rs,s);
return rs;
wassert(IS_Z80);
setupPair(PAIR_IY, aop, offset);
tsprintf(s,"!*iyx", offset);
- ALLOC_ATOMIC(rs,strlen(s)+1);
+ rs = Safe_calloc(strlen(s)+1);
strcpy(rs,s);
return rs;
tsprintf(s, "!*hl");
}
else {
- tsprintf(s,"!*ixx", aop->aopu.aop_stk+offset);
+ if (aop->aopu.aop_stk >= 0)
+ offset += _G.stack.param_offset;
+ tsprintf(s,"!*ixx ; x", aop->aopu.aop_stk+offset);
}
- ALLOC_ATOMIC(rs,strlen(s)+1);
+ rs = Safe_calloc(strlen(s)+1);
strcpy(rs,s);
return rs;
emit2("ld !*hl,%s", s);
}
else {
+ if (aop->aopu.aop_stk >= 0)
+ offset += _G.stack.param_offset;
if (!canAssignToPtr(s)) {
emit2("ld a,%s", s);
emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
/** Take the value in carry and put it into a register
*/
-void outBitC(operand *result)
+void outBitCLong(operand *result, bool swap_sense)
{
/* if the result is bit */
if (AOP_TYPE(result) == AOP_CRY) {
else {
emit2("ld a,!zero");
emit2("rla");
+ if (swap_sense)
+ emit2("xor a,!immedbyte", 1);
outAcc(result);
}
}
+void outBitC(operand *result)
+{
+ outBitCLong(result, FALSE);
+}
+
/*-----------------------------------------------------------------*/
/* toBoolean - emit code for orl a,operator(sizeop) */
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
static void genNot (iCode *ic)
{
- link *optype = operandType(IC_LEFT(ic));
+ sym_link *optype = operandType(IC_LEFT(ic));
/* assign asmOps to operand & result */
aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
static void genUminus (iCode *ic)
{
int offset ,size ;
- link *optype, *rtype;
+ sym_link *optype, *rtype;
/* assign asmops */
aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
static void emitCall(iCode *ic, bool ispcall)
{
int pushed_de = 0;
- link *detype = getSpec(operandType(IC_LEFT(ic)));
-
- if (IS_BANKED(detype))
- emit2("; call to a banked function");
+ sym_link *detype = getSpec(operandType(IC_LEFT(ic)));
/* if caller saves & we have not saved then */
if (!ic->regsSaved) {
}
if (ispcall) {
- if (IS_BANKED(detype)) {
+ if (IS_BANKEDCALL(detype)) {
werror(W_INDIR_BANKED);
}
aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
OP_SYMBOL(IC_LEFT(ic))->rname :
OP_SYMBOL(IC_LEFT(ic))->name;
- if (IS_BANKED(detype)) {
+ if (IS_BANKEDCALL(detype)) {
emit2("call banked_call");
emit2("!dws", name);
emit2("!dw !bankimmeds", name);
/*-----------------------------------------------------------------*/
static void genCall (iCode *ic)
{
- link *detype = getSpec(operandType(IC_LEFT(ic)));
+ sym_link *detype = getSpec(operandType(IC_LEFT(ic)));
emitCall(ic, FALSE);
}
return 0;
}
+extern set *publics;
+
/*-----------------------------------------------------------------*/
/* genFunction - generated code for function entry */
/*-----------------------------------------------------------------*/
static void genFunction (iCode *ic)
{
symbol *sym = OP_SYMBOL(IC_LEFT(ic));
- link *fetype;
+ sym_link *fetype;
nregssaved = 0;
setArea(IS_NONBANKED(sym->etype));
+ /* PENDING: hack */
+ if (!IS_STATIC(sym->etype)) {
+ addSetIfnotP(&publics, sym);
+ }
+
/* create the function header */
emit2("!functionheader", sym->name);
/* PENDING: portability. */
/* if true label then we jump if condition
supplied is true */
- if ( IC_TRUE(ic) ) {
+ if (IC_TRUE(ic)) {
jlbl = IC_TRUE(ic);
if (!strcmp(jval, "a")) {
inst = "nz";
else if (!strcmp(jval, "c")) {
inst = "c";
}
+ else if (!strcmp(jval, "nc")) {
+ inst = "nc";
+ }
else {
/* The buffer contains the bit on A that we should test */
inst = "nz";
else if (!strcmp(jval, "c")) {
inst = "nc";
}
+ else if (!strcmp(jval, "nc")) {
+ inst = "c";
+ }
else {
/* The buffer contains the bit on A that we should test */
inst = "z";
}
else if (!strcmp(jval, "c")) {
}
+ else if (!strcmp(jval, "nc")) {
+ }
else {
emitcode("bit", "%s,a", jval);
}
ic->generated = 1;
}
+static const char *_getPairIdName(PAIR_ID id)
+{
+ return _pairs[id].name;
+}
+
/** Generic compare for > or <
*/
static void genCmp (operand *left,operand *right,
{
int size, offset = 0 ;
unsigned long lit = 0L;
+ bool swap_sense = FALSE;
/* if left & right are bit variables */
if (AOP_TYPE(left) == AOP_CRY &&
emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
}
else {
+ /* Special cases:
+ On the GB:
+ If the left or the right is a lit:
+ Load -lit into HL, add to right via, check sense.
+ */
+ if (size == 2 && (AOP_TYPE(right) == AOP_LIT || AOP_TYPE(left) == AOP_LIT)) {
+ PAIR_ID id = PAIR_DE;
+ asmop *lit = AOP(right);
+ asmop *op = AOP(left);
+ swap_sense = TRUE;
+
+ if (AOP_TYPE(left) == AOP_LIT) {
+ swap_sense = FALSE;
+ lit = AOP(left);
+ op = AOP(right);
+ }
+ if (sign) {
+ emit2("ld e,%s", aopGet(op, 0, 0));
+ emit2("ld a,%s", aopGet(op, 1, 0));
+ emit2("xor a,!immedbyte", 0x80);
+ emit2("ld d,a");
+ }
+ else {
+ id = getPairId(op);
+ if (id == PAIR_INVALID) {
+ fetchPair(PAIR_DE, op);
+ id = PAIR_DE;
+ }
+ }
+ spillPair(PAIR_HL);
+ emit2("ld hl,%s", fetchLitSpecial(lit, TRUE, sign));
+ emit2("add hl,%s", _getPairIdName(id));
+ goto release;
+ }
if(AOP_TYPE(right) == AOP_LIT) {
lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
/* optimize if(x < 0) or if(x >= 0) */
release:
if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
- outBitC(result);
+ outBitCLong(result, swap_sense);
} else {
/* if the result is used in the next
ifx conditional branch then generate
code a little differently */
- if (ifx )
- genIfxJump (ifx,"c");
+ if (ifx)
+ genIfxJump(ifx, swap_sense ? "nc" : "c");
else
- outBitC(result);
+ outBitCLong(result, swap_sense);
/* leave the result in acc */
}
}
static void genCmpGt (iCode *ic, iCode *ifx)
{
operand *left, *right, *result;
- link *letype , *retype;
+ sym_link *letype , *retype;
int sign ;
left = IC_LEFT(ic);
static void genCmpLt (iCode *ic, iCode *ifx)
{
operand *left, *right, *result;
- link *letype , *retype;
+ sym_link *letype , *retype;
int sign ;
left = IC_LEFT(ic);
static void genRightShift (iCode *ic)
{
operand *right, *left, *result;
- link *retype ;
+ sym_link *retype ;
int size, offset, first = 1;
char *l;
bool is_signed;
operand *result, iCode *ic)
{
int size, offset ;
- link *retype = getSpec(operandType(result));
+ sym_link *retype = getSpec(operandType(result));
int pair = PAIR_HL;
if (IS_GB)
static void genPointerGet (iCode *ic)
{
operand *left, *result ;
- link *type, *etype;
+ sym_link *type, *etype;
left = IC_LEFT(ic);
result = IC_RESULT(ic) ;
operand *result, iCode *ic)
{
int size, offset ;
- link *retype = getSpec(operandType(right));
+ sym_link *retype = getSpec(operandType(right));
PAIR_ID pairId = PAIR_HL;
aopOp(result,ic,FALSE, FALSE);
static void genPointerSet (iCode *ic)
{
operand *right, *result ;
- link *type, *etype;
+ sym_link *type, *etype;
right = IC_RIGHT(ic);
result = IC_RESULT(ic) ;
spillCached();
if (sym->onStack) {
/* if it has an offset then we need to compute it */
- emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
+ if (sym->stack > 0)
+ emitcode("ld", "hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
+ else
+ emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
emitcode("add", "hl,sp");
}
else {
static void genCast (iCode *ic)
{
operand *result = IC_RESULT(ic);
- link *ctype = operandType(IC_LEFT(ic));
+ sym_link *ctype = operandType(IC_LEFT(ic));
operand *right = IC_RIGHT(ic);
int size, offset ;