/* lkaomf51.c - Create an absolute object memory format 51 file
Copyright (C) 2002 Jesus Calvino-Fraga, jesusc at ieee dot org
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include
#include
#include
#include
#include "aslink.h"
#define EQ(A,B) !strcmp((A),(B))
#define MEMSIZE 0x1000000
#ifndef DODUMP
#define DODUMP 0
#endif
typedef struct
{
char PathName[PATH_MAX];
char ModuleName[PATH_MAX];
} _infn;
int numin=0;
_infn * infn=NULL;
typedef struct
{
char name[0x100];
int FileNameNumber;
int Procedure;//If the symbol belongs to a function
int Static; //If the symbol is only public on its file
int Address;
int UsageType;
} _symbol;
int numsym=0;
_symbol * symbol=NULL;
typedef struct
{
char name[0x100];
int FileNameNumber;
int BeginAdd;
int EndAdd;
int RegBank;
} _procedure;
int numproc=0;
_procedure * procedure=NULL;
typedef struct
{
int Number;
int Address;
int Procedure;
int FileNameNumber;
} _linenum;
int numlinenum=0;
_linenum * linenum=NULL;
#if 0
typedef struct
{
char * name;
int usage;
}
_UsageType;
_UsageType UsageType[]=
{
{"CSEG", 0},
{"GSINIT", 0},
{"GSINIT0", 0},
{"GSINIT1", 0},
{"GSINIT2", 0},
{"GSINIT3", 0},
{"GSINIT4", 0},
{"GSINIT5", 0},
{"GSFINAL", 0},
{"HOME", 0},
{"XINIT", 0},
{"XSEG", 1},
{"XISEG", 1},
{"REG_BANK_0", 2},
{"REG_BANK_1", 2},
{"REG_BANK_2", 2},
{"REG_BANK_3", 2},
{"DSEG", 2},
{"OSEG", 2},
{"SSEG", 2},
{"ISEG", 3},
{"BSEG", 4},
{"", 5} /*A typeless number?*/
};
#endif
char * UsageTypeName[]={"CODE", "XDATA", "DATA", "IDATA", "BIT", "NUMBER"};
int AddNumber;
short * ihxBuff=NULL;
FILE * aomf51out;
int GlobalChkSum=0;
int HexSize, HexBegin=0x1000000;
int GetName(char * filepath, char * name)
{
int j, k;
for(j=strlen(filepath); j>0; j--)
if( (filepath[j-1]=='/')||(filepath[j-1]=='\\') ) break;
for(k=0; (filepath[j]!=0)&&(filepath[j]!='.'); j++, k++)
name[k]=filepath[j];
name[k]=0;
return j;
}
void SaveLinkedFilePath(char * filepath)
{
int j;
if((yflag) && (!rflag))
{
int ext;
infn = realloc(infn, sizeof(_infn)*(numin+1));
/*Get the module name=filename, no drive, no dir, no ext*/
ext = GetName(filepath, infn[numin].ModuleName);
//printf("%s, %s\n", infn[numin].PathName, infn[numin].ModuleName);
strcpy(infn[numin].PathName, filepath);
/*If there is an extension remove it*/
if (infn[numin].PathName[ext] == '.')
infn[numin].PathName[ext] = '\0';
/*Check if this filename is already in*/
for (j=0; j=0)?procedure[symbol[j].Procedure].name:"GLOBAL",
symbol[j].Address,
k<6?UsageTypeName[k]:"???");
}
fprintf(DumpFile,"\nPROCEDURES:\n");
for(j=0; j %s\n",
linenum[j].Number,
linenum[j].Address,
infn[linenum[j].FileNameNumber].PathName,
(linenum[j].Procedure>=0)?procedure[linenum[j].Procedure].name:"I don't know");
}
fclose(DumpFile);
}
void ParseRegisters(_symbol * symbol, const char * Registers)
{
char c;
int i;
char regs[0x100][4];
int address[4];
int nRegs = sscanf(Registers, "[ %[^,] %c %[^,] %c %[^,] %c %[^,] ]",
regs[0], &c, regs[1], &c, regs[2], &c, regs[3]);
nRegs = (nRegs + 1) / 2;
for (i=0; iProcedure && symbol->Procedure < numproc)
symbol->Address = address[0] + procedure[symbol->Procedure].RegBank * 8;
}
void OutputAOEMF51(void)
{
int i, j, k, recsize;
char MHRname[0x100], Mname[0x100];
char aomf51FileName[PATH_MAX];
strcpy(aomf51FileName, infn[0].PathName);
strcat(aomf51FileName, ".omf");
aomf51out=fopen(aomf51FileName, "wb");
if(aomf51out==NULL)
{
printf("Couldn't create file %s\n", aomf51FileName);
return;
}
GetName(infn[0].PathName, MHRname);
GlobalChkSum=0;
/*Module header record*/
OutputByte(0x02);/*REC TYPE*/
OutputWord((strlen(MHRname)+1)+3);/*Record Length*/
OutputName(MHRname);/*Module Name*/
OutputByte(0xff);/*TRN ID: RL51?*/
OutputByte(0x00);
OutputChkSum();
for(j=0; j2) /*If there are any symbols*/
{
OutputByte(0x12); /*REC TYPE*/
OutputWord(recsize); /*Record Length*/
OutputByte(0x01); /*DEF TYPE: Public symbols*/
for(k=0; k2) /*If there are any symbols*/
{
OutputByte(0x12); /*REC TYPE*/
OutputWord(recsize); /*Record Length*/
OutputByte(0x00); /*DEF TYPE: Local symbols*/
for(k=0; k2) /*If there are any symbols*/
{
OutputByte(0x12); /*REC TYPE*/
OutputWord(recsize); /*Record Length*/
OutputByte(0x00); /*DEF TYPE: Local symbols*/
for(i=0; i2) /*If there are any line numbers*/
{
OutputByte(0x12); /*REC TYPE*/
OutputWord(recsize); /*Record Length*/
OutputByte(0x03); /*DEF TYPE: Line numbers*/
for(i=0; i i)
{
/*Content Record*/
OutputByte(0x06);/*REC TYPE*/
OutputWord(k-i+4);/*Record Length*/
OutputByte(0x00);/*SEG ID*/
OutputWord(i); /*Offset*/
for ( ; i= 0)
break;
}
}
/*Scope Definition record: end module block*/
OutputByte(0x10);/*REC TYPE*/
OutputWord((strlen(Mname)+1)+2);/*Record Length*/
OutputByte(0x03);/*BLK TYP: module end*/
OutputName(Mname);/*Module Name*/
OutputChkSum();
/*Module end record*/
OutputByte(0x04);/*REC TYPE*/
OutputWord((strlen(MHRname)+1)+5);/*Record Length*/
OutputName(MHRname);/*Module Name*/
OutputWord(0x00);
OutputByte(0x0f);/*REG MSK: All the register banks?*/
OutputByte(0x00);
OutputChkSum();
fclose(aomf51out);
}
void CollectInfoFromCDB(void)
{
int i, j, k, CurrentModule;
FILE * CDBin;
char buff[0x1000];
char SourceName[PATH_MAX];
//"S:{G|F|L.}$$$(),,,"
char Sfmt[]="%[^$] %c %[^$] %c %[^$] %c %s";
char c;
char module[0x100];
char scope[0x100];
char name[0x100];
char level[0x100];
char block[0x100];
char TypeInfo[0x100];
char AddressSpace;
int OnStack;
int StackOffset;
int IsISR;
int IntNr;
int RegBank;
char Registers[0x100];
int Address, CLine;
if(numin==0) return;
if (yfp != NULL)
{
fclose(yfp);
yfp=NULL;
}
/*Build the source filename*/
strcpy(SourceName, infn[0].PathName);
strcat(SourceName, ".cdb");
CDBin=fopen(SourceName, "r");
if(CDBin==NULL)
{
printf("Couldn't open file '%s'\n", SourceName);
lkexit(1);
}
CurrentModule=0; /*Set the active module as the first one*/
while(!feof(CDBin))
{
if(NULL==fgets(buff, sizeof(buff)-1, CDBin))
{
if(ferror(CDBin))
{
perror("Can't read file");
lkexit(1);
}
else if(!feof(CDBin))
{
fprintf(stderr, "Unknown error while reading file '%s'\n", SourceName);
lkexit(1);
}
}
if(!feof(CDBin)) switch(buff[0])
{
/*Example: "M:adq"*/
case 'M':
sscanf(&buff[2], "%s", name);
for(j=0; j(),,,*/
sscanf(block, "%[^)] %c %c %c %c %d %c %d %c %s",
TypeInfo, &c, &c,
&AddressSpace, &c,
&OnStack, &c,
&StackOffset, &c,
Registers);
i=-1; k=-1;
switch(scope[2])
{
case 'G': /*Global symbol*/
break;
case 'F': /*Local symbol to a module*/
for(j=0; j(),,,,,, */
sscanf(block, "%[^)] %c %c %c %c %d %c %d %c %d %c %d %c %d",
TypeInfo, &c, &c,
&AddressSpace, &c,
&OnStack, &c,
&StackOffset, &c,
&IsISR, &c,
&IntNr, &c,
&RegBank);
/*The same may have been already defined */
for(j=0; j=procedure[k].BeginAdd) &&
(linenum[j].Address<=procedure[k].EndAdd) &&
(linenum[j].FileNameNumber==procedure[k].FileNameNumber) )
{
linenum[j].Procedure=k;
}
}
}
fclose(CDBin);
}
int hex2dec (unsigned char hex_digit)
{
if (isdigit (hex_digit))
return hex_digit-'0';
else
return toupper (hex_digit)-'A'+10;
}
unsigned char GetByte(char * buffer)
{
return hex2dec(buffer[0])*0x10+hex2dec(buffer[1]);
}
unsigned short GetWord(char * buffer)
{
return hex2dec(buffer[0])*0x1000+
hex2dec(buffer[1])*0x100+
hex2dec(buffer[2])*0x10+
hex2dec(buffer[3]);
}
int ReadHexFile(int * Begin)
{
char ihxFileName[PATH_MAX];
char buffer[1024];
FILE * filein;
int j;
unsigned char linesize, recordtype, rchksum, value;
int address, hi_addr = 0;
int MaxAddress = 0;
int chksum;
/*If the hexfile is already open, close it*/
if(ofp!=NULL)
{
fclose(ofp);
ofp=NULL;
}
strcpy(ihxFileName, infn[0].PathName);
strcat(ihxFileName, ".ihx");
if ( (filein=fopen(ihxFileName, "r")) == NULL )
{
printf("Error: Can't open file `%s`.\r\n", ihxFileName);
return 0;
}
ihxBuff = calloc(MEMSIZE, sizeof(short));
if (ihxBuff==NULL)
{
printf("Insufficient memory\n");
fclose(filein);
return -1;
}
for (j=0; j