kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
598 wiersze
15 KiB
C
598 wiersze
15 KiB
C
/* listing.h - listing file */
|
|
/* (c) in 2020-2021 by Volker Barthelmann and Frank Wille */
|
|
|
|
#include "vasm.h"
|
|
|
|
#define MADDR(x) ((unsigned long long)((x)&taddrmask))
|
|
#define USEDMASK (USED|EXPORT|COMMON|WEAK|LOCAL|ABSLABEL)
|
|
|
|
typedef struct {
|
|
const char *fmtname;
|
|
void (*fmtfunction)(char *,section *);
|
|
} list_formats;
|
|
|
|
int produce_listing,listena,listnosyms;
|
|
int listformfeed=1,listlinesperpage=40;
|
|
listing *first_listing,*last_listing,*cur_listing;
|
|
|
|
static int listbpl=8;
|
|
static int listnoinc,listformat,listtitlecnt,listall,listlabelsonly;
|
|
static char **listtitles;
|
|
static int *listtitlelines;
|
|
|
|
|
|
int listing_option(char *arg)
|
|
{
|
|
if (!strcmp("all",arg)) {
|
|
listall = 1;
|
|
return 1;
|
|
}
|
|
if (!strncmp("bpl=",arg,4)) {
|
|
sscanf(&arg[4],"%i",&listbpl);
|
|
if (listbpl<1 || listbpl>64) {
|
|
listbpl = 8;
|
|
general_error(78,"-Lbpl");
|
|
}
|
|
return 1;
|
|
}
|
|
if (!strncmp("fmt=",arg,4)) {
|
|
set_listformat(&arg[4]);
|
|
return 1;
|
|
}
|
|
if (!strcmp("lo",arg)) {
|
|
listlabelsonly=1;
|
|
return 1;
|
|
}
|
|
if (!strcmp("nf",arg)) {
|
|
listformfeed=0;
|
|
return 1;
|
|
}
|
|
if (!strcmp("ni",arg)) {
|
|
listnoinc=1;
|
|
return 1;
|
|
}
|
|
if (!strcmp("ns",arg)) {
|
|
listnosyms=1;
|
|
return 1;
|
|
}
|
|
if (arg[0] == 'l') {
|
|
int i=arg[1]=='='?2:1;
|
|
sscanf(&arg[i],"%i",&listlinesperpage);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
listing *new_listing(source *src,int line)
|
|
{
|
|
listing *new = mymalloc(sizeof(*new));
|
|
|
|
new->next = NULL;
|
|
new->line = line;
|
|
new->error = 0;
|
|
new->atom = 0;
|
|
new->sec = 0;
|
|
new->pc = 0;
|
|
new->src = src;
|
|
|
|
if (first_listing) {
|
|
last_listing->next = new;
|
|
last_listing = new;
|
|
}
|
|
else
|
|
first_listing = last_listing = new;
|
|
cur_listing = new;
|
|
return new;
|
|
}
|
|
|
|
void set_listing(int on)
|
|
{
|
|
listena = on && produce_listing;
|
|
}
|
|
|
|
void set_list_title(char *p,int len)
|
|
{
|
|
listtitlecnt++;
|
|
listtitles=myrealloc(listtitles,listtitlecnt*sizeof(*listtitles));
|
|
listtitles[listtitlecnt-1]=mymalloc(len+1);
|
|
strncpy(listtitles[listtitlecnt-1],p,len);
|
|
listtitles[listtitlecnt-1][len]=0;
|
|
listtitlelines=myrealloc(listtitlelines,listtitlecnt*sizeof(*listtitlelines));
|
|
listtitlelines[listtitlecnt-1]=cur_src->line;
|
|
}
|
|
|
|
static size_t get_symbols(symbol **symlist,uint32_t flags)
|
|
{
|
|
size_t cnt;
|
|
symbol *sym;
|
|
|
|
for (cnt=0,sym=first_symbol; sym; sym=sym->next) {
|
|
if ((sym->flags & VASMINTERN) || *sym->name==' ')
|
|
continue;
|
|
if (listall || sym->type!=EXPRESSION || (sym->flags & flags)) {
|
|
cnt++;
|
|
if (symlist != NULL)
|
|
*symlist++ = sym;
|
|
}
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
static int namecmp(const void *s1,const void *s2)
|
|
{
|
|
return nocase ? stricmp((*(symbol **)s1)->name,(*(symbol **)s2)->name) :
|
|
strcmp((*(symbol **)s1)->name,(*(symbol **)s2)->name);
|
|
}
|
|
|
|
static int valcmp(const void *s1,const void *s2)
|
|
{
|
|
return (int)(get_sym_value(*(symbol **)s1) - get_sym_value(*(symbol **)s2));
|
|
}
|
|
|
|
#if VASM_CPU_OIL
|
|
static void print_list_header(FILE *f,int cnt)
|
|
{
|
|
if(cnt%listlinesperpage==0){
|
|
if(cnt!=0&&listformfeed)
|
|
fprintf(f,"\f");
|
|
if(listtitlecnt>0){
|
|
int i,t;
|
|
for(i=0,t=-1;i<listtitlecnt;i++){
|
|
if(listtitlelines[i]<=cnt+listlinesperpage)
|
|
t=i;
|
|
}
|
|
if(t>=0){
|
|
int sp=(120-strlen(listtitles[t]))/2;
|
|
while(--sp)
|
|
fprintf(f," ");
|
|
fprintf(f,"%s\n",listtitles[t]);
|
|
}
|
|
cnt++;
|
|
}
|
|
fprintf(f,"Err Line Loc. S Object1 Object2 M Source\n");
|
|
}
|
|
}
|
|
|
|
static void write_listing_old(char *listname,section *first_section)
|
|
{
|
|
FILE *f;
|
|
int nsecs,i,cnt=0,nl;
|
|
section *secp;
|
|
listing *p;
|
|
atom *a;
|
|
symbol *sym;
|
|
taddr pc;
|
|
char rel;
|
|
|
|
if(!(f=fopen(listname,"w"))){
|
|
general_error(13,listname);
|
|
return;
|
|
}
|
|
for(nsecs=0,secp=first_section;secp;secp=secp->next)
|
|
secp->idx=nsecs++;
|
|
for(p=first_listing;p;p=p->next){
|
|
if(!p->src||p->src->id!=0)
|
|
continue;
|
|
print_list_header(f,cnt++);
|
|
if(p->error!=0)
|
|
fprintf(f,"%04d ",p->error);
|
|
else
|
|
fprintf(f," ");
|
|
fprintf(f,"%4d ",p->line);
|
|
a=p->atom;
|
|
while(a&&a->type!=DATA&&a->next&&a->next->line==a->line&&a->next->src==a->src)
|
|
a=a->next;
|
|
if(a&&a->type==DATA){
|
|
int size=a->content.db->size;
|
|
char *dp=a->content.db->data;
|
|
pc=p->pc;
|
|
fprintf(f,"%05lX %d ",(unsigned long)pc,(int)(p->sec?p->sec->idx:0));
|
|
for(i=0;i<8;i++){
|
|
if(i==4)
|
|
fprintf(f," ");
|
|
if(i<size){
|
|
fprintf(f,"%02X",(unsigned char)*dp++);
|
|
pc++;
|
|
}else
|
|
fprintf(f," ");
|
|
/* append following atoms with align 1 directly */
|
|
if(i==size-1&&i<7&&a->next&&a->next->align<=a->align&&a->next->type==DATA&&a->next->line==a->line&&a->next->src==a->src){
|
|
a=a->next;
|
|
size+=a->content.db->size;
|
|
dp=a->content.db->data;
|
|
}
|
|
}
|
|
fprintf(f," ");
|
|
if(a->content.db->relocs){
|
|
symbol *s=((nreloc *)(a->content.db->relocs->reloc))->sym;
|
|
if(s->type==IMPORT)
|
|
rel='X';
|
|
else
|
|
rel='0'+p->sec->idx;
|
|
}else
|
|
rel='A';
|
|
fprintf(f,"%c ",rel);
|
|
}else
|
|
fprintf(f," ");
|
|
|
|
fprintf(f," %-.77s",p->txt);
|
|
|
|
/* bei laengeren Daten den Rest ueberspringen */
|
|
/* Block entfernen, wenn alles ausgegeben werden soll */
|
|
if(a&&a->type==DATA&&i<a->content.db->size){
|
|
pc+=a->content.db->size-i;
|
|
i=a->content.db->size;
|
|
}
|
|
|
|
/* restliche DATA-Zeilen, wenn noetig */
|
|
while(a){
|
|
if(a->type==DATA){
|
|
int size=a->content.db->size;
|
|
char *dp=a->content.db->data+i;
|
|
|
|
if(i<size){
|
|
for(;i<size;i++){
|
|
if((i&7)==0){
|
|
fprintf(f,"\n");
|
|
print_list_header(f,cnt++);
|
|
fprintf(f," %05lX %d ",(unsigned long)pc,(int)(p->sec?p->sec->idx:0));
|
|
}else if((i&3)==0)
|
|
fprintf(f," ");
|
|
fprintf(f,"%02X",(unsigned char)*dp++);
|
|
pc++;
|
|
/* append following atoms with align 1 directly */
|
|
if(i==size-1&&a->next&&a->next->align<=a->align&&a->next->type==DATA&&a->next->line==a->line&&a->next->src==a->src){
|
|
a=a->next;
|
|
size+=a->content.db->size;
|
|
dp=a->content.db->data;
|
|
}
|
|
}
|
|
i=8-(i&7);
|
|
if(i>=4)
|
|
fprintf(f," ");
|
|
while(i--){
|
|
fprintf(f," ");
|
|
}
|
|
fprintf(f," %c",rel);
|
|
}
|
|
i=0;
|
|
}
|
|
if(a->next&&a->next->line==a->line&&a->next->src==a->src){
|
|
a=a->next;
|
|
pc=pcalign(a,pc);
|
|
if(a->type==DATA&&a->content.db->relocs){
|
|
symbol *s=((nreloc *)(a->content.db->relocs->reloc))->sym;
|
|
if(s->type==IMPORT)
|
|
rel='X';
|
|
else
|
|
rel='0'+p->sec->idx;
|
|
}else
|
|
rel='A';
|
|
}else
|
|
a=0;
|
|
}
|
|
fprintf(f,"\n");
|
|
}
|
|
fprintf(f,"\n\nSections:\n");
|
|
for(secp=first_section;secp;secp=secp->next)
|
|
fprintf(f,"%d %s\n",(int)secp->idx,secp->name);
|
|
if(!listnosyms){
|
|
fprintf(f,"\n\nSymbols:\n");
|
|
{
|
|
symbol *last=0,*cur,*symo;
|
|
for(symo=first_symbol;symo;symo=symo->next){
|
|
cur=0;
|
|
for(sym=first_symbol;sym;sym=sym->next){
|
|
if(!last||stricmp(sym->name,last->name)>0)
|
|
if(!cur||stricmp(sym->name,cur->name)<0)
|
|
cur=sym;
|
|
}
|
|
if(cur){
|
|
print_symbol(f,cur);
|
|
fprintf(f,"\n");
|
|
last=cur;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(errors==0)
|
|
fprintf(f,"\nThere have been no errors.\n");
|
|
else
|
|
fprintf(f,"\nThere have been %d errors!\n",errors);
|
|
fclose(f);
|
|
for(p=first_listing;p;){
|
|
listing *m=p->next;
|
|
myfree(p);
|
|
p=m;
|
|
}
|
|
}
|
|
#else
|
|
static void write_listing_old(char *listname,section *first_section)
|
|
{
|
|
unsigned long i,maxsrc=0;
|
|
FILE *f;
|
|
int nsecs;
|
|
section *secp;
|
|
listing *p;
|
|
atom *a;
|
|
symbol *sym;
|
|
taddr pc;
|
|
|
|
if(!(f=fopen(listname,"w"))){
|
|
general_error(13,listname);
|
|
return;
|
|
}
|
|
for(nsecs=1,secp=first_section;secp;secp=secp->next)
|
|
secp->idx=nsecs++;
|
|
for(p=first_listing;p;p=p->next){
|
|
char err[6];
|
|
if(p->error!=0)
|
|
sprintf(err,"E%04d",p->error);
|
|
else
|
|
sprintf(err," ");
|
|
if(p->src&&p->src->id>maxsrc)
|
|
maxsrc=p->src->id;
|
|
fprintf(f,"F%02d:%04d %s %s",(int)(p->src?p->src->id:0),p->line,err,p->txt);
|
|
a=p->atom;
|
|
pc=p->pc;
|
|
while(a){
|
|
if(a->type==DATA){
|
|
unsigned long size=a->content.db->size;
|
|
for(i=0;i<size&&i<32;i++){
|
|
if((i&15)==0)
|
|
fprintf(f,"\n S%02d:%08lX: ",(int)(p->sec?p->sec->idx:0),(unsigned long)(pc));
|
|
fprintf(f," %02X",(unsigned char)a->content.db->data[i]);
|
|
pc++;
|
|
}
|
|
if(a->content.db->relocs)
|
|
fprintf(f," [R]");
|
|
}
|
|
if(a->next&&a->next->list==a->list){
|
|
a=a->next;
|
|
pc=pcalign(a,pc);
|
|
}else
|
|
a=0;
|
|
}
|
|
fprintf(f,"\n");
|
|
}
|
|
fprintf(f,"\n\nSections:\n");
|
|
for(secp=first_section;secp;secp=secp->next)
|
|
fprintf(f,"S%02d %s\n",(int)secp->idx,secp->name);
|
|
fprintf(f,"\n\nSources:\n");
|
|
for(i=0;i<=maxsrc;i++){
|
|
for(p=first_listing;p;p=p->next){
|
|
if(p->src&&p->src->id==i){
|
|
fprintf(f,"F%02lu %s\n",i,p->src->name);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
fprintf(f,"\n\nSymbols:\n");
|
|
for(sym=first_symbol;sym;sym=sym->next){
|
|
print_symbol(f,sym);
|
|
fprintf(f,"\n");
|
|
}
|
|
if(errors==0)
|
|
fprintf(f,"\nThere have been no errors.\n");
|
|
else
|
|
fprintf(f,"\nThere have been %d errors!\n",errors);
|
|
fclose(f);
|
|
for(p=first_listing;p;){
|
|
listing *m=p->next;
|
|
myfree(p);
|
|
p=m;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void write_listing_wide(char *listname,section *first_section)
|
|
{
|
|
int addrw = bytespertaddr*2; /* width of address field */
|
|
source *lastsrc = NULL;
|
|
FILE *f;
|
|
section *secp;
|
|
listing *l;
|
|
int i;
|
|
|
|
if (!(f = fopen(listname,"w"))) {
|
|
general_error(13,listname);
|
|
return;
|
|
}
|
|
|
|
fprintf(f,"Sections:\n");
|
|
for (secp=first_section,i=0; secp; secp=secp->next,i++) {
|
|
secp->idx = i;
|
|
fprintf(f,"%02X: \"%s\" (%llX-%llX)\n",(unsigned)i,secp->name,
|
|
MADDR(secp->org),MADDR(secp->pc));
|
|
}
|
|
fputc('\n',f);
|
|
|
|
for (l=first_listing; l; l=l->next) {
|
|
atom *a = l->atom;
|
|
taddr pc = l->pc;
|
|
int flag = 0;
|
|
char stype = ':';
|
|
size_t spc;
|
|
|
|
if (l->src) {
|
|
if (l->src->num_params >= 0)
|
|
stype = 'M';
|
|
else if (!strncmp(l->src->name,"REPEAT:",7))
|
|
stype = 'R';
|
|
else {
|
|
if (listnoinc && l->src->parent!=NULL)
|
|
continue;
|
|
if (l->src != lastsrc) {
|
|
fprintf(f,"\nSource: \"%s\"\n",l->src->name);
|
|
lastsrc = l->src;
|
|
}
|
|
}
|
|
}
|
|
i = 0;
|
|
|
|
while (a) {
|
|
size_t dlen;
|
|
|
|
spc = 0;
|
|
if (a->type == DATA) {
|
|
dlen = a->content.db->size;
|
|
for (; i<dlen; i++,pc++) {
|
|
if (!(i % listbpl)) {
|
|
if (i) {
|
|
if (!flag) {
|
|
fprintf(f,"\t%6d%c %s\n",l->line,stype,l->txt);
|
|
flag = 1;
|
|
}
|
|
else
|
|
fputc('\n',f);
|
|
}
|
|
fprintf(f,"%02X:%0*llX ",
|
|
(unsigned)(l->sec?l->sec->idx:0),
|
|
addrw,MADDR(pc));
|
|
}
|
|
fprintf(f,"%02X",(unsigned)a->content.db->data[i]);
|
|
}
|
|
}
|
|
else if (a->type == SPACE) {
|
|
dlen = a->content.sb->size;
|
|
if (spc = a->content.sb->space * dlen) {
|
|
for (; i<dlen; i++,pc++) {
|
|
if (!(i % listbpl)) {
|
|
if (i) {
|
|
if (!flag) {
|
|
fprintf(f,"\t%6d%c %s\n",l->line,stype,l->txt);
|
|
flag = 1;
|
|
}
|
|
else
|
|
fputc('\n',f);
|
|
}
|
|
fprintf(f,"%02X:%0*llX ",
|
|
(unsigned)(l->sec?l->sec->idx:0),
|
|
addrw,MADDR(pc));
|
|
}
|
|
fprintf(f,"%02X",(unsigned)a->content.sb->fill[i]);
|
|
}
|
|
spc -= dlen;
|
|
}
|
|
}
|
|
if (i) {
|
|
if (!flag) {
|
|
fprintf(f,"%*c%6d%c %s",2*(listbpl-i)+1,'\t',l->line,stype,l->txt);
|
|
if (spc) {
|
|
fprintf(f,"\n%02X:%0*llX *",
|
|
(unsigned)(l->sec?l->sec->idx:0),
|
|
addrw,MADDR(pc));
|
|
pc += spc;
|
|
}
|
|
flag = 1;
|
|
}
|
|
fputc('\n',f);
|
|
i = 0;
|
|
}
|
|
|
|
if (a->next!=NULL && a->next->list==a->list) {
|
|
a = a->next;
|
|
pc = pcalign(a,pc);
|
|
}
|
|
else
|
|
a = NULL;
|
|
}
|
|
if (!flag) /* no data generated for this source line */
|
|
fprintf(f,"%*c%6d%c %s\n",4+addrw+2*listbpl+1,'\t',l->line,stype,l->txt);
|
|
if (l->error)
|
|
fprintf(f,"%*c ^-ERROR:%04d\n",4+addrw+2*listbpl+1,'\t',l->error);
|
|
}
|
|
|
|
if (!listnosyms) {
|
|
size_t nsyms = get_symbols(NULL,USEDMASK);
|
|
symbol *sym,**symlist;
|
|
|
|
fprintf(f,"\n\nSymbols by name:\n");
|
|
symlist = (symbol **)mymalloc(nsyms*sizeof(symbol *));
|
|
get_symbols(symlist,USEDMASK);
|
|
qsort(symlist,nsyms,sizeof(symbol *),namecmp); /* sort by name */
|
|
for (i=0; i<nsyms; i++) {
|
|
sym = symlist[i];
|
|
fprintf(f,"%-31.31s ",sym->name);
|
|
if (sym->flags & COMMON) {
|
|
fprintf(f,"COM %lld bytes, alignment %lld",
|
|
(long long)get_sym_size(sym),(long long)sym->align);
|
|
}
|
|
else {
|
|
char type;
|
|
|
|
switch (sym->type) {
|
|
case LABSYM:
|
|
fprintf(f,"%02X:%0*llX",
|
|
(unsigned)(sym->sec?sym->sec->idx:0),
|
|
addrw,MADDR(sym->pc));
|
|
break;
|
|
case IMPORT:
|
|
fprintf(f,"external");
|
|
break;
|
|
default:
|
|
if (sym->flags & EQUATE)
|
|
type = 'E';
|
|
else if (sym->flags & REGLIST)
|
|
type = 'R';
|
|
else if (sym->flags & ABSLABEL)
|
|
type = 'A';
|
|
else
|
|
type = 'S';
|
|
fprintf(f," %c:%0*llX",
|
|
type,addrw,MADDR(get_sym_value(sym)));
|
|
}
|
|
}
|
|
if (sym->flags & EXPORT)
|
|
fprintf(f," EXP");
|
|
if (sym->flags & LOCAL)
|
|
fprintf(f," LOC");
|
|
if (sym->flags & WEAK)
|
|
fprintf(f," WEAK");
|
|
fputc('\n',f);
|
|
}
|
|
|
|
if (listlabelsonly)
|
|
fprintf(f,"\nLabels by address:\n");
|
|
else
|
|
fprintf(f,"\nSymbols by value:\n");
|
|
qsort(symlist,nsyms,sizeof(symbol *),valcmp); /* sort by value/address */
|
|
for (i=0; i<nsyms; i++) {
|
|
sym = symlist[i];
|
|
if (sym->type==IMPORT || (sym->flags & (COMMON|REGLIST)))
|
|
continue;
|
|
if (listlabelsonly) {
|
|
if (sym->type!=LABSYM &&
|
|
(sym->type!=EXPRESSION || !(sym->flags & ABSLABEL)))
|
|
continue;
|
|
}
|
|
fprintf(f,"%0*llX %s\n",addrw,MADDR(get_sym_value(sym)),sym->name);
|
|
}
|
|
|
|
myfree(symlist);
|
|
}
|
|
}
|
|
|
|
static list_formats list_format_table[] = {
|
|
{ "wide", write_listing_wide },
|
|
{ "old", write_listing_old }
|
|
};
|
|
|
|
void set_listformat(const char *fmtname)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<sizeof(list_format_table)/sizeof(list_format_table[0]); i++) {
|
|
if (!stricmp(fmtname,list_format_table[i].fmtname)) {
|
|
listformat = i;
|
|
return;
|
|
}
|
|
}
|
|
general_error(80,fmtname); /* format selection ignored */
|
|
}
|
|
|
|
void write_listing(char *listname,section *first_section)
|
|
{
|
|
list_format_table[listformat].fmtfunction(listname,first_section);
|
|
}
|