SDCCsymt.o SDCCopt.o SDCCast.o SDCCmem.o SDCCval.o \
SDCCicode.o SDCCbitv.o SDCCset.o SDCClabel.o \
SDCCBBlock.o SDCCloop.o SDCCcse.o SDCCcflow.o SDCCdflow.o \
- SDCClrange.o SDCCptropt.o SDCCpeeph.o SDCCglue.o spawn.o
+ SDCClrange.o SDCCptropt.o SDCCpeeph.o SDCCglue.o spawn.o \
+ asm.o
+
SOURCES = $(patsubst %.o,%.c,$(OBJECTS))
TARGET = $(PRJDIR)/bin/sdcc
-------------------------------------------------------------------------*/
#include "common.h"
+#include "asm.h"
#include <time.h>
symbol *interrupts[256];
fputc (ch, dest);
}
-/*-----------------------------------------------------------------*/
-/* aopLiteral - string from a literal value */
-/*-----------------------------------------------------------------*/
-char *aopLiteral (value *val, int offset)
+char *aopLiteralLong(value *val, int offset, int size)
{
char *rs;
union {
unsigned long v = floatFromVal(val);
v >>= (offset * 8);
- sprintf(buffer,"#0x%02x",((char) v) & 0xff);
+ switch (size) {
+ case 1:
+ sprintf(buffer,"#0x%02x", (unsigned int)v & 0xff);
+ break;
+ case 2:
+ sprintf(buffer,"#0x%04x", (unsigned int)v & 0xffff);
+ break;
+ default:
+ /* Hmm. Too big for now. */
+ assert(0);
+ }
ALLOC_ATOMIC(rs,strlen(buffer)+1);
return strcpy (rs,buffer);
}
+ /* PENDING: For now size must be 1 */
+ assert(size == 1);
+
/* it is type float */
fl.f = (float) floatFromVal(val);
#ifdef _BIG_ENDIAN
return strcpy (rs,buffer);
}
+/*-----------------------------------------------------------------*/
+/* aopLiteral - string from a literal value */
+/*-----------------------------------------------------------------*/
+char *aopLiteral (value *val, int offset)
+{
+ return aopLiteralLong(val, offset, 1);
+}
+
/*-----------------------------------------------------------------*/
/* emitRegularMap - emit code for maps with no special cases */
/*-----------------------------------------------------------------*/
symbol *sym;
if (addPublics)
- fprintf (map->oFile, "\t.area\t%s\n", map->sname);
+ asm_printf(map->oFile, asm_port->area, map->sname);
/* print the area name */
for (sym = setFirstItem (map->syms); sym;
/* allocate space */
if ((options.debug || sym->level == 0) && !options.nodebug)
fprintf(map->oFile,"==.\n");
- fprintf (map->oFile, "%s:\n", sym->rname);
- fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
+ asm_printf(map->oFile, asm_port->label, sym->rname);
+ asm_printf(map->oFile, asm_port->ds, (unsigned int)getSize (sym->type) & 0xffff);
}
/* if it has a initial value then do it only if
int i;
int len = strlen (s);
int pplen = 0;
-
- while (len && pplen < plen) {
+ char buf[100];
+ char *p = buf;
+ while (len && pplen < plen) {
+ while (i && *s && pplen < plen) {
+ if (*s < ' ' || *s == '\"') {
+ *p = '\0';
+ if (p != buf)
+ asm_printf(ofile, asm_port->ascii, buf);
+ asm_printf(ofile, asm_port->db, *s);
+ p = buf;
+ }
+ else {
+ *p = *s;
+ p++;
+ }
+ s++;
+ pplen++;
+ i--;
+ }
+ if (p != buf) {
+ *p = '\0';
+ asm_printf(ofile, asm_port->ascii, buf);
+ }
+
+ if (len > 60)
+ len -= 60;
+ else
+ len = 0;
+ }
+ asm_printf(ofile, asm_port->db, 0);
+#if 0
+ if (pplen < plen)
+ fprintf(ofile,"\t.byte\t0\n");
+
fprintf (ofile, "\t.ascii /");
i = 60;
while (i && *s && pplen < plen) {
}
if (pplen < plen)
fprintf(ofile,"\t.byte\t0\n");
+#endif
}
/*-----------------------------------------------------------------*/
break;
case 2:
- if (!val)
- fprintf (oFile, "\t.word 0\n");
- else
- fprintf (oFile, "\t.byte %s,%s\n",
- aopLiteral (val, 0), aopLiteral (val, 1));
- break;
-
+ fprintf(oFile, "\t.word %s\n", aopLiteralLong(val, 0, 2));
+break;
case 4:
if (!val)
fprintf (oFile, "\t.word 0,0\n");
{
int size = 0;
+ /* PENDING: this is _very_ mcs51 specific, including a magic
+ number...
+ It's also endin specific.
+ */
size = getSize (type);
-
- if (size == 1)
- fprintf(oFile,
- "\t.byte %s", val->name) ;
- else
- fprintf (oFile,
- "\t.byte %s,(%s >> 8)",
- val->name, val->name);
-
- if (size > 2)
- fprintf (oFile, ",#0x02\n");
- else
- fprintf (oFile, "\n");
-
+
+ if (val->name && strlen(val->name)) {
+ switch (size) {
+ case 1:
+ fprintf(oFile,
+ "\t.byte %s\n", val->name) ;
+ break;
+ case 2:
+ fprintf(oFile, "\t.word %s\n", val->name);
+ break;
+ /* PENDING: probably just 3 */
+ default:
+ /* PENDING: 0x02 or 0x%02x, CDATA? */
+ fprintf (oFile,
+ "\t.byte %s,(%s >> 8),#0x02\n",
+ val->name, val->name);
+ }
+ }
+ else {
+ switch (size) {
+ case 1:
+ fprintf(oFile, "\t.byte %s\n", aopLiteral(val, 0));
+ break;
+ case 2:
+ fprintf(oFile, "\t.word %s\n",
+ aopLiteralLong(val, 0, 2));
+ break;
+ case 3:
+ /* PENDING: 0x02 or 0x%02x, CDATA? */
+ fprintf(oFile, "\t.byte %s,%s,0x02\n",
+ aopLiteral (val, 0), aopLiteral (val, 1));
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+
if (val->sym && val->sym->isstrlit)
addSet (&statsg->syms, val->sym);
fprintf (oFile, "\t.byte 0x%02x\n", ((char) floatFromVal (val)) & 0xff);
break;
case 2:
- fprintf (oFile, "\t.byte %s,%s\n",
- aopLiteral (val, 0), aopLiteral (val, 1));
-
+ fprintf (oFile, "\t.word %s\n", aopLiteralLong(val, 0, 2));
break;
case 3:
fprintf (oFile, "\t.byte %s,%s,0x%02x\n",
printChar (code->oFile,
SPEC_CVAL (sym->etype).v_char,
strlen(SPEC_CVAL (sym->etype).v_char)+1);
- else
- fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type)& 0xffff);
+ else
+ asm_printf(code->oFile, asm_port->ds, (unsigned int)getSize (sym->type)& 0xffff);
}
}
}
for (sym = setFirstItem (publics); sym;
sym = setNextItem (publics))
- fprintf (afile, "\t.globl %s\n", sym->rname);
+ asm_printf(afile, asm_port->global, sym->rname);
}
/*-----------------------------------------------------------------*/
fprintf(afile,"==.\n");
/* allocate space */
- fprintf (afile, "%s:\n", sym->rname);
- fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
+ asm_printf(afile, asm_port->label, sym->rname);
+ asm_printf(afile, asm_port->ds, (unsigned int)getSize (sym->type) & 0xffff);
}
}
initialComments (asmFile);
/* print module name */
- fprintf (asmFile, "\t.module %s\n", moduleName);
+ asm_printf(asmFile, asm_port->module, moduleName);
/* Let the port generate any global directives, etc. */
if (port->genAssemblerPreamble)
#define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
+extern ASM_PORT asxxxx_port;
+extern ASM_PORT rgbds_port;
+
+ASM_PORT *asm_port;
+
+static ASM_PORT *_asm_ports[] = {
+ &asxxxx_port,
+ &rgbds_port
+};
+
/** Sets the port to the one given by the command line option.
@param The name minus the option (eg 'mcs51')
@return 0 on success.
static void _findPort(int argc, char **argv)
{
+ asm_port = _asm_ports[0];
argc--;
while (argc) {
if (!strncmp(*argv, "-m", 2)) {
#include "SDCCptropt.h"
#include "SDCCopt.h"
+#include "asm.h"
#include "port.h"
#include "config.h"
emitcode("ld", "%s,#%s", pair, l);
}
-static void fetchPair(PAIR_ID pairId, asmop *aop)
+static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
{
/* if this is remateriazable */
if (isLitWord(aop)) {
- fetchLitPair(pairId, aop, 0);
+ fetchLitPair(pairId, aop, offset);
}
else { /* we need to get it byte by byte */
if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
- aopGet(aop, 0, FALSE);
+ aopGet(aop, offset, FALSE);
emitcode("ld", "a,(hl+)");
emitcode("ld", "h,(hl)");
emitcode("ld", "l,a");
}
else {
- emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, 0, FALSE));
- emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, 1, FALSE));
+ 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)
}
}
+static void fetchPair(PAIR_ID pairId, asmop *aop)
+{
+ fetchPairLong(pairId, aop, 0);
+}
+
static void fetchHL(asmop *aop)
{
fetchPair(PAIR_HL, aop);
/*-----------------------------------------------------------------*/
void assignResultValue(operand * oper)
{
- int offset = 0;
int size = AOP_SIZE(oper);
+ bool topInA = 0;
- wassert(size <= 2);
+ wassert(size <= 4);
+ topInA = requiresHL(AOP(oper));
- while (size--) {
- aopPut(AOP(oper),_fReturn[offset],offset);
- offset++;
+ if (!IS_GB)
+ wassert(size <= 2);
+ if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
+ /* We do it the hard way here. */
+ emitcode("push", "hl");
+ _G.stack.pushed += 2;
+ aopPut(AOP(oper), _fReturn[0], 0);
+ aopPut(AOP(oper), _fReturn[1], 1);
+ emitcode("pop", "de");
+ _G.stack.pushed -= 2;
+ aopPut(AOP(oper), _fReturn[0], 2);
+ aopPut(AOP(oper), _fReturn[1], 3);
+ }
+ else {
+ while (size--) {
+ aopPut(AOP(oper), _fReturn[size], size);
+ }
}
}
}
else {
if (_G.stack.offset) {
- emitcode("ld", "hl,#%d", _G.stack.offset);
- emitcode("add", "hl,sp");
- emitcode("ld", "sp,hl");
+ emitcode("lda", "sp,%d(sp)", _G.stack.offset);
}
}
emitcode("pop", "bc");
emitcode("ret", "");
- emitcode("; Useful for profiling and debugging", "");
- emitcode(".dw", "%s", sym->rname);
- emitcode("", "__%s_end:", sym->rname);
}
_G.stack.pushed = 0;
_G.stack.offset = 0;
}
}
else {
- while (size--) {
- l = aopGet(AOP(IC_LEFT(ic)),offset,
- FALSE);
- if (strcmp(_fReturn[offset],l))
- emitcode("ld","%s,%s", _fReturn[offset++],l);
+ if (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
+ fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
+ fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
+ }
+ else {
+ while (size--) {
+ l = aopGet(AOP(IC_LEFT(ic)),offset,
+ FALSE);
+ if (strcmp(_fReturn[offset],l))
+ emitcode("ld","%s,%s", _fReturn[offset++],l);
+ }
}
}
freeAsmop (IC_LEFT(ic),NULL,ic);
freeAsmop(result,NULL,ic);
}
+/*-----------------------------------------------------------------*/
/* genlshTwo - left shift two bytes by known amount != 0 */
/*-----------------------------------------------------------------*/
static void genrshOne (operand *result,operand *left, int shCount)
/*-----------------------------------------------------------------*/
static void genRightShift (iCode *ic)
{
- operand *left,*right, *result;
+ operand *right, *left, *result;
+ link *retype ;
+ int size, offset, first = 1;
+ char *l;
+ bool is_signed;
+
+ symbol *tlbl, *tlbl1 ;
+
+ /* if signed then we do it the hard way preserve the
+ sign bit moving it inwards */
+ retype = getSpec(operandType(IC_RESULT(ic)));
+
+ is_signed = !SPEC_USIGN(retype);
+
+ /* signed & unsigned types are treated the same : i.e. the
+ signed is NOT propagated inwards : quoting from the
+ ANSI - standard : "for E1 >> E2, is equivalent to division
+ by 2**E2 if unsigned or if it has a non-negative value,
+ otherwise the result is implementation defined ", MY definition
+ is that the sign does not get propagated */
right = IC_RIGHT(ic);
left = IC_LEFT(ic);
/* if the shift count is known then do it
as efficiently as possible */
if (AOP_TYPE(right) == AOP_LIT) {
- genRightShiftLiteral (left,right,result,ic);
- return ;
+ genRightShiftLiteral(left,right,result,ic);
+ return;
}
- else {
- wassert(0);
+
+ aopOp(left,ic,FALSE);
+ aopOp(result,ic,FALSE);
+
+ /* now move the left to the result if they are not the
+ same */
+ if (!sameRegs(AOP(left),AOP(result)) &&
+ AOP_SIZE(result) > 1) {
+
+ size = AOP_SIZE(result);
+ offset=0;
+ while (size--) {
+ l = aopGet(AOP(left),offset,FALSE);
+ aopPut(AOP(result),l,offset);
+ offset++;
+ }
}
+
+ emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
+ emitcode("inc","a");
+ freeAsmop (right, NULL, ic);
+
+ tlbl = newiTempLabel(NULL);
+ tlbl1= newiTempLabel(NULL);
+ size = AOP_SIZE(result);
+ offset = size - 1;
+
+ emitcode(_shortJP, LABEL_STR, tlbl1->key+100);
+ emitcode("", LABEL_STR ":", tlbl->key+100);
+ while (size--) {
+ l = aopGet(AOP(result),offset--,FALSE);
+ if (first) {
+ if (is_signed)
+ emitcode("sra", "%s", l);
+ else
+ emitcode("srl", "%s", l);
+ first = 0;
+ }
+ else
+ emitcode("rr", "%s", l);
+ }
+ emitcode("", LABEL_STR ":", tlbl1->key+100);
+ emitcode("dec", "a");
+ emitcode(_shortJP, "nz," LABEL_STR, tlbl->key+100);
+
+ freeAsmop(left,NULL,ic);
+ freeAsmop(result,NULL,ic);
}
/*-----------------------------------------------------------------*/