#define OPTION_NOSTDLIB "-nostdlib"
#define OPTION_NOSTDINC "-nostdinc"
#define OPTION_VERBOSE "-verbose"
+#define OPTION_LESS_PEDANTIC "-lesspedantic"
+
static const char *_preCmd[] =
{
"sdcpp", "-Wall", "-lang-c++", "-DSDCC=1",
options.verbose = 1;
continue;
}
+
+ if (strcmp (argv[i] +1, OPTION_LESS_PEDANTIC) == 0)
+ {
+ setErrorLogLevel(ERROR_LEVEL_WARNINGS);
+ continue;
+ }
if (!port->parseOption (&argc, argv, &i))
{
smuldivmod[muldivmod],
ssu[su],
sbwd[bwd]);
- __muldiv[muldivmod][bwd][su] = funcOfType (buffer, __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
+ __muldiv[muldivmod][bwd][su] = funcOfType (buffer, __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
SPEC_NONBANKED (__muldiv[muldivmod][bwd][su]->etype) = 1;
if (bwd < port->muldiv.force_reg_param_below)
_makeRegParam (__muldiv[muldivmod][bwd][su]);
include $(PRJDIR)/Makefile.common
-OBJ = i186.o ralloc.o gen.o tlcs900h.o gen_generic.o
+OBJ = i186.o ralloc.o gen.o tlcs900h.o gen_generic.o aop.o util.o
LIB = port.a
CFLAGS += -I.. -I. -I../..
main.o: main.c peeph.rul peeph-z80.rul peeph-gbz80.rul mappings.i
+i186.o: i186.c i186_mappings.i
+
include clean.mk
#include "izt.h"
#include "gen.h"
-static void
-_genLabel (iCode * ic)
+static void _setupPointer(REG *reg, asmop *into, int offset)
{
- iemit ("!tlabeldef", IC_LABEL (ic)->key + 100);
+ iemit("; _setupPointer for %s", reg->name);
}
-static void
-_genGoto (iCode * ic)
+void izt_putAop(asmop *into, const char *sz, int size, int offset)
{
- iemit ("jp !tlabel", IC_LABEL (ic)->key + 100);
+ wassert(offset == 0);
+
+ switch (into->type) {
+ case AOP_TYPE_REG:
+ iemit("mov %s,%s", into->u.reg->name, sz);
+ break;
+ case AOP_TYPE_CARRY:
+ // Should support.
+ wassert(0);
+ break;
+
+ case AOP_TYPE_SCRATCH_PTR:
+ _setupPointer(izt_port->scratch, into, offset);
+ iemit("mov a,%s", sz);
+ iemit("mov %s,a", izt_port->scratch->name);
+ break;
+
+ case AOP_TYPE_STACK:
+ iemit("mov a,%s", sz);
+ iemit("mov (%s+%d),a", izt_port->base_ptr->name, into->u.stack);
+ break;
+
+ case AOP_TYPE_LITERAL:
+ case AOP_TYPE_IMMEDIATE:
+ default:
+ wassert(0);
+ }
}
-static void
-_genFunction (iCode * ic)
+char *izt_getAop(asmop *from, int size, int offset)
{
- symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+ return "blah";
+}
- // Create the function header
- iemit ("!functionheader", sym->name);
- iemit ("!functionlabeldef", sym->rname);
+/** Perform a generic move operation.
+ */
+static void _mov(asmop *into, asmop *from)
+{
+ int size = into->size;
+ izt_putAop(into, izt_getAop(from, size, 0), size, 0);
+}
- if (sym->stack)
- {
- iemit ("!enterx", sym->stack);
+static void _genLabel(iCode *ic)
+{
+ iemit("!tlabeldef", IC_LABEL(ic)->key + 100);
+}
+
+static void _genGoto(iCode *ic)
+{
+ iemit("jp !tlabel", IC_LABEL(ic)->key+100);
+}
+
+static void _genFunction(iCode *ic)
+{
+ symbol *sym = OP_SYMBOL(IC_LEFT(ic));
+
+ // Create the function header
+ iemit("!functionheader", sym->name);
+ iemit("!functionlabeldef", sym->rname);
+
+ if (sym->stack) {
+ iemit("!enterx", sym->stack);
}
else
{
}
}
+static void _genEndFunction(iCode *ic)
+{
+ // symbol *sym = OP_SYMBOL(IC_LEFT(ic));
+
+ /* PENDING: calleeSave */
+
+ iemit("!leave");
+ iemit("ret");
+}
+
static void
_genReturn (iCode * ic)
{
- if (IC_LEFT (ic))
- {
- // Has a return value. Load it up.
- iemit ("; PENDING: call the generic loader to setup the return value.");
+ if (IC_LEFT(ic)) {
+ // Has a return value. Load it up.
+ izt_bindAop(IC_LEFT(ic), ic);
+ _mov(izt_getAopForReturn(AOP_SIZE(IC_LEFT(ic))), AOP(IC_LEFT(ic)));
}
if (ic->next && ic->next->op == LABEL && IC_LABEL (ic->next) == returnLabel)
}
}
-static EMITTER _base_emitters[] =
-{
- {LABEL, _genLabel},
- {GOTO, _genGoto},
- {FUNCTION, _genFunction},
- {RETURN, _genReturn},
- {0, NULL}
+static EMITTER _base_emitters[] = {
+ { LABEL, _genLabel },
+ { GOTO, _genGoto },
+ { FUNCTION, _genFunction },
+ { RETURN, _genReturn },
+ { ENDFUNCTION, _genEndFunction },
+ { 0, NULL }
};
void
/** @file izt/i186.c
- i186 specific general functions.
+ i186 specific general functions.
*/
#include "izt.h"
-static REG _i186_regs[] =
-{
- {1, REG_ID_CL, "cl", 0,
- {REG_ID_CX, REG_ID_NONE, REG_ID_NONE}},
- {1, REG_ID_CH, "ch", 0,
- {REG_ID_CX, REG_ID_NONE, REG_ID_NONE}},
- {1, REG_ID_DL, "dl", 0,
- {REG_ID_DX, REG_ID_NONE, REG_ID_NONE}},
- {1, REG_ID_DH, "dh", 0,
- {REG_ID_DX, REG_ID_NONE, REG_ID_NONE}},
- {2, REG_ID_CX, "cx", 0,
- {REG_ID_CL, REG_ID_CH, REG_ID_NONE}},
- {2, REG_ID_DX, "dx", 0,
- {REG_ID_DL, REG_ID_DH, REG_ID_NONE}},
- {0, REG_ID_NONE, "??", 0,
- {REG_ID_NONE, REG_ID_NONE, REG_ID_NONE}}
+static REG _i186_otherRegs[] = {
+ { 1, REG_ID_AL, "al", 0, { REG_ID_AX, REG_ID_NONE, REG_ID_NONE } },
+ { 1, REG_ID_AH, "ah", 0, { REG_ID_AX, REG_ID_NONE, REG_ID_NONE } },
+ { 2, REG_ID_AX, "ax", 0, { REG_ID_AL, REG_ID_AH, REG_ID_NONE } },
+ { 1, REG_ID_BL, "bl", 0, { REG_ID_BX, REG_ID_NONE, REG_ID_NONE } },
+ { 1, REG_ID_BH, "bh", 0, { REG_ID_BX, REG_ID_NONE, REG_ID_NONE } },
+ { 2, REG_ID_BX, "bx", 0, { REG_ID_BL, REG_ID_BH, REG_ID_NONE } },
+ { 2, REG_ID_BP, "bp", 0, { REG_ID_NONE, REG_ID_NONE, REG_ID_NONE } },
+ { 0, REG_ID_NONE,"??", 0, { REG_ID_NONE, REG_ID_NONE, REG_ID_NONE } }
+};
+
+static REG _i186_regs[] = {
+ { 1, REG_ID_CL, "cl", 0, { REG_ID_CX, REG_ID_NONE, REG_ID_NONE } },
+ { 1, REG_ID_CH, "ch", 0, { REG_ID_CX, REG_ID_NONE, REG_ID_NONE } },
+ { 1, REG_ID_DL, "dl", 0, { REG_ID_DX, REG_ID_NONE, REG_ID_NONE } },
+ { 1, REG_ID_DH, "dh", 0, { REG_ID_DX, REG_ID_NONE, REG_ID_NONE } },
+ { 2, REG_ID_CX, "cx", 0, { REG_ID_CL, REG_ID_CH, REG_ID_NONE } },
+ { 2, REG_ID_DX, "dx", 0, { REG_ID_DL, REG_ID_DH, REG_ID_NONE } },
+ { 0, REG_ID_NONE,"??", 0, { REG_ID_NONE, REG_ID_NONE, REG_ID_NONE } }
};
-static IZT_PORT _i186_port =
-{
- _i186_regs
+static IZT_PORT _i186_port = {
+ _i186_regs,
+ { _i186_otherRegs + 0, _i186_otherRegs + 1, _i186_otherRegs + 2 },
+ _i186_otherRegs + 5,
+ _i186_otherRegs + 6
};
static char _defaultRules[] =
{
- //#include "peeph.rul"
+ //#include "peeph.rul"
};
/* list of key words used by i186 */
NULL
};
-// PENDING: A default set of mappings to make asm.c happy.
-static const ASM_MAPPING _asxxxx_z80_mapping[] =
-{
- /* We want to prepend the _ */
- {"area", ".area _%s"},
- {"areacode", ".area _%s"},
- {"areadata", ".area _%s"},
- {"areahome", ".area _%s"},
- {"*ixx", "%d(ix)"},
- {"*iyx", "%d(iy)"},
- {"*hl", "(hl)"},
- {"di", "di"},
- {"ldahli",
- "ld a,(hl)\n"
- "\tinc\thl"},
- {"ldahlsp",
- "ld hl,#%d\n"
- "\tadd\thl,sp"},
- {"ldaspsp",
- "ld hl,#%d\n"
- "\tadd\thl,sp\n"
- "\tld\tsp,hl"},
- {"*pair", "(%s)"},
- {"shortjp", "jp"},
- {"enter",
- "push\tix\n"
- "\tld\tix,#0\n"
- "\tadd\tix,sp"},
- {"enterx",
- "push\tix\n"
- "\tld\tix,#0\n"
- "\tadd\tix,sp\n"
- "\tld\thl,#-%d\n"
- "\tadd\thl,sp\n"
- "\tld\tsp,hl"},
- {"leave",
- "pop\tix\n"
- },
- {"leavex",
- "ld sp,ix\n"
- "\tpop\tix\n"
- },
- {"pusha",
- "push af\n"
- "\tpush\tbc\n"
- "\tpush\tde\n"
- "\tpush\thl"
- },
- {"adjustsp", "lda sp,-%d(sp)"},
- {NULL, NULL}
-};
-
-static const ASM_MAPPINGS _asxxxx_z80 =
-{
- &asm_asxxxx_mapping,
- _asxxxx_z80_mapping
-};
+#include "i186_mappings.i"
static void
_i186_init (void)
{
- asm_addTree (&asm_asxxxx_mapping);
- asm_addTree (&_asxxxx_z80);
- izt_init (&_i186_port);
+ asm_addTree(&_as86_i186_mappings);
+ izt_init(&_i186_port);
}
static void
_i186_getRegName (struct regs *reg)
{
if (reg)
- return reg->name;
+ return reg->name;
wassert (0);
return "err";
}
}
/** $1 is always the basename.
- $2 is always the output file.
- $3 varies
- $l is the list of extra options that should be there somewhere...
- MUST be terminated with a NULL.
+ $2 is always the output file.
+ $3 varies
+ $l is the list of extra options that should be there somewhere...
+ MUST be terminated with a NULL.
*/
// PENDING
static const char *_linkCmd[] =
}
/* Globals */
-PORT i186_port =
-{
- TARGET_ID_I186,
- "i186",
- "Intel 8086/80186", /* Target name */
- {
- FALSE, /* Emit glue around main */
- MODEL_SMALL,
- MODEL_SMALL
- },
- {
- _asmCmd,
- NULL,
- NULL,
- 0,
- NULL
- },
- {
- _linkCmd,
- NULL,
- ".o"
- },
- {
- _defaultRules
- },
- {
- /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
- 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
- },
- {
- "XSEG (XDATA)",
- "STACK (DATA)",
- "CSEG (CODE)",
- "DSEG (DATA)",
- "ISEG (DATA)",
- "XSEG (XDATA)",
- "BSEG (BIT)",
- "RSEG (DATA)",
- "GSINIT (CODE)",
- "OSEG (OVR,DATA)",
- "GSFINAL (CODE)",
- "HOME (CODE)",
- NULL,
- NULL,
- 1
- },
- {
- +1, 1, 4, 1, 1, 0
- },
+PORT i186_port = {
+ TARGET_ID_I186,
+ "i186",
+ "Intel 80186", /* Target name */
+ {
+ FALSE, /* Emit glue around main */
+ MODEL_SMALL,
+ MODEL_SMALL
+ },
+ {
+ _asmCmd,
+ NULL,
+ NULL,
+ 0,
+ ".s"
+ },
+ {
+ _linkCmd,
+ NULL,
+ ".o"
+ },
+ {
+ _defaultRules
+ },
+ {
+ /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
+ 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
+ },
+ {
+ ".BSS",
+ ".BSS",
+ ".TEXT",
+ ".DATA",
+ ".DATA",
+ ".DATA",
+ ".DATA",
+ ".DATA",
+ ".TEXT",
+ ".DATA",
+ ".TEXT",
+ ".TEXT",
+ NULL,
+ NULL,
+ 1
+ },
+ {
+ +1, 1, 4, 1, 1, 0
+ },
/* i186 has an 16 bit mul */
- {
- 2, 0
- },
- "_",
- _i186_init,
- _i186_parseOptions,
- _i186_finaliseOptions,
- _i186_setDefaultOptions,
- izt_assignRegisters,
- _i186_getRegName,
- _i186_keywords,
- _i186_genAssemblerPreamble,
- _i186_genIVT,
- _i186_reset_regparm,
- _i186_regparm,
- NULL,
- FALSE,
- 0, /* leave lt */
- 0, /* leave gt */
- 1, /* transform <= to ! > */
- 1, /* transform >= to ! < */
- 1, /* transform != to !(a == b) */
- 0, /* leave == */
- PORT_MAGIC
+ {
+ 2, 0
+ },
+ "_",
+ _i186_init,
+ _i186_parseOptions,
+ _i186_finaliseOptions,
+ _i186_setDefaultOptions,
+ izt_assignRegisters,
+ _i186_getRegName ,
+ _i186_keywords,
+ _i186_genAssemblerPreamble,
+ _i186_genIVT ,
+ _i186_reset_regparm,
+ _i186_regparm,
+ NULL,
+ FALSE,
+ 0, /* leave lt */
+ 0, /* leave gt */
+ 1, /* transform <= to ! > */
+ 1, /* transform >= to ! < */
+ 1, /* transform != to !(a == b) */
+ 0, /* leave == */
+ PORT_MAGIC
};
#include <common.h>
#include "gen.h"
-
-typedef enum
- {
- REG_ID_NONE,
- // Z80
- REG_ID_A,
- REG_ID_B,
- REG_ID_C,
- REG_ID_D,
- REG_ID_E,
- REG_ID_H,
- REG_ID_L,
- REG_ID_AF,
- REG_ID_BC,
- REG_ID_DE,
- REG_ID_HL,
- REG_ID_IX,
- REG_ID_IY,
- // TLCS-900H
- REG_ID_XBC,
- REG_ID_XDE,
- // i186
- REG_ID_CL,
- REG_ID_CH,
- REG_ID_CX,
- REG_ID_DL,
- REG_ID_DH,
- REG_ID_DX,
- REG_ID_MAX
- }
-REG_ID;
-
-enum
- {
- REG_USED = 1,
- REG_USED_HIDDEN = 2
- };
-
-enum
- {
- REG_TYPE_CND = 1,
- REG_TYPE_GPR = 2
- }
-REG_TYPE;
-
-typedef struct regs
- {
- int size;
- REG_ID id;
- const char *name;
- int used;
- REG_ID hides[3];
- }
-REG;
+#include "regs.h"
+#include "aop.h"
#define TEST(_d, _a) \
(_a) ? (void)0 : (failures++, printf("Test %s \"%s\" failed.\n", #_a, _d), _dumpRegs())
#define NUM_OF(_a) (sizeof(_a)/sizeof(*(_a)))
-typedef struct
- {
+typedef struct {
REG *regs;
- }
-IZT_PORT;
+ /// One for each size {1, 2, 4}
+ REG *returnRegs[3];
+ REG *scratch;
+ REG *base_ptr;
+} IZT_PORT;
IZT_PORT *izt_port;
-void izt_init (IZT_PORT * port);
-void izt_assignRegisters (eBBlock ** ebbs, int count);
-void izt_gen (iCode * ic);
+void izt_init(IZT_PORT *port);
+void izt_assignRegisters (eBBlock **ebbs, int count);
+void izt_gen(iCode *ic);
+/// Return the base 2 log of i, providing i is a power of 2.
+int izt_util_binLog(int i);
IX-2 temp0 LH
*/
-static struct
- {
- struct
- {
+static struct {
+ struct {
AOP_TYPE last_type;
const char *lit;
int offset;
- }
+ }
pairs[NUM_PAIRS];
- struct
- {
+ struct {
int last;
int pushed;
int param_offset;
int offset;
int pushed_bc;
int pushed_de;
- }
- stack;
+ } stack;
int frameId;
+ int receiveOffset;
bool flush_statics;
bool in_home;
}
{
switch (aop->type)
{
+ case AOP_IY:
case AOP_HL:
case AOP_STK:
return TRUE;
static void
fetchPairLong (PAIR_ID pairId, asmop * aop, int offset)
{
- /* if this is remateriazable */
- if (isLitWord (aop))
- {
- fetchLitPair (pairId, aop, offset);
- }
- else
- { /* we need to get it byte by byte */
- if (pairId == PAIR_HL && IS_GB && requiresHL (aop))
- {
- aopGet (aop, offset, FALSE);
- switch (aop->size)
- {
- case 1:
- emit2 ("ld l,!*hl");
- emit2 ("ld h,!immedbyte", 0);
- break;
- case 2:
- emit2 ("!ldahli");
- emit2 ("ld h,!*hl");
- emit2 ("ld l,a");
- break;
- default:
- emit2 ("; WARNING: mlh woosed out. This code is invalid.");
- }
- }
- else if (IS_Z80 && aop->type == AOP_IY)
- {
- /* Instead of fetching relative to IY, just grab directly
- from the address IY refers to */
- char *l = aopGetLitWordLong (aop, offset, FALSE);
- wassert (l);
- emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
- }
- else
- {
- emitcode ("ld", "%s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
- emitcode ("ld", "%s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
- }
- /* PENDING: check? */
- if (pairId == PAIR_HL)
- spillPair (PAIR_HL);
+ /* if this is remateriazable */
+ if (isLitWord (aop)) {
+ fetchLitPair (pairId, aop, offset);
+ }
+ else {
+ /* we need to get it byte by byte */
+ if (pairId == PAIR_HL && IS_GB && requiresHL (aop)) {
+ aopGet (aop, offset, FALSE);
+ switch (aop->size) {
+ case 1:
+ emit2 ("ld l,!*hl");
+ emit2 ("ld h,!immedbyte", 0);
+ break;
+ case 2:
+ emit2 ("!ldahli");
+ emit2 ("ld h,!*hl");
+ emit2 ("ld l,a");
+ break;
+ default:
+ emit2 ("; WARNING: mlh woosed out. This code is invalid.");
+ }
+ }
+ else if (IS_Z80 && aop->type == AOP_IY) {
+ /* Instead of fetching relative to IY, just grab directly
+ from the address IY refers to */
+ char *l = aopGetLitWordLong (aop, offset, FALSE);
+ wassert (l);
+ emit2 ("ld %s,(%s)", _pairs[pairId].name, l);
+
+ if (aop->size < 2) {
+ emit2("ld %s,!zero", _pairs[pairId].h);
+ }
+ }
+ else {
+ emitcode ("ld", "%s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
+ emitcode ("ld", "%s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE));
+ }
+ /* PENDING: check? */
+ if (pairId == PAIR_HL)
+ spillPair (PAIR_HL);
}
}
switch (pairId)
{
case PAIR_DE:
- if (bitVectBitValue (ic->rUsed, D_IDX))
+ if (bitVectBitValue (ic->rMask, D_IDX))
ret++;
- if (bitVectBitValue (ic->rUsed, E_IDX))
+ if (bitVectBitValue (ic->rMask, E_IDX))
ret++;
break;
default:
static void
setArea (int inHome)
{
- static int lastArea = 0;
-
/*
+ static int lastArea = 0;
+
if (_G.in_home != inHome) {
if (inHome) {
const char *sz = port->mem.code_name;
static void
genCall (iCode * ic)
{
- sym_link *detype = getSpec (operandType (IC_LEFT (ic)));
emitCall (ic, FALSE);
}
sym_link *fetype;
nregssaved = 0;
+ // PENDING: HACK
+ _G.receiveOffset = 0;
+
setArea (IS_NONBANKED (sym->etype));
/* PENDING: hack */
_G.stack.pushed_bc = 0;
_G.stack.pushed_de = 0;
_G.stack.param_offset = 0;
+
+ /* PENDING: BUG: We don't detect if DE or BC are used in a send set.
+ For now assume the worst and always save.
+ */
+ _G.stack.pushed_bc = 1;
+ _G.stack.pushed_de = 1;
+
if (sym->regsUsed)
{
int i;
}
}
}
- if (_G.stack.pushed_bc)
- {
+ }
+
+ if (_G.stack.pushed_bc)
+ {
emit2 ("push bc");
_G.stack.param_offset += 2;
- }
- if (_G.stack.pushed_de)
- {
+ }
+ if (_G.stack.pushed_de)
+ {
emit2 ("push de");
_G.stack.param_offset += 2;
- }
- }
+ }
/* adjust the stack for the function */
_G.stack.last = sym->stack;
aopOp ((right = IC_RIGHT (ic)), ic, FALSE, FALSE);
aopOp ((result = IC_RESULT (ic)), ic, TRUE, FALSE);
+ emit2("; genCmpEq: left %u, right %u, result %u\n", AOP_SIZE(IC_LEFT(ic)), AOP_SIZE(IC_RIGHT(ic)), AOP_SIZE(IC_RESULT(ic)));
+
/* Swap operands if it makes the operation easier. ie if:
1. Left is a literal.
*/
}
else
{
- accInUse++;
- aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
- accInUse--;
- assignResultValue (IC_RESULT (ic));
+ // PENDING: HACK
+ int size;
+ int i;
+
+ aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
+ size = AOP_SIZE(IC_RESULT(ic));
+
+ for (i = 0; i < size; i++) {
+ aopPut(AOP(IC_RESULT(ic)), _fReturn[_G.receiveOffset++], i);
+ }
}
freeAsmop (IC_RESULT (ic), NULL, ic);
"push\tix\n"
"\tld\tix,#0\n"
"\tadd\tix,sp\n"
+ "\tld\tb,h\n"
+ "\tld\tc,l\n"
"\tld\thl,#-%d\n"
"\tadd\thl,sp\n"
- "\tld\tsp,hl" },
+ "\tld\tsp,hl\n"
+ "\tld\th,b\n"
+ "\tld\tl,c"
+ },
{ "leave",
"pop\tix\n"
},