6502/vasm/output_vobj.c

294 lines
6.1 KiB
C

/* output_vasm.c vobj format output driver for vasm */
/* (c) in 2002-2018 by Volker Barthelmann */
#include "vasm.h"
#ifdef OUTVOBJ
static char *copyright="vasm vobj output module 0.9b (c) 2002-2018 Volker Barthelmann";
/*
Format (WILL CHANGE!):
.byte 0x56,0x4f,0x42,0x4a
.byte flags
1: BIGENDIAN
2: LITTLENDIAN
.number bitsperbyte
.number bytespertaddr
.string cpu
.number nsections [1-based]
.number nsymbols [1-based]
nsymbols
.string name
.number type
.number flags
.number secindex
.number val
.number size
nsections
.string name
.string attr
.number flags
.number align
.number size
.number nrelocs
.number databytes
.byte[databytes]
nrelocs [standard|special]
standard
.number type
.number byteoffset
.number bitoffset
.number size
.number mask
.number addend
.number symbolindex | 0 (sectionbase)
special
.number type
.number size
.byte[size]
.number:[taddr]
.byte 0--127 [0--127]
.byte 128-255 [x-0x80 bytes little-endian]
*/
static void write_number(FILE *f,taddr val)
{
int i;
if(val>=0&&val<=127){
fw8(f,val);
return;
}
fw8(f,0x80+bytespertaddr);
for(i=bytespertaddr;i>0;i--){
fw8(f,val&0xff);
val>>=8;
}
}
static int size_number(taddr val)
{
if(val>=0&&val<=127)
return 1;
else
return bytespertaddr+1;
}
static void write_string(FILE *f,char *p)
{
while(p&&*p){
fw8(f,*p);
p++;
}
fw8(f,0);
}
static int sym_valid(symbol *symp)
{
if(*symp->name==' ')
return 0; /* ignore internal/temporary symbols */
if(symp->flags & VASMINTERN)
return 0; /* ignore vasm-internal symbols */
return 1;
}
static int count_relocs(rlist *rl)
{
int nrelocs;
for(nrelocs=0; rl; rl=rl->next) {
if(rl->type>=FIRST_STANDARD_RELOC && rl->type<=LAST_STANDARD_RELOC) {
nreloc *r = (nreloc *)rl->reloc;
if (r->sym->type==IMPORT&&!sym_valid(r->sym))
unsupp_reloc_error(rl);
else
nrelocs++;
}
else
unsupp_reloc_error(rl);
}
return nrelocs;
}
static void get_section_sizes(section *sec,taddr *rsize,taddr *rdata,taddr *rnrelocs)
{
taddr data=0,nrelocs=0;
atom *p;
rlist *rl;
int i;
sec->pc=0;
for(p=sec->first;p;p=p->next){
sec->pc=pcalign(p,sec->pc);
sec->pc+=atom_size(p,sec,sec->pc);
if(p->type==DATA){
data=sec->pc;
nrelocs+=count_relocs(p->content.db->relocs);
}
else if(p->type==SPACE){
if(p->content.sb->relocs){
nrelocs+=count_relocs(p->content.sb->relocs);
data=sec->pc;
}else{
for(i=0;i<p->content.sb->size;i++)
if(p->content.sb->fill[i]!=0)
data=sec->pc;
}
}
}
*rdata=data;
*rsize=sec->pc;
*rnrelocs=nrelocs;
}
static void write_data(FILE *f,section *sec,taddr data)
{
atom *p;
sec->pc=0;
for(p=sec->first;p;p=p->next){
if(sec->pc>=data)
return;
sec->pc=fwpcalign(f,p,sec,sec->pc);
sec->pc+=atom_size(p,sec,sec->pc);
if(p->type==DATA)
fwdata(f,p->content.db->data,p->content.db->size);
else if(p->type==SPACE)
fwsblock(f,p->content.sb);
}
}
static void write_rlist(FILE *f,section *sec,rlist *rl)
{
int idx;
for(;rl;rl=rl->next){
if(rl->type>=FIRST_STANDARD_RELOC&&rl->type<=LAST_STANDARD_RELOC){
nreloc *rel=rl->reloc;
if(!(idx=rel->sym->idx)){
if(rel->sym->type==IMPORT&&!sym_valid(rel->sym))
continue;
idx=rel->sym->sec->idx; /* symbol does not exist, use section-symbol */
}
write_number(f,rl->type);
write_number(f,sec->pc+rel->byteoffset);
write_number(f,rel->bitoffset);
write_number(f,rel->size);
write_number(f,rel->mask);
write_number(f,rel->addend);
write_number(f,idx);
}
}
}
static void write_relocs(FILE *f,section *sec)
{
atom *p;
rlist *rl;
sec->pc=0;
for(p=sec->first;p;p=p->next){
sec->pc=pcalign(p,sec->pc);
if(p->type==DATA)
write_rlist(f,sec,p->content.db->relocs);
else if(p->type==SPACE)
write_rlist(f,sec,p->content.sb->relocs);
sec->pc+=atom_size(p,sec,sec->pc);
}
}
static void write_output(FILE *f,section *sec,symbol *sym)
{
int nsyms,nsecs;
section *secp;
symbol *symp,*first,*last;
taddr size,data,nrelocs;
/* assign section index, make section symbols */
for(nsecs=1,secp=sec,first=sym,last=NULL;secp;secp=secp->next){
secp->idx=nsecs++; /* symp->idx will become equal to secp->idx */
symp=mymalloc(sizeof(*symp));
symp->name=secp->name;
symp->type=LABSYM;
symp->flags=TYPE_SECTION;
symp->sec=secp;
symp->pc=0;
symp->expr=symp->size=NULL;
symp->align=0;
symp->next=sym;
if(last!=NULL)
last->next=symp;
else
first=symp;
last=symp;
}
/* assign symbol index to all symbols */
for(nsyms=1,symp=first;symp;symp=symp->next){
if(sym_valid(symp))
symp->idx=nsyms++;
else
symp->idx=0; /* use section-symbol, when needed */
}
fw32(f,0x564f424a,1); /* "VOBJ" */
if(BIGENDIAN)
fw8(f,1);
else if(LITTLEENDIAN)
fw8(f,2);
else
ierror(0);
write_number(f,bitsperbyte);
write_number(f,bytespertaddr);
write_string(f,cpuname);
write_number(f,nsecs-1);
write_number(f,nsyms-1);
for(symp=first;symp;symp=symp->next){
if(!sym_valid(symp))
continue;
write_string(f,symp->name);
write_number(f,symp->type);
write_number(f,symp->flags);
write_number(f,symp->sec?symp->sec->idx:0);
write_number(f,get_sym_value(symp));
write_number(f,get_sym_size(symp));
}
for(secp=sec;secp;secp=secp->next){
write_string(f,secp->name);
write_string(f,secp->attr);
write_number(f,secp->flags);
write_number(f,secp->align);
get_section_sizes(secp,&size,&data,&nrelocs);
write_number(f,size);
write_number(f,nrelocs);
write_number(f,data);
write_data(f,secp,data);
write_relocs(f,secp);
}
}
static int output_args(char *p)
{
return 0;
}
int init_output_vobj(char **cp,void (**wo)(FILE *,section *,symbol *),int (**oa)(char *))
{
*cp=copyright;
*wo=write_output;
*oa=output_args;
return 1;
}
#else
int init_output_vobj(char **cp,void (**wo)(FILE *,section *,symbol *),int (**oa)(char *))
{
return 0;
}
#endif