home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
messroms.de
/
2007-01-13_www.messroms.de.zip
/
VZ200
/
TOOLS
/
ZCCSRC.ZIP
/
scc
/
codez80.c
next >
Wrap
C/C++ Source or Header
|
2000-03-09
|
11KB
|
760 lines
/* File code8080.c: 2.2 (84/08/31,10:05:09) */
/*% cc -O -c %
*
*/
#include <stdio.h>
#include "defs.h"
#include "data.h"
#include "proto.h"
/*
* Some predefinitions:
*
* INTSIZE is the size of an integer in the target machine
* BYTEOFF is the offset of an byte within an integer on the
* target machine. (ie: 8080,pdp11 = 0, 6809 = 1, 360 = 3)
* This compiler assumes that an integer is the SAME length as
* a pointer - in fact, the compiler uses INTSIZE for both.
*/
#define INTSIZE 2
#define BYTEOFF 0
int savestkp;
/* Print all assembler info before any code is generated */
void header(char *n)
{
outstr(";\tSmall C z80;\n;\tCoder (2.5,00/03/03)\n;");
FEvers();
nl();
ol(".globl\t.gchar,.gint,.pchar,.pint,.bool,.sxt,.or,.and,.xor");
ol(".globl\t.eq,.ne,.gt,.le,.ge,.lt,.uge,.ult,.ugt,.ule");
ol(".globl\t.asr,.asl,.sub,.neg,.com,.lneg,.mul,.div,.mod");
ol(".globl\t.case");
outstr("\t.module");
ol(n);
}
/* New line */
void nl(void)
{
outbyte(EOL);
}
/* Default path to prepend to includes */
char *inclib(void)
{
return ("");
}
/* Initialize macros */
void initmac(void)
{
defmac("Z80\t1");
defmac("smallc\t1");
}
/* Return aligned address */
int galign(int t)
{
return (t);
}
/* Return size of an integer */
int intsize(void)
{
return (INTSIZE);
}
/*
* Return offset of less significant byte within word
* (ie: 8080 & pdp11 is 0, 6809 is 1, 360 is 3)
*/
int byteoff(void)
{
return (BYTEOFF);
}
/* Output internal generated label prefix */
void olprfix(void)
{
outbyte('.');
}
/* Output a label definition terminator */
void col(void)
{
outbyte(':');
}
/* Begin a comment line for the assembler */
void comment(void)
{
outbyte(';');
}
/* Emit user label prefix */
void prefix(void)
{
}
/* Print any assembler stuff needed after all code */
void trailer(void)
{
}
/* Function prologue */
void prologue(void)
{
}
#ifdef FRAME_IX
/* set up frame pointer */
int frame(void)
{
ol("push\tix");
ol("ld\tix, #0"); /* make ix point to where sp was before push */
ol("add\tix, sp");
stkp = stkp - INTSIZE;
savestkp = stkp;
return (INTSIZE);
}
#endif
/* text (code) segment */
void gtext(void)
{
ol(".area\t_CODE");
}
/* data segment */
void gdata(void)
{
ol(".area\t_DATA");
}
/* bss segment */
void gbss(void)
{
ol(".area\t_BSS");
}
/* Output the variable symbol at scptr as an extrn or a public */
void ppubext(char *scptr)
{
if (cptr[STORAGE] == STATIC)
return;
ot(scptr[STORAGE] == EXTERN ? ".globl\t" : ".globl\t");
prefix();
outstr(scptr);
nl();
}
/* Output the function symbol at scptr as an extrn or a public */
void fpubext(char *scptr)
{
if (scptr[STORAGE] == STATIC)
return;
ot(scptr[OFFSET] == FUNCTION ? ".globl\t" : ".globl\t");
prefix();
outstr(scptr);
nl();
}
/* Output a decimal number to the assembler file */
void onum(int num)
{
outdec(num); /* pdp11 needs a "." here */
}
/* Fetch a static memory cell into the primary register */
void getmem(char *sym)
{
if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR))
{
ot("ld\ta,(");
outstr(sym + NAME);
outbyte(')');
#ifdef FRAME_IX
ot(";static");
#endif
nl();
gcall(".sxt");
}
else
{
ot("ld\thl,(");
outstr(sym + NAME);
outbyte(')');
#ifdef FRAME_IX
ot(";static");
#endif
nl();
}
}
/*
* fetch the address of the specified symbol into the primary register
*/
void getloc(char *sym)
{
int i;
immed();
if (sym[STORAGE] == LSTATIC)
{
printlabel(glint(sym));
#ifdef FRAME_IX
ot(";static");
#endif
nl();
}
else
{
outdec(glint(sym) - stkp);
#ifdef FRAME_IX
/* generate the annotation only if in range of (ix) addressing */
if ((i = glint(sym) - savestkp) >= -128 && i <= 127)
{
ot(";");
outdec(i);
outstr("(ix) [");
outstr(sym);
outstr("]");
}
#endif
nl();
ol("add\thl,sp");
}
}
/*
* store the primary register into the specified static memory cell
*/
void putmem(char *sym)
{
if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR))
{
ol("ld\ta,l");
ot("ld\t(");
outstr(sym + NAME);
outstr("),a");
nl();
}
else
{
ot("ld\t(");
outstr(sym + NAME);
#ifdef FRAME_IX
outstr("),hl\t;static");
#else
outstr("),hl");
#endif
nl();
}
}
/*
* store the specified object type in the primary register
* at the address on the top of the stack
*/
void putstk(char typeobj)
{
gpop();
if (typeobj == CCHAR)
gcall(".pchar");
else
gcall(".pint");
}
/*
* fetch the specified object type indirect through the primary
* register into the primary register
*/
void indirect(char typeobj)
{
if (typeobj == CCHAR)
gcall(".gchar");
else
gcall(".gint");
}
/*
* swap the primary and secondary registers
*/
void swap(void)
{
ol("ex\tde,hl");
}
/*
* print partial instruction to get an immediate value into
* the primary register
*/
void immed(void)
{
ot("ld\thl,#");
}
/*
* push the primary register onto the stack
*/
void gpush(void)
{
ol("push\thl");
stkp = stkp - INTSIZE;
}
/*
* pop the top of the stack into the secondary register
*/
void gpop(void)
{
ol("pop\tde");
stkp = stkp + INTSIZE;
}
/*
* swap the primary register and the top of the stack
*/
void swapstk(void)
{
ol("ex\t(sp),hl");
}
/*
* call the specified subroutine name
*/
void gcall(char *sname)
{
ot("call\t");
outstr(sname);
nl();
}
/*
* return from subroutine
*/
void gret(void)
{
if (frameix)
ol("pop\tix");
ol("ret");
}
/*
* perform subroutine call to value on top of stack
*/
void callstk(void)
{
immed();
outstr("+5");
nl();
swapstk();
ol("jp\t(hl)");
stkp = stkp + INTSIZE;
}
/*
* jump to specified internal label number
*/
void jump(int label)
{
ot("j\t");
printlabel(label);
nl();
}
/*
* test the primary register and jump if false to label
*/
void testjump(int label, int ft)
{
ol("ld\ta,h");
ol("or\tl");
if (ft)
ot("j\tnz,");
else
ot("j\tz,");
printlabel(label);
nl();
}
/*
* print pseudo-op to define a byte
*/
void defbyte(void)
{
ot(".db\t");
}
/*
* print pseudo-op to define storage
*/
void defstorage(void)
{
ot(".ds\t");
}
/*
* print pseudo-op to define a word
*/
void defword(void)
{
ot(".dw\t");
}
/*
* modify the stack pointer to the new value indicated
*/
int modstk(int newstkp)
{
int k;
k = galign(newstkp - stkp);
if (k == 0)
return (newstkp);
if (k > 0)
{
if (k < 8)
{
if (k & 1)
{
ol("inc\tsp");
k--;
}
while (k)
{
ol("pop\tbc");
k = k - INTSIZE;
}
return (newstkp);
}
}
else
{
if (k > -8)
{
if (k & 1)
{
ol("dec\tsp");
k++;
}
while (k)
{
ol("push\tbc");
k = k + INTSIZE;
}
return (newstkp);
}
}
swap();
immed();
outdec(k);
nl();
ol("add\thl,sp");
ol("ld\tsp,hl");
swap();
return (newstkp);
}
/*
* multiply the primary register by INTSIZE
*/
void gaslint(void)
{
ol("add\thl,hl");
}
/*
* divide the primary register by INTSIZE
*/
void gasrint(void)
{
#if 1
ol("srl\th");
ol("rr\tl");
#else
gpush(); /* push primary in prep for gasr */
immed();
onum(1);
nl();
gasr(); /* divide by two */
#endif
}
/*
* Case jump instruction
*/
void gjcase(void)
{
ot("jp\t.case");
nl();
}
/*
* add the primary and secondary registers
* if lval2 is int pointer and lval is not, scale lval
*/
void gadd(int *lval, int *lval2)
{
gpop();
if (dbltest(lval2, lval))
{
swap();
gaslint();
swap();
}
ol("add\thl,de");
}
/*
* subtract the primary register from the secondary
*/
void gsub(void)
{
gpop();
gcall(".sub");
}
/*
* multiply the primary and secondary registers
* (result in primary)
*/
void gmult(void)
{
gpop();
gcall(".mul");
}
/*
* divide the secondary register by the primary
* (quotient in primary, remainder in secondary)
*/
void gdiv(void)
{
gpop();
gcall(".div");
}
/*
* compute the remainder (mod) of the secondary register
* divided by the primary register
* (remainder in primary, quotient in secondary)
*/
void gmod(void)
{
gpop();
gcall(".mod");
}
/*
* inclusive 'or' the primary and secondary registers
*/
void gor(void)
{
gpop();
gcall(".or");
}
/*
* exclusive 'or' the primary and secondary registers
*/
void gxor(void)
{
gpop();
gcall(".xor");
}
/*
* 'and' the primary and secondary registers
*/
void gand(void)
{
gpop();
gcall(".and");
}
/*
* arithmetic shift right the secondary register the number of
* times in the primary register
* (results in primary register)
*/
void gasr(void)
{
gpop();
gcall(".asr");
}
/*
* arithmetic shift left the secondary register the number of
* times in the primary register
* (results in primary register)
*/
void gasl(void)
{
gpop();
gcall(".asl");
}
/*
* two's complement of primary register
*/
void gneg(void)
{
gcall(".neg");
}
/*
* logical complement of primary register
*/
void glneg(void)
{
gcall(".lneg");
}
/*
* one's complement of primary register
*/
void gcom(void)
{
gcall(".com");
}
/*
* Convert primary value into logical value (0 if 0, 1 otherwise)
*/
void gbool(void)
{
gcall(".bool");
}
/*
* increment the primary register by 1 if char, INTSIZE if int
*/
void ginc(int lval[])
{
ol("inc\thl");
if (lval[2] == CINT)
ol("inc\thl");
}
/*
* decrement the primary register by one if char, INTSIZE if int
*/
void gdec(int lval[])
{
ol("dec\thl");
if (lval[2] == CINT)
ol("dec\thl");
}
/*
* following are the conditional operators.
* they compare the secondary register against the primary register
* and put a literl 1 in the primary if the condition is true,
* otherwise they clear the primary register
*/
/*
* equal
*/
void geq(void)
{
gpop();
gcall(".eq");
}
/*
* not equal
*/
void gne(void)
{
gpop();
gcall(".ne");
}
/*
* less than (signed)
*/
void glt(void)
{
gpop();
gcall(".lt");
}
/*
* less than or equal (signed)
*/
void gle(void)
{
gpop();
gcall(".le");
}
/*
* greater than (signed)
*/
void ggt(void)
{
gpop();
gcall(".gt");
}
/*
* greater than or equal (signed)
*/
void gge(void)
{
gpop();
gcall(".ge");
}
/*
* less than (unsigned)
*/
void gult(void)
{
gpop();
gcall(".ult");
}
/*
* less than or equal (unsigned)
*/
void gule(void)
{
gpop();
gcall(".ule");
}
/*
* greater than (unsigned)
*/
void gugt(void)
{
gpop();
gcall(".ugt");
}
/*
* greater than or equal (unsigned)
*/
void guge(void)
{
gpop();
gcall(".uge");
}
/* Squirrel away argument count in a register that modstk doesn't touch. */
void gnargs(int d)
{
ot("ld\ta,#");
onum(d);
nl();
}