|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 6998 (0x1b56)
Types: TextFile
Notes: UNIX file
Names: »asmout.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/as/z8001/asmout.c«
/*
* Output routines.
* 16 bit.
* Non segmented.
*/
#include "asm.h"
#include <canon.h>
#define NTXT 128
#define NREL 128
#define outlst(b) { if (cp < &cb[NCODE]) *cp++ = (b); }
address txtla;
long crbase;
long crseek;
struct ldheader ldh;
struct loc *txtlp;
char txt[NTXT];
char rel[NREL];
char *txtp = { txt };
char *relp = { rel };
outab(b)
{
if (pass == 2) {
if (inbss)
err('s');
else {
outlst(b);
outchk(1, 0);
*txtp++ = b;
}
}
++dot->s_addr;
}
outaw(w)
{
if (pass == 2) {
if (inbss)
err('s');
else {
outlst(fbyte(w));
outlst(sbyte(w));
outchk(2, 0);
*txtp++ = fbyte(w);
*txtp++ = sbyte(w);
}
}
dot->s_addr += 2;
}
outal(l)
long l;
{
if (pass==2) {
if (inbss)
err('s');
else {
outlst(fbyte(fword(l)));
outlst(sbyte(fword(l)));
outlst(fbyte(sword(l)));
outlst(sbyte(sword(l)));
outchk(4, 0);
*txtp++ = fbyte(fword(l));
*txtp++ = sbyte(fword(l));
*txtp++ = fbyte(sword(l));
*txtp++ = sbyte(sword(l));
}
}
dot->s_addr += 4;
}
outrb(esp, pcrf)
register struct expr *esp;
{
register address a;
register n;
int t;
if (pass == 2) {
if (inbss)
err('s');
else {
t = esp->e_type;
if (t==E_AREG || t==E_ASEG)
t = E_ACON;
if (t == E_SEG)
t = E_SYM;
a = esp->e_addr;
if (pcrf)
a -= dot->s_addr+1;
outlst(a);
if (t == E_ACON) {
n = 0;
if (pcrf)
n = 5;
outchk(1, n);
*txtp++ = a;
if (pcrf)
outrel(LR_BYTE|LR_PCR|L_ABS,
dot->s_addr);
} else {
n = 5;
if (t == E_SYM)
n = 7;
outchk(1, n);
*txtp++ = a;
n = LR_BYTE;
if (pcrf)
n |= LR_PCR;
if (t == E_SYM)
n |= L_SYM;
else
n |= esp->e_base.e_lp->l_seg;
outrel(n, dot->s_addr);
if (t == E_SYM) {
n = esp->e_base.e_sp->s_ref;
*relp++ = sbyte(n);
*relp++ = fbyte(n);
}
}
}
}
++dot->s_addr;
}
outrw(esp, pcrf)
register struct expr *esp;
{
register address a;
register n;
int t;
if (pass == 2) {
if (inbss)
err('s');
else {
t = esp->e_type;
if (t==E_AREG || t==E_ASEG)
t = E_ACON;
if (t == E_SEG)
t = E_SYM;
a = esp->e_addr;
if (pcrf)
a -= dot->s_addr+2;
outlst(fbyte(a));
outlst(sbyte(a));
if (t == E_ACON) {
n = 0;
if (pcrf)
n = 5;
outchk(2, n);
*txtp++ = fbyte(a);
*txtp++ = sbyte(a);
if (pcrf)
outrel(LR_WORD|LR_PCR|L_ABS,
dot->s_addr);
} else {
n = 3;
if (t == E_SYM)
n = 5;
outchk(2, n);
*txtp++ = fbyte(a);
*txtp++ = sbyte(a);
n = LR_WORD;
if (pcrf)
n |= LR_PCR;
if (t == E_SYM)
n |= L_SYM;
else
n |= esp->e_base.e_lp->l_seg;
outrel(n, dot->s_addr);
if (t == E_SYM) {
n = esp->e_base.e_sp->s_ref;
*relp++ = sbyte(n);
*relp++ = fbyte(n);
}
}
}
}
dot->s_addr += 2;
}
/*
* Output a relocatable long.
* Bits should be 0x80 if long segment form
* much be generated, 0x00 otherwise.
*/
outrl(esp, pcrf, bits)
register struct expr *esp;
int pcrf, bits;
{
register address a;
register n;
int t;
if (pass == 2) {
if (inbss)
err('s');
else {
t = esp->e_type;
if (t==E_AREG || t==E_ASEG)
t = E_ACON;
if (t == E_SEG)
t = E_SYM;
a = esp->e_addr;
if (pcrf)
a -= dot->s_addr+2;
a += (long)bits<<24;
outlst(fbyte(fword(a)));
outlst(sbyte(fword(a)));
outlst(fbyte(sword(a)));
outlst(sbyte(sword(a)));
if (t == E_ACON) {
n = 0;
if (pcrf)
n = 5;
outchk(2, n);
*txtp++ = fbyte(fword(a));
*txtp++ = sbyte(fword(a));
*txtp++ = fbyte(sword(a));
*txtp++ = sbyte(sword(a));
if (pcrf)
outrel(LR_LONG|LR_PCR|L_ABS,
dot->s_addr);
} else {
n = 3;
if (t == E_SYM)
n = 5;
outchk(2, n);
*txtp++ = fbyte(fword(a));
*txtp++ = sbyte(fword(a));
*txtp++ = fbyte(sword(a));
*txtp++ = sbyte(sword(a));
n = LR_LONG;
if (pcrf)
n |= LR_PCR;
if (t == E_SYM)
n |= L_SYM;
else
n |= esp->e_base.e_lp->l_seg;
outrel(n, dot->s_addr);
if (t == E_SYM) {
n = esp->e_base.e_sp->s_ref;
*relp++ = sbyte(n);
*relp++ = fbyte(n);
}
}
}
}
dot->s_addr += 4;
}
/*
* Make sure there is room in
* the buffers for `nt' bytes worth
* text and `nr' bytes of rel.
* If not, write the buffers out
* to the file.
*/
outchk(nt, nr)
{
register unsigned n;
register tn;
long ts;
if (txtp+nt>&txt[NTXT] || relp+nr>&rel[NREL]) {
if ((n = txtp-txt) != 0) {
ts = txtla + sizeof(ldh);
tn = txtlp->l_seg;
if (tn > L_BSSI) {
ts -= ldh.l_ssize[L_BSSI];
if (tn > L_BSSD)
ts -= ldh.l_ssize[L_BSSD];
}
fseek(ofp, ts, 0);
xwrite(txt, sizeof(char), n);
if ((n = relp-rel) != 0) {
fseek(ofp, crseek, 0);
xwrite(rel, sizeof(char), n);
crseek += n;
relp = rel;
}
}
txtp = txt;
}
if (txtp == txt) {
txtla = dot->s_addr;
txtlp = dot->s_base.s_lp;
}
}
/*
* Output a relocation record.
*/
outrel(op, addr)
int op;
address addr;
{
*relp++ = op;
*relp++ = sbyte(fword(addr));
*relp++ = fbyte(fword(addr));
*relp++ = sbyte(sword(addr));
*relp++ = fbyte(sword(addr));
}
outinit()
{
register struct loc *lp;
register struct sym *sp;
register i;
struct ldsym lds;
int rn;
long sb, ss;
ldh.l_magic = L_MAGIC;
#if LADDR
ldh.l_flag = LF_32;
ldh.l_tbase = sizeof(ldh);
#else
ldh.l_flag = 0;
#endif
ldh.l_machine = M_MACHINE;
ldh.l_entry = 0;
sb = sizeof(ldh);
for (i=0; i<nloc; ++i) {
ss = 0;
lp = loc[i];
while (lp != NULL) {
ss += locrup(lp->l_break);
lp = lp->l_lp;
}
ldh.l_ssize[i] = ss;
if (i!=L_BSSI && i!=L_BSSD)
sb += ss;
}
fseek(ofp, sb, 0);
ss = 0;
rn = 0;
for (i=0; i<NHASH; ++i) {
sp = symhash[i];
while (sp != NULL) {
if ((sp->s_flag&S_SYMT) != 0
&& (xflag == 0
|| (sp->s_flag&S_GBL) != 0
|| sp->s_id[0] != 'L')) {
sp->s_ref = rn++;
symcopy(lds.ls_id, sp->s_id);
if (sp->s_kind == S_NEW)
lds.ls_type = L_REF;
else if (sp->s_type != E_DIR)
lds.ls_type = L_ABS;
else
lds.ls_type = sp->s_base.s_lp->l_seg;
if ((sp->s_flag&S_GBL) != 0)
lds.ls_type |= L_GLOBAL;
lds.ls_addr = sp->s_addr;
canint(lds.ls_type);
#if LADDR
canlong(lds.ls_addr);
#else
canvaddr(lds.ls_addr);
#endif
xwrite(&lds, sizeof(lds), 1);
ss += sizeof(lds);
}
sp = sp->s_sp;
}
}
ldh.l_ssize[L_SYM] = ss;
crseek = sb+ss;
crbase = crseek;
}
/*
* Finish up l.out
*/
outfinish()
{
int i;
ldh.l_ssize[L_REL] = crseek-crbase;
canshort(ldh.l_magic);
canshort(ldh.l_flag);
canshort(ldh.l_machine);
#if LADDR
canshort(ldh.l_tbase);
canlong(ldh.l_entry);
#else
canvaddr(ldh.l_entry);
#endif
for (i=0; i<NLSEG; i++)
cansize(ldh.l_ssize[i]);
fseek(ofp, (long)0, 0);
xwrite(&ldh, sizeof(ldh), 1);
fclose(ofp);
}
/*
* Write code file.
* Check for any errors.
*/
xwrite(p, s, n)
char *p;
{
if (fwrite(p, s, n, ofp) != n) {
fprintf(stderr, "%s: I/O error.\n", ofn);
exit(1);
}
}