OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /eco32/trunk
    from Rev 6 to Rev 7
    Reverse comparison

Rev 6 → Rev 7

/binutils/ld/ld.c
0,0 → 1,924
/*
* ld.c -- ECO32 linking loader
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <unistd.h>
 
#include "../include/a.out.h"
 
 
/**************************************************************/
 
 
#define MAX_STRLEN 200
 
#define PAGE_SHIFT 12
#define PAGE_SIZE (1 << PAGE_SHIFT)
#define PAGE_MASK (PAGE_SIZE - 1)
#define PAGE_ROUND(n) (((n) + PAGE_SIZE - 1) & ~PAGE_MASK)
 
#define MSB ((unsigned int) 1 << (sizeof(unsigned int) * 8 - 1))
 
 
/**************************************************************/
 
 
int debugLink = 0;
int debugFixup = 0;
 
int withHeader = 1;
 
char codeName[L_tmpnam];
char dataName[L_tmpnam];
char *outName = NULL;
char *mapName = NULL;
char *inName = NULL;
 
FILE *codeFile = NULL;
FILE *dataFile = NULL;
FILE *outFile = NULL;
FILE *mapFile = NULL;
FILE *inFile = NULL;
 
unsigned int segPtr[4] = { 0, 0, 0, 0 };
int segStartDefined[4] = { 0, 0, 0, 0 };
unsigned int segStart[4] = { 0, 0, 0, 0 };
char *segName[4] = { "ABS", "CODE", "DATA", "BSS" };
char *methodName[5] = { "H16", "L16", "R16", "R26", "W32" };
 
 
typedef struct reloc {
int segment; /* in which segment to relocate */
unsigned int offset; /* where in the segment to relocate */
int method; /* how to relocate */
int value; /* additive part of value */
int type; /* 0: base is a segment */
/* 1: base is a symbol */
union { /* relocation relative to .. */
int segment; /* .. a segment */
struct symbol *symbol; /* .. a symbol */
} base;
struct reloc *next; /* next relocation */
} Reloc;
 
 
typedef struct symbol {
char *name; /* name of symbol */
int type; /* if MSB = 0: the symbol's segment */
/* if MSB = 1: the symbol is undefined */
int value; /* if symbol defined: the symbol's value */
/* if symbol not defined: meaningless */
struct symbol *left; /* left son in binary search tree */
struct symbol *right; /* right son in binary search tree */
} Symbol;
 
 
/**************************************************************/
 
 
void error(char *fmt, ...) {
va_list ap;
 
va_start(ap, fmt);
fprintf(stderr, "Error: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
if (codeFile != NULL) {
fclose(codeFile);
codeFile = NULL;
}
if (dataFile != NULL) {
fclose(dataFile);
dataFile = NULL;
}
if (outFile != NULL) {
fclose(outFile);
outFile = NULL;
}
if (mapFile != NULL) {
fclose(mapFile);
mapFile = NULL;
}
if (inFile != NULL) {
fclose(inFile);
inFile = NULL;
}
if (codeName != NULL) {
unlink(codeName);
}
if (dataName != NULL) {
unlink(dataName);
}
if (outName != NULL) {
unlink(outName);
}
if (mapName != NULL) {
unlink(mapName);
}
exit(1);
}
 
 
void *allocateMemory(unsigned int size) {
void *p;
 
p = malloc(size);
if (p == NULL) {
error("out of memory");
}
return p;
}
 
 
void freeMemory(void *p) {
free(p);
}
 
 
/**************************************************************/
 
 
Reloc *relocs = NULL;
 
 
void addReloc(int segment, RelocRecord *relRec, Symbol **symMap) {
Reloc *rel;
 
rel = allocateMemory(sizeof(Reloc));
rel->segment = segment;
rel->offset = relRec->offset + segPtr[segment];
rel->method = relRec->method;
rel->value = relRec->value;
if ((relRec->base & MSB) == 0) {
/* relocation is relative to a segment */
rel->type = 0;
rel->base.segment = relRec->base;
rel->value += segPtr[relRec->base];
} else {
/* relocation is relative to a symbol */
rel->type = 1;
rel->base.symbol = symMap[relRec->base & ~MSB];
}
rel->next = relocs;
relocs = rel;
}
 
 
void linkSymbol(Reloc *rel) {
Symbol *sym;
 
/* check if this is a reference to a symbol */
if (rel->type != 1) {
/* no: nothing to do here */
return;
}
/* get information from the symbol table record */
sym = rel->base.symbol;
if (sym->type & MSB) {
error("undefined symbol '%s'", sym->name);
}
/* output debugging info */
if (debugLink) {
printf("DEBUG: link '%s' (s:%s, v:%08X)\n",
sym->name, segName[sym->type], sym->value);
printf(" (s:%s, o:%08X, m:%s, v:%08X --> %08X, b:%s)\n",
segName[rel->segment], rel->offset, methodName[rel->method],
rel->value, rel->value + sym->value, segName[sym->type]);
}
/* update relocation information */
rel->value += sym->value;
rel->type = 0;
rel->base.segment = sym->type;
}
 
 
void linkSymbols(void) {
Reloc *rel;
 
rel = relocs;
while (rel != NULL) {
linkSymbol(rel);
rel = rel->next;
}
}
 
 
void fixupRef(Reloc *rel) {
FILE *file;
unsigned int value;
unsigned int final;
 
/* determine the segment in which to do fixup */
switch (rel->segment) {
case SEGMENT_ABS:
/* this should never happen */
error("cannot do fixup in ABS");
break;
case SEGMENT_CODE:
file = codeFile;
break;
case SEGMENT_DATA:
file = dataFile;
break;
case SEGMENT_BSS:
/* this should never happen */
error("cannot do fixup in BSS");
break;
default:
/* this should never happen */
error("illegal segment in doFixup()");
break;
}
/* check that the base is indeed a segment */
if (rel->type != 0) {
/* this should never happen */
error("fixup cannot handle reference to symbol");
}
/* now patch according to method */
switch (rel->method) {
case METHOD_H16:
value = rel->value + segStart[rel->base.segment];
final = (value >> 16) & 0x0000FFFF;
fseek(file, rel->offset + 2, SEEK_SET);
fputc((final >> 8) & 0xFF, file);
fputc((final >> 0) & 0xFF, file);
break;
case METHOD_L16:
value = rel->value + segStart[rel->base.segment];
final = value & 0x0000FFFF;
fseek(file, rel->offset + 2, SEEK_SET);
fputc((final >> 8) & 0xFF, file);
fputc((final >> 0) & 0xFF, file);
break;
case METHOD_R16:
value = (rel->value - (rel->offset + 4)) / 4;
final = value & 0x0000FFFF;
fseek(file, rel->offset + 2, SEEK_SET);
fputc((final >> 8) & 0xFF, file);
fputc((final >> 0) & 0xFF, file);
break;
case METHOD_R26:
value = (rel->value - (rel->offset + 4)) / 4;
fseek(file, rel->offset, SEEK_SET);
final = (fgetc(file) << 24) & 0xFC000000;
final |= value & 0x03FFFFFF;
fseek(file, -1, SEEK_CUR);
fputc((final >> 24) & 0xFF, file);
fputc((final >> 16) & 0xFF, file);
fputc((final >> 8) & 0xFF, file);
fputc((final >> 0) & 0xFF, file);
break;
case METHOD_W32:
value = rel->value + segStart[rel->base.segment];
final = value;
fseek(file, rel->offset, SEEK_SET);
fputc((final >> 24) & 0xFF, file);
fputc((final >> 16) & 0xFF, file);
fputc((final >> 8) & 0xFF, file);
fputc((final >> 0) & 0xFF, file);
break;
default:
/* this should never happen */
error("illegal method in doFixup()");
break;
}
/* output debugging info */
if (debugFixup) {
printf("DEBUG: fixup (s:%s, o:%08X, m:%s, v:%08X), %08X --> %08X\n",
segName[rel->segment], rel->offset, methodName[rel->method],
rel->value, value, final);
}
}
 
 
void relocateSegments(void) {
Reloc *rel;
 
/* determine start of segments */
if (!segStartDefined[SEGMENT_CODE]) {
segStart[SEGMENT_CODE] = 0;
segStartDefined[SEGMENT_CODE] = 1;
}
if (!segStartDefined[SEGMENT_DATA]) {
segStart[SEGMENT_DATA] = segStart[SEGMENT_CODE] +
PAGE_ROUND(segPtr[SEGMENT_CODE]);
segStartDefined[SEGMENT_DATA] = 1;
}
if (!segStartDefined[SEGMENT_BSS]) {
segStart[SEGMENT_BSS] = segStart[SEGMENT_DATA] +
segPtr[SEGMENT_DATA];
segStartDefined[SEGMENT_BSS] = 1;
}
/* fixup all references (which now are only relative to segments) */
while (relocs != NULL) {
rel = relocs;
relocs = rel->next;
fixupRef(rel);
freeMemory(rel);
}
}
 
 
/**************************************************************/
 
 
Symbol *symbolTable = NULL;
 
 
Symbol *newSymbol(char *name) {
Symbol *p;
 
p = allocateMemory(sizeof(Symbol));
p->name = allocateMemory(strlen(name) + 1);
strcpy(p->name, name);
p->type = MSB;
p->value = 0;
p->left = NULL;
p->right = NULL;
return p;
}
 
 
Symbol *lookupEnter(char *name) {
Symbol *p, *q, *r;
int cmp;
 
p = symbolTable;
if (p == NULL) {
r = newSymbol(name);
symbolTable = r;
return r;
}
while (1) {
q = p;
cmp = strcmp(name, q->name);
if (cmp == 0) {
return q;
}
if (cmp < 0) {
p = q->left;
} else {
p = q->right;
}
if (p == NULL) {
r = newSymbol(name);
if (cmp < 0) {
q->left = r;
} else {
q->right = r;
}
return r;
}
}
}
 
 
void walkTree(Symbol *s, void (*fp)(Symbol *sp)) {
if (s == NULL) {
return;
}
walkTree(s->left, fp);
(*fp)(s);
walkTree(s->right, fp);
}
 
 
void walkSymbols(void (*fp)(Symbol *sym)) {
walkTree(symbolTable, fp);
}
 
 
/**************************************************************/
 
 
unsigned int read4FromEco(unsigned char *p) {
return (unsigned int) p[0] << 24 |
(unsigned int) p[1] << 16 |
(unsigned int) p[2] << 8 |
(unsigned int) p[3] << 0;
}
 
 
void write4ToEco(unsigned char *p, unsigned int data) {
p[0] = data >> 24;
p[1] = data >> 16;
p[2] = data >> 8;
p[3] = data >> 0;
}
 
 
void conv4FromEcoToNative(unsigned char *p) {
unsigned int data;
 
data = read4FromEco(p);
* (unsigned int *) p = data;
}
 
 
void conv4FromNativeToEco(unsigned char *p) {
unsigned int data;
 
data = * (unsigned int *) p;
write4ToEco(p, data);
}
 
 
/**************************************************************/
 
 
#define CODE_START(h) (sizeof(ExecHeader))
#define DATA_START(h) (CODE_START(h) + (h).csize)
#define CRELOC_START(h) (DATA_START(h) + (h).dsize)
#define DRELOC_START(h) (CRELOC_START(h) + (h).crsize)
#define SYMTBL_START(h) (DRELOC_START(h) + (h).drsize)
#define STRING_START(h) (SYMTBL_START(h) + (h).symsize)
 
 
ExecHeader inHeader;
Symbol **symMap;
 
 
void readHeader(void) {
if (fseek(inFile, 0, SEEK_SET) < 0) {
error("cannot seek to exec header");
}
if (fread(&inHeader, sizeof(ExecHeader), 1, inFile) != 1) {
error("cannot read exec header");
}
conv4FromEcoToNative((unsigned char *) &inHeader.magic);
conv4FromEcoToNative((unsigned char *) &inHeader.csize);
conv4FromEcoToNative((unsigned char *) &inHeader.dsize);
conv4FromEcoToNative((unsigned char *) &inHeader.bsize);
conv4FromEcoToNative((unsigned char *) &inHeader.crsize);
conv4FromEcoToNative((unsigned char *) &inHeader.drsize);
conv4FromEcoToNative((unsigned char *) &inHeader.symsize);
conv4FromEcoToNative((unsigned char *) &inHeader.strsize);
if (inHeader.magic != EXEC_MAGIC) {
error("wrong magic number in exec header");
}
}
 
 
void readCode(void) {
unsigned char *buffer;
 
if (fseek(inFile, CODE_START(inHeader), SEEK_SET) < 0) {
error("cannot seek to code section");
}
buffer = allocateMemory(inHeader.csize);
if (fread(buffer, 1, inHeader.csize, inFile) != inHeader.csize) {
error("cannot read code segment");
}
if (fwrite(buffer, 1, inHeader.csize, codeFile) != inHeader.csize) {
error("cannot write code segment");
}
freeMemory(buffer);
}
 
 
void readData(void) {
unsigned char *buffer;
 
if (fseek(inFile, DATA_START(inHeader), SEEK_SET) < 0) {
error("cannot seek to data section");
}
buffer = allocateMemory(inHeader.dsize);
if (fread(buffer, 1, inHeader.dsize, inFile) != inHeader.dsize) {
error("cannot read data segment");
}
if (fwrite(buffer, 1, inHeader.dsize, dataFile) != inHeader.dsize) {
error("cannot write data segment");
}
freeMemory(buffer);
}
 
 
void readCodeRelocs(void) {
int n, i;
RelocRecord relRec;
 
if (fseek(inFile, CRELOC_START(inHeader), SEEK_SET) < 0) {
error("cannot seek to code relocation section");
}
n = inHeader.crsize / sizeof(RelocRecord);
for (i = 0; i < n; i++) {
if (fread(&relRec, sizeof(RelocRecord), 1, inFile) != 1) {
error("cannot read code relocation records");
}
conv4FromEcoToNative((unsigned char *) &relRec.offset);
conv4FromEcoToNative((unsigned char *) &relRec.method);
conv4FromEcoToNative((unsigned char *) &relRec.value);
conv4FromEcoToNative((unsigned char *) &relRec.base);
addReloc(SEGMENT_CODE, &relRec, symMap);
}
}
 
 
void readDataRelocs(void) {
int n, i;
RelocRecord relRec;
 
if (fseek(inFile, DRELOC_START(inHeader), SEEK_SET) < 0) {
error("cannot seek to data relocation section");
}
n = inHeader.drsize / sizeof(RelocRecord);
for (i = 0; i < n; i++) {
if (fread(&relRec, sizeof(RelocRecord), 1, inFile) != 1) {
error("cannot read data relocation records");
}
conv4FromEcoToNative((unsigned char *) &relRec.offset);
conv4FromEcoToNative((unsigned char *) &relRec.method);
conv4FromEcoToNative((unsigned char *) &relRec.value);
conv4FromEcoToNative((unsigned char *) &relRec.base);
addReloc(SEGMENT_DATA, &relRec, symMap);
}
}
 
 
void readString(unsigned int offset, char *buffer, int size) {
long pos;
int c;
 
pos = ftell(inFile);
if (fseek(inFile, STRING_START(inHeader) + offset, SEEK_SET) < 0) {
error("cannot seek to string");
}
do {
c = fgetc(inFile);
if (c == EOF) {
error("unexpected end of file");
}
*buffer++ = c;
if (--size == 0) {
error("string buffer overflow");
}
} while (c != 0);
fseek(inFile, pos, SEEK_SET);
}
 
 
void readSymbols(void) {
int n, i;
SymbolRecord symRec;
char strBuf[MAX_STRLEN];
Symbol *sym;
 
if (fseek(inFile, SYMTBL_START(inHeader), SEEK_SET) < 0) {
error("cannot seek to symbol table section");
}
n = inHeader.symsize / sizeof(SymbolRecord);
symMap = allocateMemory(n * sizeof(Symbol *));
for (i = 0; i < n; i++) {
if (fread(&symRec, sizeof(SymbolRecord), 1, inFile) != 1) {
error("cannot read symbol table");
}
conv4FromEcoToNative((unsigned char *) &symRec.name);
conv4FromEcoToNative((unsigned char *) &symRec.type);
conv4FromEcoToNative((unsigned char *) &symRec.value);
readString(symRec.name, strBuf, MAX_STRLEN);
sym = lookupEnter(strBuf);
if ((symRec.type & MSB) == 0) {
/* the symbol is defined in this symbol record */
if ((sym->type & MSB) == 0) {
/* the symbol was already defined in the table */
error("symbol '%s' multiply defined", sym->name);
} else {
/* the symbol was not yet defined in the table, so define it now */
/* the segment is copied directly from the file */
/* the value is the sum of the value given in the file */
/* and this module's segment start of the symbol's segment */
sym->type = symRec.type;
sym->value = symRec.value + segPtr[symRec.type];
}
} else {
/* the symbol is undefined in this symbol record */
/* nothing to do here: lookupEnter already entered */
/* the symbol into the symbol table, if necessary */
}
/* in any case remember the symbol table entry, so that */
/* a symbol index in a relocation record can be resolved */
symMap[i] = sym;
}
}
 
 
void readModule(void) {
/* read the file header to determine the sizes */
readHeader();
/* read and transfer the code and data segments */
readCode();
readData();
/* read and build the symbol table and a symbol map */
readSymbols();
/* read and build a list of relocation records */
readCodeRelocs();
readDataRelocs();
/* free the symbol map, it is no longer needed */
freeMemory(symMap);
/* update accumulated segment sizes */
segPtr[SEGMENT_CODE] += inHeader.csize;
segPtr[SEGMENT_DATA] += inHeader.dsize;
segPtr[SEGMENT_BSS] += inHeader.bsize;
}
 
 
/**************************************************************/
 
 
void printSymbol(Symbol *s) {
fprintf(mapFile, "%-32s", s->name);
if (s->type & MSB) {
/* symbol is undefined */
fprintf(mapFile, "%-15s", "UNDEFINED");
} else {
/* symbol is defined */
switch (s->type) {
case SEGMENT_ABS:
fprintf(mapFile, "%-15s", "ABS");
break;
case SEGMENT_CODE:
fprintf(mapFile, "%-15s", "CODE");
break;
case SEGMENT_DATA:
fprintf(mapFile, "%-15s", "DATA");
break;
case SEGMENT_BSS:
fprintf(mapFile, "%-15s", "BSS");
break;
default:
error("illegal symbol segment in printToMap()");
}
}
fprintf(mapFile, "0x%08X", s->value);
fprintf(mapFile, "\n");
}
 
 
void printToMapFile(void) {
walkSymbols(printSymbol);
fprintf(mapFile, "\n");
fprintf(mapFile, "CODE start 0x%08X size 0x%08X\n",
segStart[SEGMENT_CODE], segPtr[SEGMENT_CODE]);
fprintf(mapFile, "DATA start 0x%08X size 0x%08X\n",
segStart[SEGMENT_DATA], segPtr[SEGMENT_DATA]);
fprintf(mapFile, "BSS start 0x%08X size 0x%08X\n",
segStart[SEGMENT_BSS], segPtr[SEGMENT_BSS]);
}
 
 
/**************************************************************/
 
 
void writeHeader(void) {
ExecHeader outHeader;
 
if (withHeader) {
outHeader.magic = EXEC_MAGIC;
outHeader.csize = segPtr[SEGMENT_CODE];
outHeader.dsize = segPtr[SEGMENT_DATA];
outHeader.bsize = segPtr[SEGMENT_BSS];
outHeader.crsize = 0;
outHeader.drsize = 0;
outHeader.symsize = 0;
outHeader.strsize = 0;
conv4FromNativeToEco((unsigned char *) &outHeader.magic);
conv4FromNativeToEco((unsigned char *) &outHeader.csize);
conv4FromNativeToEco((unsigned char *) &outHeader.dsize);
conv4FromNativeToEco((unsigned char *) &outHeader.bsize);
conv4FromNativeToEco((unsigned char *) &outHeader.crsize);
conv4FromNativeToEco((unsigned char *) &outHeader.drsize);
conv4FromNativeToEco((unsigned char *) &outHeader.symsize);
conv4FromNativeToEco((unsigned char *) &outHeader.strsize);
fwrite(&outHeader, sizeof(ExecHeader), 1, outFile);
}
}
 
 
void writeCode(void) {
int data;
 
rewind(codeFile);
while (1) {
data = fgetc(codeFile);
if (data == EOF) {
break;
}
fputc(data, outFile);
}
}
 
 
void writeData(void) {
int data;
 
rewind(dataFile);
while (1) {
data = fgetc(dataFile);
if (data == EOF) {
break;
}
fputc(data, outFile);
}
}
 
 
/**************************************************************/
 
 
int readNumber(char *str, unsigned int *np) {
int base;
int value;
int digit;
 
base = 10;
value = 0;
if (*str == '0') {
str++;
if (*str == 'x' || *str == 'X') {
base = 16;
str++;
} else
if (isdigit((int) *str)) {
base = 8;
} else
if (*str == '\0') {
*np = value;
return 1;
} else {
return 0;
}
}
while (isxdigit((int) *str)) {
digit = *str++ - '0';
if (digit >= 'A' - '0') {
if (digit >= 'a' - '0') {
digit += '0' - 'a' + 10;
} else {
digit += '0' - 'A' + 10;
}
}
if (digit >= base) {
return 0;
}
value *= base;
value += digit;
}
if (*str == '\0') {
*np = value;
return 1;
} else {
return 0;
}
}
 
 
void usage(char *myself) {
fprintf(stderr, "Usage: %s\n", myself);
fprintf(stderr, " [-h] do not write object header\n");
fprintf(stderr, " [-o objfile] set output file name\n");
fprintf(stderr, " [-m mapfile] produce map file\n");
fprintf(stderr, " [-rc addr] relocate code segment\n");
fprintf(stderr, " [-rd addr] relocate data segment\n");
fprintf(stderr, " [-rb addr] relocate bss segment\n");
fprintf(stderr, " file object file name\n");
fprintf(stderr, " [files...] additional object files\n");
exit(1);
}
 
 
int main(int argc, char *argv[]) {
int i;
char *argp;
unsigned int *ssp;
int *ssdp;
 
tmpnam(codeName);
tmpnam(dataName);
outName = "a.out";
for (i = 1; i < argc; i++) {
argp = argv[i];
if (*argp != '-') {
break;
}
argp++;
switch (*argp) {
case 'h':
withHeader = 0;
break;
case 'o':
if (i == argc - 1) {
usage(argv[0]);
}
outName = argv[++i];
break;
case 'm':
if (i == argc - 1) {
usage(argv[0]);
}
mapName = argv[++i];
break;
case 'r':
if (argp[1] == 'c') {
ssp = &segStart[SEGMENT_CODE];
ssdp = &segStartDefined[SEGMENT_CODE];
} else
if (argp[1] == 'd') {
ssp = &segStart[SEGMENT_DATA];
ssdp = &segStartDefined[SEGMENT_DATA];
} else
if (argp[1] == 'b') {
ssp = &segStart[SEGMENT_BSS];
ssdp = &segStartDefined[SEGMENT_BSS];
} else {
usage(argv[0]);
}
if (i == argc - 1) {
usage(argv[0]);
}
if (!readNumber(argv[++i], ssp)) {
error("cannot read number given with option '-%s'", argp);
}
*ssdp = 1;
break;
default:
usage(argv[0]);
}
}
if (i == argc) {
usage(argv[0]);
}
codeFile = fopen(codeName, "w+b");
if (codeFile == NULL) {
error("cannot create temporary code file '%s'", codeName);
}
dataFile = fopen(dataName, "w+b");
if (dataFile == NULL) {
error("cannot create temporary data file '%s'", dataName);
}
outFile = fopen(outName, "wb");
if (outFile == NULL) {
error("cannot open output file '%s'", outName);
}
if (mapName != NULL) {
mapFile = fopen(mapName, "wt");
if (mapFile == NULL) {
error("cannot open map file '%s'", mapName);
}
}
do {
inName = argv[i];
if (*inName == '-') {
usage(argv[0]);
}
inFile = fopen(inName, "rb");
if (inFile == NULL) {
error("cannot open input file '%s'", inName);
}
fprintf(stderr, "Reading module '%s'...\n", inName);
readModule();
if (inFile != NULL) {
fclose(inFile);
inFile = NULL;
}
} while (++i < argc);
fprintf(stderr, "Linking modules...\n");
linkSymbols();
fprintf(stderr, "Relocating segments...\n");
relocateSegments();
writeHeader();
writeCode();
writeData();
if (mapFile != NULL) {
printToMapFile();
}
if (codeFile != NULL) {
fclose(codeFile);
codeFile = NULL;
}
if (dataFile != NULL) {
fclose(dataFile);
dataFile = NULL;
}
if (outFile != NULL) {
fclose(outFile);
outFile = NULL;
}
if (mapFile != NULL) {
fclose(mapFile);
mapFile = NULL;
}
if (codeName != NULL) {
unlink(codeName);
}
if (dataName != NULL) {
unlink(dataName);
}
return 0;
}
/binutils/ld/Makefile
0,0 → 1,36
#
# Makefile for ECO32 linking loader
#
 
BUILD = ../../build
 
CC = gcc -m32
CFLAGS = -g -Wall
LDFLAGS = -g
LDLIBS = -lm
 
SRCS = ld.c
OBJS = $(patsubst %.c,%.o,$(SRCS))
BIN = ld
 
.PHONY: all install clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/bin
cp $(BIN) $(BUILD)/bin
 
$(BIN): $(OBJS)
$(CC) $(LDFLAGS) -o $(BIN) $(OBJS) $(LDLIBS)
 
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
 
depend.mak:
$(CC) -MM -MG $(CFLAGS) $(SRCS) > depend.mak
 
-include depend.mak
 
clean:
rm -f *~ $(OBJS) $(BIN) depend.mak
/binutils/tests-1/L16/test0.s
0,0 → 1,20
.nosyn
 
.code
 
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
 
.bss
 
.space 0x100
/binutils/tests-1/L16/test1.s
0,0 → 1,56
.nosyn
 
.export C_global
.import C_extern
.export D_global
.import D_extern
.export B_global
.import B_extern
 
.code
 
add $3,$2,$1
add $3,$2,$1
xnor $3,$1,C_local+10
xnor $3,$1,C_global+20
xnor $3,$1,C_extern+30
xnor $3,$1,D_local+40
xnor $3,$1,D_global+50
xnor $3,$1,D_extern+60
xnor $3,$1,B_local+70
xnor $3,$1,B_global+80
xnor $3,$1,B_extern+90
add $3,$2,$1
add $3,$2,$1
C_local:
add $3,$2,$1
C_global:
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
xnor $3,$1,C_local+10
xnor $3,$1,C_global+20
xnor $3,$1,C_extern+30
xnor $3,$1,D_local+40
xnor $3,$1,D_global+50
xnor $3,$1,D_extern+60
xnor $3,$1,B_local+70
xnor $3,$1,B_global+80
xnor $3,$1,B_extern+90
.word 0x55AA55AA
.word 0x55AA55AA
D_local:
.word 0x55AA55AA
D_global:
.word 0x55AA55AA
 
.bss
 
.space 0x100
B_local:
.space 0x100
B_global:
.space 0x100
/binutils/tests-1/L16/test2.s
0,0 → 1,30
.nosyn
 
.export C_extern
.export D_extern
.export B_extern
 
.code
 
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
C_extern:
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
D_extern:
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
 
.bss
.space 0x100
B_extern:
.space 0x100
/binutils/tests-1/L16/Makefile
0,0 → 1,15
#
# Makefile for as/ld test
#
 
BUILD = ../../../build
 
all:
$(BUILD)/bin/as -o test0.o test0.s
$(BUILD)/bin/as -o test1.o test1.s
$(BUILD)/bin/as -o test2.o test2.s
$(BUILD)/bin/ld -h -o test -m test.map test0.o test1.o test2.o
$(BUILD)/bin/dof -a test1.o >test1.dump
 
clean:
rm -f *~ test0.o test1.o test2.o test test.map test1.dump
/binutils/tests-1/R16/test0.s
0,0 → 1,20
.nosyn
 
.code
 
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
 
.bss
 
.space 0x100
/binutils/tests-1/R16/test1.s
0,0 → 1,56
.nosyn
 
.export C_global
.import C_extern
.export D_global
.import D_extern
.export B_global
.import B_extern
 
.code
 
add $3,$2,$1
add $3,$2,$1
beq $2,$1,C_local+10
beq $2,$1,C_global+20
beq $2,$1,C_extern+30
beq $2,$1,D_local+40
beq $2,$1,D_global+50
beq $2,$1,D_extern+60
beq $2,$1,B_local+70
beq $2,$1,B_global+80
beq $2,$1,B_extern+90
add $3,$2,$1
add $3,$2,$1
C_local:
add $3,$2,$1
C_global:
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
beq $2,$1,C_local+10
beq $2,$1,C_global+20
beq $2,$1,C_extern+30
beq $2,$1,D_local+40
beq $2,$1,D_global+50
beq $2,$1,D_extern+60
beq $2,$1,B_local+70
beq $2,$1,B_global+80
beq $2,$1,B_extern+90
.word 0x55AA55AA
.word 0x55AA55AA
D_local:
.word 0x55AA55AA
D_global:
.word 0x55AA55AA
 
.bss
 
.space 0x100
B_local:
.space 0x100
B_global:
.space 0x100
/binutils/tests-1/R16/test2.s
0,0 → 1,30
.nosyn
 
.export C_extern
.export D_extern
.export B_extern
 
.code
 
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
C_extern:
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
D_extern:
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
 
.bss
.space 0x100
B_extern:
.space 0x100
/binutils/tests-1/R16/Makefile
0,0 → 1,15
#
# Makefile for as/ld test
#
 
BUILD = ../../../build
 
all:
$(BUILD)/bin/as -o test0.o test0.s
$(BUILD)/bin/as -o test1.o test1.s
$(BUILD)/bin/as -o test2.o test2.s
$(BUILD)/bin/ld -h -o test -m test.map test0.o test1.o test2.o
$(BUILD)/bin/dof -a test1.o >test1.dump
 
clean:
rm -f *~ test0.o test1.o test2.o test test.map test1.dump
/binutils/tests-1/R26/test0.s
0,0 → 1,20
.nosyn
 
.code
 
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
 
.bss
 
.space 0x100
/binutils/tests-1/R26/test1.s
0,0 → 1,56
.nosyn
 
.export C_global
.import C_extern
.export D_global
.import D_extern
.export B_global
.import B_extern
 
.code
 
add $3,$2,$1
add $3,$2,$1
j C_local+10
j C_global+20
j C_extern+30
j D_local+40
j D_global+50
j D_extern+60
j B_local+70
j B_global+80
j B_extern+90
add $3,$2,$1
add $3,$2,$1
C_local:
add $3,$2,$1
C_global:
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
j C_local+10
j C_global+20
j C_extern+30
j D_local+40
j D_global+50
j D_extern+60
j B_local+70
j B_global+80
j B_extern+90
.word 0x55AA55AA
.word 0x55AA55AA
D_local:
.word 0x55AA55AA
D_global:
.word 0x55AA55AA
 
.bss
 
.space 0x100
B_local:
.space 0x100
B_global:
.space 0x100
/binutils/tests-1/R26/test2.s
0,0 → 1,30
.nosyn
 
.export C_extern
.export D_extern
.export B_extern
 
.code
 
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
C_extern:
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
D_extern:
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
 
.bss
.space 0x100
B_extern:
.space 0x100
/binutils/tests-1/R26/Makefile
0,0 → 1,15
#
# Makefile for as/ld test
#
 
BUILD = ../../../build
 
all:
$(BUILD)/bin/as -o test0.o test0.s
$(BUILD)/bin/as -o test1.o test1.s
$(BUILD)/bin/as -o test2.o test2.s
$(BUILD)/bin/ld -h -o test -m test.map test0.o test1.o test2.o
$(BUILD)/bin/dof -a test1.o >test1.dump
 
clean:
rm -f *~ test0.o test1.o test2.o test test.map test1.dump
/binutils/tests-1/W32/test0.s
0,0 → 1,20
.nosyn
 
.code
 
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
 
.bss
 
.space 0x100
/binutils/tests-1/W32/test1.s
0,0 → 1,56
.nosyn
 
.export C_global
.import C_extern
.export D_global
.import D_extern
.export B_global
.import B_extern
 
.code
 
add $3,$2,$1
add $3,$2,$1
.word C_local+10
.word C_global+20
.word C_extern+30
.word D_local+40
.word D_global+50
.word D_extern+60
.word B_local+70
.word B_global+80
.word B_extern+90
add $3,$2,$1
add $3,$2,$1
C_local:
add $3,$2,$1
C_global:
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
.word C_local+10
.word C_global+20
.word C_extern+30
.word D_local+40
.word D_global+50
.word D_extern+60
.word B_local+70
.word B_global+80
.word B_extern+90
.word 0x55AA55AA
.word 0x55AA55AA
D_local:
.word 0x55AA55AA
D_global:
.word 0x55AA55AA
 
.bss
 
.space 0x100
B_local:
.space 0x100
B_global:
.space 0x100
/binutils/tests-1/W32/test2.s
0,0 → 1,30
.nosyn
 
.export C_extern
.export D_extern
.export B_extern
 
.code
 
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
C_extern:
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
D_extern:
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
 
.bss
.space 0x100
B_extern:
.space 0x100
/binutils/tests-1/W32/Makefile
0,0 → 1,15
#
# Makefile for as/ld test
#
 
BUILD = ../../../build
 
all:
$(BUILD)/bin/as -o test0.o test0.s
$(BUILD)/bin/as -o test1.o test1.s
$(BUILD)/bin/as -o test2.o test2.s
$(BUILD)/bin/ld -h -o test -m test.map test0.o test1.o test2.o
$(BUILD)/bin/dof -a test1.o >test1.dump
 
clean:
rm -f *~ test0.o test1.o test2.o test test.map test1.dump
/binutils/tests-1/Makefile
0,0 → 1,20
#
# Makefile for as/ld tests
#
 
BUILD = ../../build
 
DIRS = H16 L16 R16 R26 W32
 
.PHONY: all clean
 
all:
for i in $(DIRS) ; do \
$(MAKE) -C $$i all ; \
done
 
clean:
for i in $(DIRS) ; do \
$(MAKE) -C $$i clean ; \
done
rm -f *~
/binutils/tests-1/H16/test0.s
0,0 → 1,20
.nosyn
 
.code
 
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
 
.bss
 
.space 0x100
/binutils/tests-1/H16/test1.s
0,0 → 1,56
.nosyn
 
.export C_global
.import C_extern
.export D_global
.import D_extern
.export B_global
.import B_extern
 
.code
 
add $3,$2,$1
add $3,$2,$1
ldhi $3,C_local+10
ldhi $3,C_global+20
ldhi $3,C_extern+30
ldhi $3,D_local+40
ldhi $3,D_global+50
ldhi $3,D_extern+60
ldhi $3,B_local+70
ldhi $3,B_global+80
ldhi $3,B_extern+90
add $3,$2,$1
add $3,$2,$1
C_local:
add $3,$2,$1
C_global:
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
ldhi $3,C_local+10
ldhi $3,C_global+20
ldhi $3,C_extern+30
ldhi $3,D_local+40
ldhi $3,D_global+50
ldhi $3,D_extern+60
ldhi $3,B_local+70
ldhi $3,B_global+80
ldhi $3,B_extern+90
.word 0x55AA55AA
.word 0x55AA55AA
D_local:
.word 0x55AA55AA
D_global:
.word 0x55AA55AA
 
.bss
 
.space 0x100
B_local:
.space 0x100
B_global:
.space 0x100
/binutils/tests-1/H16/test2.s
0,0 → 1,30
.nosyn
 
.export C_extern
.export D_extern
.export B_extern
 
.code
 
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
C_extern:
add $3,$2,$1
add $3,$2,$1
add $3,$2,$1
 
.data
 
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
D_extern:
.word 0x55AA55AA
.word 0x55AA55AA
.word 0x55AA55AA
 
.bss
.space 0x100
B_extern:
.space 0x100
/binutils/tests-1/H16/Makefile
0,0 → 1,15
#
# Makefile for as/ld test
#
 
BUILD = ../../../build
 
all:
$(BUILD)/bin/as -o test0.o test0.s
$(BUILD)/bin/as -o test1.o test1.s
$(BUILD)/bin/as -o test2.o test2.s
$(BUILD)/bin/ld -h -o test -m test.map test0.o test1.o test2.o
$(BUILD)/bin/dof -a test1.o >test1.dump
 
clean:
rm -f *~ test0.o test1.o test2.o test test.map test1.dump
/binutils/tests-2/intrpt/intrpt.s
0,0 → 1,229
;
; intrpt.s -- a first attempt to utilize interrupts
;
 
.set stack,0xC0010000 ; stack
.set timerbase,0xF0000000 ; timer base address
.set termbase,0xF0300000 ; terminal base address
 
reset:
j start ; reset arrives here
 
intrpt:
j isr ; interrupts arrive here
 
userMiss:
j userMiss ; user TLB miss exceptions arrive here
 
isr:
mvfs $26,0 ; determine cause
slr $26,$26,14 ; $26 = 4 * IRQ number
and $26,$26,0x1F << 2
ldw $26,$26,irqsrv ; get addr of service routine
jr $26 ; jump to service routine
 
start:
add $29,$0,stack ; set sp
add $4,$0,runmsg ; pointer to string
jal msg ; show string
add $8,$0,timerbase ; program timer
add $9,$0,1000 ; divisor = 1000
stw $9,$8,4
add $9,$0,2 ; enable timer interrupts
stw $9,$8,0
mvfs $8,0
or $8,$8,1 << 14 ; open timer IRQ mask bit
or $8,$8,1 << 23 ; enable processor interrupts
or $8,$8,1 << 27 ; let vector point to RAM
mvts $8,0
start1:
j start1 ; loop
 
tmrisr:
add $8,$0,0x02 ; ien = 1, int = 0
stw $8,$0,timerbase
j shmsg
 
shmsg:
mvfs $8,0
slr $8,$8,14 ; $8 = 4 * IRQ number
and $8,$8,0x1F << 2
ldw $4,$8,msgtbl ; get addr of message
jal msg ; show message
rfx ; return from exception
 
msg:
sub $29,$29,8 ; save registers
stw $31,$29,4
stw $16,$29,0
add $16,$4,$0 ; get pointer
msg1:
ldbu $4,$16,0 ; get char
beq $4,$0,msg2 ; null - finished
jal out ; output char
add $16,$16,1 ; bump pointer
j msg1 ; next char
msg2:
ldw $16,$29,0 ; restore registers
ldw $31,$29,4
add $29,$29,8
jr $31 ; return
 
out:
add $8,$0,termbase ; set I/O base address
out1:
ldw $9,$8,8 ; get status
and $9,$9,1 ; xmtr ready?
beq $9,$0,out1 ; no - wait
stw $4,$8,12 ; send char
jr $31 ; return
 
; service routine table
 
irqsrv:
.word shmsg ; 00: terminal 0 transmitter interrupt
.word shmsg ; 01: terminal 0 receiver interrupt
.word shmsg ; 02: terminal 1 transmitter interrupt
.word shmsg ; 03: terminal 1 receiver interrupt
.word shmsg ; 04: keyboard interrupt
.word shmsg ; 05: unused
.word shmsg ; 06: unused
.word shmsg ; 07: unused
.word shmsg ; 08: disk interrupt
.word shmsg ; 09: unused
.word shmsg ; 10: unused
.word shmsg ; 11: unused
.word shmsg ; 12: unused
.word shmsg ; 13: unused
.word tmrisr ; 14: timer interrupt
.word shmsg ; 15: unused
.word shmsg ; 16: bus timeout exception
.word shmsg ; 17: illegal instruction exception
.word shmsg ; 18: privileged instruction exception
.word shmsg ; 19: divide instruction exception
.word shmsg ; 20: trap instruction exception
.word shmsg ; 21: TLB miss exception
.word shmsg ; 22: TLB write exception
.word shmsg ; 23: TLB invalid exception
.word shmsg ; 24: illegal address exception
.word shmsg ; 25: privileged address exception
.word shmsg ; 26: unused
.word shmsg ; 27: unused
.word shmsg ; 28: unused
.word shmsg ; 29: unused
.word shmsg ; 30: unused
.word shmsg ; 31: unused
 
; message table
 
msgtbl:
.word xmtmsg ; 00: terminal 0 transmitter interrupt
.word rcvmsg ; 01: terminal 0 receiver interrupt
.word xmtmsg ; 02: terminal 1 transmitter interrupt
.word rcvmsg ; 03: terminal 1 receiver interrupt
.word kbdmsg ; 04: keyboard interrupt
.word uimsg ; 05: unused
.word uimsg ; 06: unused
.word uimsg ; 07: unused
.word dskmsg ; 08: disk interrupt
.word uimsg ; 09: unused
.word uimsg ; 10: unused
.word uimsg ; 11: unused
.word uimsg ; 12: unused
.word uimsg ; 13: unused
.word tmrmsg ; 14: timer interrupt
.word uimsg ; 15: unused
.word btmsg ; 16: bus timeout exception
.word iimsg ; 17: illegal instruction exception
.word pimsg ; 18: privileged instruction exception
.word dimsg ; 19: divide instruction exception
.word timsg ; 20: trap instruction exception
.word msmsg ; 21: TLB miss exception
.word wrmsg ; 22: TLB write exception
.word ivmsg ; 23: TLB invalid exception
.word iamsg ; 24: illegal address exception
.word pamsg ; 25: privileged address exception
.word uemsg ; 26: unused
.word uemsg ; 27: unused
.word uemsg ; 28: unused
.word uemsg ; 29: unused
.word uemsg ; 30: unused
.word uemsg ; 31: unused
 
; sign-on message
 
runmsg:
.byte "system running..."
.byte 0x0D, 0x0A, 0
 
; interrupt messages
 
uimsg:
.byte "unknown interrupt"
.byte 0x0D, 0x0A, 0
 
xmtmsg:
.byte "terminal transmitter interrupt"
.byte 0x0D, 0x0A, 0
 
rcvmsg:
.byte "terminal receiver interrupt"
.byte 0x0D, 0x0A, 0
 
kbdmsg:
.byte "keyboard interrupt"
.byte 0x0D, 0x0A, 0
 
dskmsg:
.byte "disk interrupt"
.byte 0x0D, 0x0A, 0
 
tmrmsg:
.byte "timer interrupt"
.byte 0x0D, 0x0A, 0
 
; exception messages
 
uemsg:
.byte "unknown exception"
.byte 0x0D, 0x0A, 0
 
btmsg:
.byte "bus timeout exception"
.byte 0x0D, 0x0A, 0
 
iimsg:
.byte "illegal instruction exception"
.byte 0x0D, 0x0A, 0
 
pimsg:
.byte "privileged instruction exception"
.byte 0x0D, 0x0A, 0
 
dimsg:
.byte "divide instruction exception"
.byte 0x0D, 0x0A, 0
 
timsg:
.byte "trap instruction exception"
.byte 0x0D, 0x0A, 0
 
msmsg:
.byte "TLB miss exception"
.byte 0x0D, 0x0A, 0
 
wrmsg:
.byte "TLB write exception"
.byte 0x0D, 0x0A, 0
 
ivmsg:
.byte "TLB invalid exception"
.byte 0x0D, 0x0A, 0
 
iamsg:
.byte "illegal address exception"
.byte 0x0D, 0x0A, 0
 
pamsg:
.byte "privileged address exception"
.byte 0x0D, 0x0A, 0
/binutils/tests-2/intrpt/Makefile
0,0 → 1,15
BUILD = ../../../build
 
all: intrpt.bin
 
intrpt.bin: intrpt.o
$(BUILD)/bin/ld -h -rc 0xC0000000 -o intrpt.bin intrpt.o
 
intrpt.o: intrpt.s
$(BUILD)/bin/as -o intrpt.o intrpt.s
 
run: intrpt.bin
$(BUILD)/bin/sim -t 1 -l intrpt.bin
 
clean:
rm -f *~ intrpt.bin intrpt.o
/binutils/tests-2/permute/src1.s
0,0 → 1,5
.code
.import fptr
.export call
.word 0x11111111
call: .word fptr
/binutils/tests-2/permute/src2.s
0,0 → 1,6
.data
.import func
.export fptr
.word 0x11111111
.word 0x22222222
fptr: .word func
/binutils/tests-2/permute/src3.s
0,0 → 1,7
.code
.export func
.import call
.word 0x11111111
.word 0x22222222
.word 0x33333333
func: .word call
/binutils/tests-2/permute/Makefile
0,0 → 1,34
BUILD = ../../../build
 
all: all123 all132 all213 all231 all312 all321
 
all123: src1.o src2.o src3.o
$(BUILD)/bin/ld -o all123 src1.o src2.o src3.o
 
all132: src1.o src2.o src3.o
$(BUILD)/bin/ld -o all132 src1.o src3.o src2.o
 
all213: src1.o src2.o src3.o
$(BUILD)/bin/ld -o all213 src2.o src1.o src3.o
 
all231: src1.o src2.o src3.o
$(BUILD)/bin/ld -o all231 src2.o src3.o src1.o
 
all312: src1.o src2.o src3.o
$(BUILD)/bin/ld -o all312 src3.o src1.o src2.o
 
all321: src1.o src2.o src3.o
$(BUILD)/bin/ld -o all321 src3.o src2.o src1.o
 
src1.o: src1.s
$(BUILD)/bin/as -o src1.o src1.s
 
src2.o: src2.s
$(BUILD)/bin/as -o src2.o src2.s
 
src3.o: src3.s
$(BUILD)/bin/as -o src3.o src3.s
 
clean:
rm -f *~ src1.o src2.o src3.o
rm -f all123 all132 all213 all231 all312 all321
/binutils/tests-2/hello/hello.s
0,0 → 1,39
;
; hello.s -- Hello, world!
;
 
; $11 I/O base address
; $12 temporary value
; $13 character
; $14 pointer to string
; $29 stack pointer
; $31 return address
 
.set tba,0xF0300000
 
reset: add $29,$0,0xC0010000
jal start
reset1: j reset1
 
start: sub $29,$29,4 ; save return register
stw $31,$29,0
add $11,$0,tba ; set I/O base address
add $14,$0,hello ; pointer to string
or $14,$14,hello
loop: ldbu $13,$14,0 ; get char
beq $13,$0,stop ; null - finished
jal out ; output char
add $14,$14,1 ; bump pointer
j loop ; next char
stop: ldw $31,$29,0 ; restore return register
add $29,$29,4
jr $31 ; return
 
out: ldw $12,$11,8 ; get status
and $12,$12,1 ; xmtr ready?
beq $12,$0,out ; no - wait
stw $13,$11,12 ; send char
jr $31 ; return
 
hello: .byte "Hello, world!"
.byte 0x0D, 0x0A, 0
/binutils/tests-2/hello/Makefile
0,0 → 1,15
BUILD = ../../../build
 
all: hello.bin
 
hello.bin: hello.o
$(BUILD)/bin/ld -h -rc 0xC0000000 -o hello.bin hello.o
 
hello.o: hello.s
$(BUILD)/bin/as -o hello.o hello.s
 
run: hello.bin
$(BUILD)/bin/sim -t 1 -l hello.bin
 
clean:
rm -f *~ hello.bin hello.o
/binutils/tests-2/abs/abs1.s
0,0 → 1,3
.code
.export absval
.set absval,0xdeadbeef
/binutils/tests-2/abs/abs2.s
0,0 → 1,4
.code
.import absval
ldhi $4,absval
or $4,$4,absval
/binutils/tests-2/abs/Makefile
0,0 → 1,15
BUILD = ../../../build
 
all:
$(BUILD)/bin/as -o abs1.o abs1.s
$(BUILD)/bin/as -o abs2.o abs2.s
$(BUILD)/bin/ld -o abs12 abs1.o abs2.o
$(BUILD)/bin/ld -o abs21 abs2.o abs1.o
@echo -n "Comparing abs12 and abs21: "
@if cmp abs12 abs21 ; \
then echo "Files are equal." ; \
else echo "Error found!" ; \
fi
 
clean:
rm -f *~ abs1.o abs2.o abs12 abs21
/binutils/tests-2/format/format.s
0,0 → 1,32
 
.export label
 
.code
 
; formatN
trap
 
; formatRH
mvfs $23,1
 
; formatRHH
ldhi $23,0x12345678
ldhi $23,label+4
 
; formatRRX
and $23,$24,$25
and $23,$24,0x00005678
and $23,$24,0x12340000
and $23,$24,0x12345678
and $23,$24,label+4
 
; formatRRY
add $23,$24,$25
add $23,$24,0x00005678
add $23,$24,0x12340000
add $23,$24,0x12345678
add $23,$24,label+4
 
.bss
.space 0x1234
label: .word 0
/binutils/tests-2/format/Makefile
0,0 → 1,16
BUILD = ../../../build
 
all: format.bin
 
format.bin: format.o
$(BUILD)/bin/ld -h -rc 0xC0000000 -o format.bin \
-m format.map format.o
 
format.o: format.s
$(BUILD)/bin/as -o format.o format.s
 
run: format.bin
$(BUILD)/bin/sim -i -l format.bin
 
clean:
rm -f *~ format.map format.bin format.o
/binutils/tests-2/jump/jump1.s
0,0 → 1,10
.code
 
.import lbl2
.export lbl1
 
add $1,$2,$3
add $4,$5,$6
lbl1: j lbl2
add $7,$8,$9
add $10,$11,$12
/binutils/tests-2/jump/Makefile
0,0 → 1,10
BUILD = ../../../build
 
all:
$(BUILD)/bin/as -o jump1.o jump1.s
$(BUILD)/bin/as -o jump2.o jump2.s
$(BUILD)/bin/ld -rc 0x12345678 -o jump jump1.o jump2.o
hexdump jump
 
clean:
rm -f *~ jump1.o jump2.o jump
/binutils/tests-2/jump/jump2.s
0,0 → 1,10
.code
 
.import lbl1
.export lbl2
 
add $13,$14,$15
add $16,$17,$18
lbl2: j lbl1
add $19,$20,$21
add $22,$23,$24
/binutils/tests-2/set/set.s
0,0 → 1,6
.set s1,11
.set s2,s1+22
.set s3,s2-s1
 
.data
.word s3
/binutils/tests-2/set/Makefile
0,0 → 1,9
BUILD = ../../../build
 
all:
$(BUILD)/bin/as -o set.o set.s
$(BUILD)/bin/ld -o set set.o
hexdump set
 
clean:
rm -f *~ set set.o
/binutils/tests-2/link/link1.s
0,0 → 1,7
.data
 
.import func
 
.word 0x12345678
.word 0xDEADBEEF
.word func+2
/binutils/tests-2/link/link2.s
0,0 → 1,10
.code
 
.export func
 
.word 0x87654321
.word 0xBEEFDEAD
 
func:
.word 0x11223344
.word 0x55667788
/binutils/tests-2/link/Makefile
0,0 → 1,15
BUILD = ../../../build
 
all:
$(BUILD)/bin/as -o link1.o link1.s
$(BUILD)/bin/as -o link2.o link2.s
$(BUILD)/bin/ld -o link12 link1.o link2.o
$(BUILD)/bin/ld -o link21 link2.o link1.o
@echo -n "Comparing link12 and link21: "
@if cmp link12 link21 ; \
then echo "Files are equal." ; \
else echo "Error found!" ; \
fi
 
clean:
rm -f *~ link1.o link2.o link12 link21
/binutils/tests-2/src123/src1.s
0,0 → 1,5
.code
.import fptr
.export call
.word 0x11111111
call: .word fptr
/binutils/tests-2/src123/src2.s
0,0 → 1,6
.data
.import func
.export fptr
.word 0x11111111
.word 0x22222222
fptr: .word func
/binutils/tests-2/src123/src3.s
0,0 → 1,7
.code
.export func
.import call
.word 0x11111111
.word 0x22222222
.word 0x33333333
func: .word call
/binutils/tests-2/src123/Makefile
0,0 → 1,11
BUILD = ../../../build
 
all:
$(BUILD)/bin/as -o src1.o src1.s
$(BUILD)/bin/as -o src2.o src2.s
$(BUILD)/bin/as -o src3.o src3.s
$(BUILD)/bin/ld -o src123 src1.o src2.o src3.o
hexdump src123
 
clean:
rm -f *~ src123 src1.o src2.o src3.o
/binutils/ar/endian.c
0,0 → 1,38
/*
* endian.c -- endianness conversions
*/
 
 
#include "endian.h"
 
 
unsigned int read4FromEco(unsigned char *p) {
return (unsigned int) p[0] << 24 |
(unsigned int) p[1] << 16 |
(unsigned int) p[2] << 8 |
(unsigned int) p[3] << 0;
}
 
 
void write4ToEco(unsigned char *p, unsigned int data) {
p[0] = data >> 24;
p[1] = data >> 16;
p[2] = data >> 8;
p[3] = data >> 0;
}
 
 
void conv4FromEcoToNative(unsigned char *p) {
unsigned int data;
 
data = read4FromEco(p);
* (unsigned int *) p = data;
}
 
 
void conv4FromNativeToEco(unsigned char *p) {
unsigned int data;
 
data = * (unsigned int *) p;
write4ToEco(p, data);
}
/binutils/ar/test1/text
0,0 → 1,38
This is a well-defined text.
/binutils/ar/test2/ttt.s
0,0 → 1,5
.code
.export L12345
 
L12345:
add $1,$2,$3
/binutils/ar/ar.c
0,0 → 1,865
/*
* ar.c -- archiver
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
 
#include "endian.h"
#include "ranlib.h"
#include "../include/ar.h"
 
 
/**************************************************************/
 
 
#define BUFSIZE 512
 
#define SKIP 0x01
#define IODD 0x02
#define OODD 0x04
#define HEAD 0x08
 
 
char *com = "drqtpmx";
char *opt = "vuabcls";
 
int signums[] = { SIGHUP, SIGINT, SIGQUIT, 0 };
 
void (*comfun)(void);
int flg[26];
 
char *arnam;
int af;
 
char **namv;
int namc;
 
int baState;
char *posName;
 
char tmp0nam[20];
char tmp1nam[20];
char tmp2nam[20];
char *tf0nam;
char *tf1nam;
char *tf2nam;
int tf0;
int tf1;
int tf2;
int qf;
 
char *file;
char name[MAX_NAME];
 
struct stat stbuf;
ArHeader arbuf;
unsigned char buf[BUFSIZE];
 
 
/**************************************************************/
 
 
#define IFMT 070000
#define SUID 004000
#define SGID 002000
#define STXT 001000
#define ROWN 000400
#define WOWN 000200
#define XOWN 000100
#define RGRP 000040
#define WGRP 000020
#define XGRP 000010
#define ROTH 000004
#define WOTH 000002
#define XOTH 000001
 
 
int m1[] = { 1, ROWN, 'r', '-' };
int m2[] = { 1, WOWN, 'w', '-' };
int m3[] = { 2, SUID, 's', XOWN, 'x', '-' };
int m4[] = { 1, RGRP, 'r', '-' };
int m5[] = { 1, WGRP, 'w', '-' };
int m6[] = { 2, SGID, 's', XGRP, 'x', '-' };
int m7[] = { 1, ROTH, 'r', '-' };
int m8[] = { 1, WOTH, 'w', '-' };
int m9[] = { 2, STXT, 't', XOTH, 'x', '-' };
 
int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9 };
 
 
void selectChar(int *pairp) {
int *ap;
int n;
 
ap = pairp;
n = *ap++;
while (--n >= 0 && (arbuf.mode & *ap++) == 0) {
ap++;
}
putchar(*ap);
}
 
 
void printMode(void) {
int **mp;
 
for (mp = &m[0]; mp < &m[9]; mp++) {
selectChar(*mp);
}
}
 
 
void showAttributes(void) {
char *cp;
 
printMode();
printf("%4d/%4d", arbuf.uid, arbuf.gid);
printf("%8ld", arbuf.size);
cp = ctime(&arbuf.date);
printf(" %-12.12s %-4.4s ", cp + 4, cp + 20);
}
 
 
/**************************************************************/
 
 
void mesg(int c) {
if (flg['v' - 'a']) {
printf("%c - %s\n", c, file);
}
}
 
 
char *trim(char *s) {
char *p1;
char *p2;
 
for (p1 = s; *p1 != '\0'; p1++) ;
while (p1 > s) {
if (*--p1 != '/') {
break;
}
*p1 = '\0';
}
p2 = s;
for (p1 = s; *p1 != '\0'; p1++) {
if (*p1 == '/') {
p2 = p1 + 1;
}
}
return p2;
}
 
 
int notFound(void) {
int n;
int i;
 
n = 0;
for (i = 0; i < namc; i++) {
if (namv[i] != NULL) {
fprintf(stderr, "ar: %s not found\n", namv[i]);
n++;
}
}
return n;
}
 
 
int moreFiles(void) {
int n;
int i;
 
n = 0;
for (i = 0; i < namc; i++) {
if (namv[i] != NULL) {
n++;
}
}
return n;
}
 
 
void unlinkTempFiles(void) {
if (tf0nam != NULL) {
unlink(tf0nam);
}
if (tf1nam != NULL) {
unlink(tf1nam);
}
if (tf2nam != NULL) {
unlink(tf2nam);
}
}
 
 
void done(int c) {
unlinkTempFiles();
exit(c);
}
 
 
void sigDone(int signum) {
done(100);
}
 
 
void noArchive(void) {
fprintf(stderr, "ar: %s does not exist\n", arnam);
done(1);
}
 
 
void writeError(void) {
perror("ar write error");
done(1);
}
 
 
void phaseError(void) {
fprintf(stderr, "ar: phase error on %s\n", file);
}
 
 
int stats(void) {
int f;
 
f = open(file, O_RDONLY);
if (f < 0) {
return f;
}
if (fstat(f, &stbuf) < 0) {
close(f);
return -1;
}
return f;
}
 
 
int match(void) {
int i;
 
for (i = 0; i < namc; i++) {
if (namv[i] == NULL) {
continue;
}
if (strcmp(trim(namv[i]), file) == 0) {
file = namv[i];
namv[i] = NULL;
return 1;
}
}
return 0;
}
 
 
void baMatch(void) {
int f;
 
if (baState == 1) {
if (strcmp(file, posName) != 0) {
return;
}
baState = 2;
if (flg['a' - 'a']) {
return;
}
}
if (baState == 2) {
baState = 0;
tf1nam = mktemp(tmp1nam);
close(creat(tf1nam, 0600));
f = open(tf1nam, O_RDWR);
if (f < 0) {
fprintf(stderr, "ar: cannot create second temp file\n");
return;
}
tf1 = tf0;
tf0 = f;
}
}
 
 
/**************************************************************/
 
 
void init(void) {
unsigned int mbuf;
 
write4ToEco((unsigned char *) &mbuf, AR_MAGIC);
tf0nam = mktemp(tmp0nam);
close(creat(tf0nam, 0600));
tf0 = open(tf0nam, O_RDWR);
if (tf0 < 0) {
fprintf(stderr, "ar: cannot create temp file\n");
done(1);
}
if (write(tf0, &mbuf, sizeof(mbuf)) != sizeof(mbuf)) {
writeError();
}
}
 
 
int getArchive(void) {
unsigned int mbuf;
 
af = open(arnam, O_RDONLY);
if (af < 0) {
return 1;
}
if (read(af, &mbuf, sizeof(mbuf)) != sizeof(mbuf) ||
read4FromEco((unsigned char *) &mbuf) != AR_MAGIC) {
fprintf(stderr, "ar: %s not in archive format\n", arnam);
done(1);
}
return 0;
}
 
 
void getQuick(void) {
unsigned int mbuf;
 
qf = open(arnam, O_RDWR);
if (qf < 0) {
if (!flg['c' - 'a']) {
fprintf(stderr, "ar: creating %s\n", arnam);
}
close(creat(arnam, 0666));
qf = open(arnam, O_RDWR);
if (qf < 0) {
fprintf(stderr, "ar: cannot create %s\n", arnam);
done(1);
}
write4ToEco((unsigned char *) &mbuf, AR_MAGIC);
if (write(qf, &mbuf, sizeof(mbuf)) != sizeof(mbuf)) {
writeError();
}
} else
if (read(qf, &mbuf, sizeof(mbuf)) != sizeof(mbuf) ||
read4FromEco((unsigned char *) &mbuf) != AR_MAGIC) {
fprintf(stderr, "ar: %s not in archive format\n", arnam);
done(1);
}
}
 
 
int getMember(void) {
int i;
 
i = read(af, &arbuf, sizeof(arbuf));
if (i != sizeof(arbuf)) {
if (tf1nam != NULL) {
i = tf0;
tf0 = tf1;
tf1 = i;
}
return 1;
}
conv4FromEcoToNative((unsigned char *) &arbuf.date);
conv4FromEcoToNative((unsigned char *) &arbuf.uid);
conv4FromEcoToNative((unsigned char *) &arbuf.gid);
conv4FromEcoToNative((unsigned char *) &arbuf.mode);
conv4FromEcoToNative((unsigned char *) &arbuf.size);
for (i = 0; i < MAX_NAME; i++) {
name[i] = arbuf.name[i];
}
file = name;
return 0;
}
 
 
void copyFile(int fi, int fo, int flags) {
int pe;
int icount, ocount;
int pad;
 
if (flags & HEAD) {
conv4FromNativeToEco((unsigned char *) &arbuf.date);
conv4FromNativeToEco((unsigned char *) &arbuf.uid);
conv4FromNativeToEco((unsigned char *) &arbuf.gid);
conv4FromNativeToEco((unsigned char *) &arbuf.mode);
conv4FromNativeToEco((unsigned char *) &arbuf.size);
if (write(fo, &arbuf, sizeof(arbuf)) != sizeof(arbuf)) {
writeError();
}
conv4FromEcoToNative((unsigned char *) &arbuf.date);
conv4FromEcoToNative((unsigned char *) &arbuf.uid);
conv4FromEcoToNative((unsigned char *) &arbuf.gid);
conv4FromEcoToNative((unsigned char *) &arbuf.mode);
conv4FromEcoToNative((unsigned char *) &arbuf.size);
}
pe = 0;
while (arbuf.size > 0) {
icount = ocount = BUFSIZE;
if (arbuf.size < icount) {
icount = ocount = arbuf.size;
pad = -icount & 0x03;
if (flags & IODD) {
icount += pad;
}
if (flags & OODD) {
ocount += pad;
}
}
if (read(fi, buf, icount) != icount) {
pe++;
}
if ((flags & SKIP) == 0) {
if (write(fo, buf, ocount) != ocount) {
writeError();
}
}
arbuf.size -= BUFSIZE;
}
if (pe != 0) {
phaseError();
}
}
 
 
void moveFile(int f) {
char *cp;
int i;
 
cp = trim(file);
for (i = 0; i < MAX_NAME; i++) {
if ((arbuf.name[i] = *cp) != '\0') {
cp++;
}
}
arbuf.size = stbuf.st_size;
arbuf.date = stbuf.st_mtime;
arbuf.uid = stbuf.st_uid;
arbuf.gid = stbuf.st_gid;
arbuf.mode = stbuf.st_mode;
copyFile(f, tf0, OODD | HEAD);
close(f);
}
 
 
void install(void) {
int i;
 
for (i = 0; signums[i] != 0; i++) {
signal(signums[i], SIG_IGN);
}
if (af < 0) {
if (!flg['c' - 'a']) {
fprintf(stderr, "ar: creating %s\n", arnam);
}
}
close(af);
af = creat(arnam, 0666);
if (af < 0) {
fprintf(stderr, "ar: cannot create %s\n", arnam);
done(1);
}
if (tf0nam != NULL) {
lseek(tf0, 0, SEEK_SET);
while ((i = read(tf0, buf, BUFSIZE)) > 0) {
if (write(af, buf, i) != i) {
writeError();
}
}
}
if (tf2nam != NULL) {
lseek(tf2, 0, SEEK_SET);
while ((i = read(tf2, buf, BUFSIZE)) > 0) {
if (write(af, buf, i) != i) {
writeError();
}
}
}
if (tf1nam != NULL) {
lseek(tf1, 0, SEEK_SET);
while ((i = read(tf1, buf, BUFSIZE)) > 0) {
if (write(af, buf, i) != i) {
writeError();
}
}
}
}
 
 
void cleanup(void) {
int i;
int f;
 
for (i = 0; i < namc; i++) {
file = namv[i];
if (file == NULL) {
continue;
}
namv[i] = NULL;
mesg('a');
f = stats();
if (f < 0) {
fprintf(stderr, "ar: cannot open %s\n", file);
continue;
}
moveFile(f);
}
}
 
 
/**************************************************************/
 
 
void dCmd(void) {
init();
if (getArchive()) {
noArchive();
}
while (!getMember()) {
if (match()) {
mesg('d');
copyFile(af, -1, IODD | SKIP);
continue;
}
mesg('c');
copyFile(af, tf0, IODD | OODD | HEAD);
}
install();
}
 
 
void rCmd(void) {
int f;
 
init();
getArchive();
while (!getMember()) {
baMatch();
if (namc == 0 || match()) {
f = stats();
if (f < 0) {
if (namc != 0) {
fprintf(stderr, "ar: cannot open %s\n", file);
}
goto cp;
}
if (flg['u' - 'a']) {
if (stbuf.st_mtime <= arbuf.date) {
close(f);
goto cp;
}
}
mesg('r');
copyFile(af, -1, IODD | SKIP);
moveFile(f);
continue;
}
cp:
mesg('c');
copyFile(af, tf0, IODD | OODD | HEAD);
}
cleanup();
install();
}
 
 
void qCmd(void) {
int i;
int f;
 
if (flg['a' - 'a'] || flg['b' - 'a']) {
fprintf(stderr, "ar: [ab] not allowed with -q\n");
done(1);
}
getQuick();
for (i = 0; signums[i] != 0; i++) {
signal(signums[i], SIG_IGN);
}
lseek(qf, 0, SEEK_END);
for (i = 0; i < namc; i++) {
file = namv[i];
if (file == NULL) {
continue;
}
namv[i] = NULL;
mesg('q');
f = stats();
if (f < 0) {
fprintf(stderr, "ar: cannot open %s\n", file);
continue;
}
tf0 = qf;
moveFile(f);
qf = tf0;
}
}
 
 
void tCmd(void) {
if (getArchive()) {
noArchive();
}
while (!getMember()) {
if (namc == 0 || match()) {
if (flg['v' - 'a']) {
showAttributes();
}
printf("%s\n", trim(file));
}
copyFile(af, -1, IODD | SKIP);
}
}
 
 
void pCmd(void) {
if (getArchive()) {
noArchive();
}
while (!getMember()) {
if (namc == 0 || match()) {
if (flg['v' - 'a']) {
printf("\n<%s>\n\n", file);
fflush(stdout);
}
copyFile(af, 1, IODD);
continue;
}
copyFile(af, -1, IODD | SKIP);
}
}
 
 
void mCmd(void) {
init();
if (getArchive()) {
noArchive();
}
tf2nam = mktemp(tmp2nam);
close(creat(tf2nam, 0600));
tf2 = open(tf2nam, O_RDWR);
if (tf2 < 0) {
fprintf(stderr, "ar: cannot create third temp file\n");
done(1);
}
while (!getMember()) {
baMatch();
if (match()) {
mesg('m');
copyFile(af, tf2, IODD | OODD | HEAD);
continue;
}
mesg('c');
copyFile(af, tf0, IODD | OODD | HEAD);
}
install();
}
 
 
void xCmd(void) {
int f;
 
if (getArchive()) {
noArchive();
}
while (!getMember()) {
if (namc == 0 || match()) {
f = creat(file, arbuf.mode & 0777);
if (f < 0) {
fprintf(stderr, "ar: cannot create %s\n", file);
goto sk;
}
mesg('x');
copyFile(af, f, IODD);
close(f);
continue;
}
sk:
mesg('c');
copyFile(af, -1, IODD | SKIP);
if (namc > 0 && !moreFiles()) {
done(0);
}
}
}
 
 
/**************************************************************/
 
/* specialized r command for updating symbols */
 
 
int exec_rCmd(int create, char *args[]) {
int i;
int res;
 
/* reset all global variables */
comfun = NULL;
for (i = 0; i < 26; i++) {
flg[i] = 0;
}
arnam = NULL;
af = 0;
namv = NULL;
namc = 0;
baState = 0;
posName = NULL;
for (i = 0; i < 20; i++) {
tmp0nam[i] = '\0';
tmp1nam[i] = '\0';
tmp2nam[i] = '\0';
}
tf0nam = NULL;
tf1nam = NULL;
tf2nam = NULL;
tf0 = 0;
tf1 = 0;
tf2 = 0;
qf = 0;
file = NULL;
for (i = 0; i < MAX_NAME; i++) {
name[i] = '\0';
}
/* prepare arguments, call r command, cleanup */
comfun = rCmd;
flg['l' - 'a'] = 1;
strcpy(tmp0nam, "v0XXXXXX");
strcpy(tmp1nam, "v1XXXXXX");
strcpy(tmp2nam, "v2XXXXXX");
if (create) {
/* ar -rlb firstName archive TEMP_NAME */
flg['b' - 'a'] = 1;
baState = 1;
posName = trim(args[0]);
arnam = args[1];
namv = &args[2];
namc = 1;
} else {
/* ar -rl archive TEMP_NAME */
arnam = args[0];
namv = &args[1];
namc = 1;
}
(*comfun)();
res = notFound();
unlinkTempFiles();
return res;
}
 
 
/**************************************************************/
 
 
void usage(void) {
printf("usage: ar -[%s][%s] archive files ...\n", com, opt);
done(1);
}
 
 
void setcom(void (*fun)(void)) {
if (comfun != NULL) {
fprintf(stderr, "ar: only one of [%s] allowed\n", com);
done(1);
}
comfun = fun;
}
 
 
int cmdCanChangeSymbols(void) {
return comfun == dCmd ||
comfun == rCmd ||
comfun == mCmd;
}
 
 
int main(int argc, char *argv[]) {
int i;
char *cp;
int res;
 
for (i = 0; signums[i] != 0; i++) {
if (signal(signums[i], SIG_IGN) != SIG_IGN) {
signal(signums[i], sigDone);
}
}
strcpy(tmp0nam, "/tmp/v0XXXXXX");
strcpy(tmp1nam, "/tmp/v1XXXXXX");
strcpy(tmp2nam, "/tmp/v2XXXXXX");
if (argc < 3 || *argv[1] != '-') {
usage();
}
for (cp = argv[1] + 1; *cp != '\0'; cp++) {
switch (*cp) {
case 'd':
setcom(dCmd);
break;
case 'r':
setcom(rCmd);
break;
case 'q':
setcom(qCmd);
break;
case 't':
setcom(tCmd);
break;
case 'p':
setcom(pCmd);
break;
case 'm':
setcom(mCmd);
break;
case 'x':
setcom(xCmd);
break;
case 'v':
case 'u':
case 'a':
case 'b':
case 'c':
case 'l':
case 's':
flg[*cp - 'a'] = 1;
break;
default:
fprintf(stderr, "ar: bad option '%c'\n", *cp);
done(1);
}
}
if (flg['l' - 'a']) {
strcpy(tmp0nam, "v0XXXXXX");
strcpy(tmp1nam, "v1XXXXXX");
strcpy(tmp2nam, "v2XXXXXX");
}
if (flg['a' - 'a'] || flg['b' - 'a']) {
baState = 1;
posName = trim(argv[2]);
argv++;
argc--;
if (argc < 3) {
usage();
}
}
arnam = argv[2];
namv = argv + 3;
namc = argc - 3;
if (comfun == NULL && !flg['s' - 'a']) {
fprintf(stderr, "ar: one of [%ss] must be specified\n", com);
done(1);
}
res = 0;
if (comfun != NULL) {
(*comfun)();
res = notFound();
unlinkTempFiles();
if (res != 0) {
return res;
}
}
if (flg['s' - 'a'] ||
(cmdCanChangeSymbols() && hasSymbols(arnam))) {
res = updateSymbols(arnam, flg['v' - 'a']);
}
return res;
}
/binutils/ar/endian.h
0,0 → 1,16
/*
* endian.h -- endianness conversions
*/
 
 
#ifndef _ENDIAN_H_
#define _ENDIAN_H_
 
 
unsigned int read4FromEco(unsigned char *p);
void write4ToEco(unsigned char *p, unsigned int data);
void conv4FromEcoToNative(unsigned char *p);
void conv4FromNativeToEco(unsigned char *p);
 
 
#endif /* _ENDIAN_H_ */
/binutils/ar/ranlib.c
0,0 → 1,367
/*
* ranlib.c -- archive index generator
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
 
#include "endian.h"
#include "ranlib.h"
#include "../include/ar.h"
#include "../include/a.out.h"
 
 
#define TEMP_NAME "__.SYMDEF"
 
#define STRING_SIZE_INIT 1024
#define STRING_SIZE_GROW 2
 
#define MAX_SYM_ENTRIES 1000
 
#define MSB ((unsigned int) 1 << (sizeof(unsigned int) * 8 - 1))
 
 
typedef struct {
unsigned int name; /* name of symbol (as offset into string space) */
off_t position; /* position of member which defines the symbol */
/* (as file offset to the member's ArHeader) */
} Entry;
 
 
FILE *fi;
FILE *fo;
 
off_t nxtOff; /* file offset to next member */
off_t curOff;
 
Entry table[MAX_SYM_ENTRIES];
int numEntries;
 
int createIndex;
char firstName[MAX_NAME];
 
ArHeader arhdr;
ExecHeader exhdr;
 
 
/**************************************************************/
 
 
char *stringArea = NULL;
unsigned int sizeAllocated = 0;
unsigned int sizeUsed = 0;
 
 
unsigned int getStringPos(void) {
return sizeUsed;
}
 
 
void storeCharacter(char c) {
unsigned int newSize;
char *newArea;
 
if (sizeUsed + 1 > sizeAllocated) {
if (sizeAllocated == 0) {
newSize = STRING_SIZE_INIT;
} else {
newSize = STRING_SIZE_GROW * sizeAllocated;
}
newArea = malloc(newSize);
if (newArea == NULL) {
fprintf(stderr, "ar: cannot allocate string area\n");
exit(1);
}
if (stringArea != NULL) {
memcpy(newArea, stringArea, sizeUsed);
free(stringArea);
}
stringArea = newArea;
sizeAllocated = newSize;
}
stringArea[sizeUsed++] = c;
}
 
 
/**************************************************************/
 
 
int nextMember(void) {
int pad;
 
curOff = nxtOff;
fseek(fi, nxtOff, SEEK_SET);
if (fread(&arhdr, sizeof(arhdr), 1, fi) != 1) {
return 0;
}
conv4FromEcoToNative((unsigned char *) &arhdr.date);
conv4FromEcoToNative((unsigned char *) &arhdr.uid);
conv4FromEcoToNative((unsigned char *) &arhdr.gid);
conv4FromEcoToNative((unsigned char *) &arhdr.mode);
conv4FromEcoToNative((unsigned char *) &arhdr.size);
pad = -arhdr.size & 0x03;
arhdr.size += pad;
nxtOff = ftell(fi) + arhdr.size;
return 1;
}
 
 
void addSymbol(unsigned int nameOffset) {
off_t curPos;
int c;
 
if (numEntries >= MAX_SYM_ENTRIES) {
fprintf(stderr, "ar: symbol table overflow\n");
exit(1);
}
table[numEntries].name = getStringPos();
table[numEntries].position = curOff;
numEntries++;
curPos = ftell(fi);
fseek(fi, curOff + sizeof(arhdr) + nameOffset, SEEK_SET);
do {
c = fgetc(fi);
storeCharacter(c);
} while (c != 0) ;
fseek(fi, curPos, SEEK_SET);
}
 
 
void fixSize(void) {
off_t deltaOff;
int pad;
int i;
 
deltaOff = sizeof(arhdr) + sizeof(int) +
numEntries * sizeof(Entry) + getStringPos();
pad = -deltaOff & 0x03;
deltaOff += pad;
nxtOff = sizeof(unsigned int);
nextMember();
if(strncmp(arhdr.name, TEMP_NAME, MAX_NAME) == 0) {
/* there is an index already present */
createIndex = 0;
deltaOff -= sizeof(arhdr) + arhdr.size;
} else {
/* no index yet present, create new one */
createIndex = 1;
strncpy(firstName, arhdr.name, MAX_NAME);
}
for (i = 0; i < numEntries; i++) {
table[i].position += deltaOff;
}
}
 
 
/**************************************************************/
 
 
void showSymdefs(char *symdefs) {
FILE *in;
int numSymbols;
int i;
Entry e;
off_t curPos;
off_t pos;
int c;
 
in = fopen(symdefs, "r");
if (in == NULL) {
printf("error: cannot open symdef file '%s'\n", symdefs);
exit(1);
}
if (fread(&numSymbols, sizeof(int), 1, in) != 1) {
printf("cannot read symdef file\n");
exit(1);
}
conv4FromEcoToNative((unsigned char *) &numSymbols);
printf("%d symbols\n", numSymbols);
for (i = 0; i < numSymbols; i++) {
if (fread(&e, sizeof(e), 1, in) != 1) {
printf("cannot read symdef file\n");
exit(1);
}
conv4FromEcoToNative((unsigned char *) &e.name);
conv4FromEcoToNative((unsigned char *) &e.position);
printf("%4d: name = 0x%08X, position = 0x%08lX, string = '",
i, e.name, e.position);
curPos = ftell(in);
pos = sizeof(int) + numSymbols * sizeof(Entry) + e.name;
fseek(in, pos, SEEK_SET);
while (1) {
c = fgetc(in);
if (c == EOF) {
printf("\nerror: unexpected end of file\n");
exit(1);
}
if (c == 0) {
break;
}
printf("%c", c);
}
printf("'\n");
fseek(in, curPos, SEEK_SET);
}
fclose(in);
}
 
 
/**************************************************************/
 
 
int hasSymbols(char *archive) {
unsigned int arMagic;
int res;
 
fi = fopen(archive, "r");
if (fi == NULL) {
return 0;
}
nxtOff = sizeof(unsigned int);
if (fread(&arMagic, sizeof(arMagic), 1, fi) != 1 ||
read4FromEco((unsigned char *) &arMagic) != AR_MAGIC) {
fclose(fi);
return 0;
}
fseek(fi, 0, SEEK_SET);
if (nextMember() == 0) {
fclose(fi);
return 0;
}
fclose(fi);
res = (strncmp(arhdr.name, TEMP_NAME, MAX_NAME) == 0);
return res;
}
 
 
int updateSymbols(char *archive, int verbose) {
unsigned int arMagic;
unsigned int skip;
int numSymbols;
unsigned int stringStart;
SymbolRecord symbol;
int i;
char *args[3];
int res;
 
if (verbose) {
printf("ar: updating symbols in %s\n", archive);
}
fi = fopen(archive, "r");
if (fi == NULL) {
fprintf(stderr, "ar: cannot re-open %s\n", archive);
return 1;
}
nxtOff = sizeof(unsigned int);
if (fread(&arMagic, sizeof(arMagic), 1, fi) != 1 ||
read4FromEco((unsigned char *) &arMagic) != AR_MAGIC) {
fprintf(stderr, "ar: %s not in archive format\n", archive);
fclose(fi);
return 1;
}
fseek(fi, 0, SEEK_SET);
numEntries = 0;
if (nextMember() == 0) {
fclose(fi);
return 0;
}
/* iterate over archive members */
do {
if (fread(&exhdr, sizeof(exhdr), 1, fi) != 1 ||
read4FromEco((unsigned char *) &exhdr.magic) != EXEC_MAGIC) {
/* archive member not in proper format - skip */
continue;
}
conv4FromEcoToNative((unsigned char *) &exhdr.magic);
conv4FromEcoToNative((unsigned char *) &exhdr.csize);
conv4FromEcoToNative((unsigned char *) &exhdr.dsize);
conv4FromEcoToNative((unsigned char *) &exhdr.bsize);
conv4FromEcoToNative((unsigned char *) &exhdr.crsize);
conv4FromEcoToNative((unsigned char *) &exhdr.drsize);
conv4FromEcoToNative((unsigned char *) &exhdr.symsize);
conv4FromEcoToNative((unsigned char *) &exhdr.strsize);
skip = exhdr.csize + exhdr.dsize + exhdr.crsize + exhdr.drsize;
fseek(fi, skip, SEEK_CUR);
numSymbols = exhdr.symsize / sizeof(SymbolRecord);
if (numSymbols == 0) {
fprintf(stderr,
"ar: symbol table of %s is empty\n",
arhdr.name);
continue;
}
stringStart = sizeof(exhdr) + skip + exhdr.symsize;
/* iterate over symbols */
while (--numSymbols >= 0) {
if (fread(&symbol, sizeof(symbol), 1, fi) != 1) {
fprintf(stderr, "ar: cannot read archive\n");
break;
}
conv4FromEcoToNative((unsigned char *) &symbol.name);
conv4FromEcoToNative((unsigned char *) &symbol.type);
conv4FromEcoToNative((unsigned char *) &symbol.value);
if ((symbol.type & MSB) == 0) {
/* this is an exported symbol */
addSymbol(stringStart + symbol.name);
}
}
} while (nextMember() != 0) ;
fixSize();
fclose(fi);
fo = fopen(TEMP_NAME, "w");
if (fo == NULL) {
fprintf(stderr, "ar: can't create temporary file\n");
return 1;
}
conv4FromNativeToEco((unsigned char *) &numEntries);
if (fwrite(&numEntries, sizeof(numEntries), 1, fo) != 1) {
fprintf(stderr, "ar: can't write temporary file\n");
fclose(fo);
unlink(TEMP_NAME);
return 1;
}
conv4FromEcoToNative((unsigned char *) &numEntries);
for (i = 0; i < numEntries; i++) {
conv4FromNativeToEco((unsigned char *) &table[i].name);
conv4FromNativeToEco((unsigned char *) &table[i].position);
}
if (fwrite(table, sizeof(Entry), numEntries, fo) != numEntries) {
fprintf(stderr, "ar: can't write temporary file\n");
fclose(fo);
unlink(TEMP_NAME);
return 1;
}
for (i = 0; i < numEntries; i++) {
conv4FromEcoToNative((unsigned char *) &table[i].name);
conv4FromEcoToNative((unsigned char *) &table[i].position);
}
if (fwrite(stringArea, 1, getStringPos(), fo) != getStringPos()) {
fprintf(stderr, "ar: can't write temporary file\n");
fclose(fo);
unlink(TEMP_NAME);
return 1;
}
fclose(fo);
if (verbose) {
showSymdefs(TEMP_NAME);
}
if (createIndex) {
/* ar -rlb firstName archive TEMP_NAME */
args[0] = firstName;
args[1] = archive;
args[2] = TEMP_NAME;
res = exec_rCmd(1, args);
} else {
/* ar -rl archive TEMP_NAME */
args[0] = archive;
args[1] = TEMP_NAME;
args[2] = NULL;
res = exec_rCmd(0, args);
}
unlink(TEMP_NAME);
return res;
}
/binutils/ar/ranlib.h
0,0 → 1,16
/*
* ranlib.c - archive index generator
*/
 
 
#ifndef _RANLIB_H_
#define _RANLIB_H_
 
 
int hasSymbols(char *archive);
int updateSymbols(char *archive, int verbose);
 
int exec_rCmd(int create, char *args[]);
 
 
#endif /* _RANLIB_H_ */
/binutils/ar/Makefile
0,0 → 1,36
#
# Makefile for ECO32 archiver
#
 
BUILD = ../../build
 
CC = gcc -m32
CFLAGS = -g -Wall
LDFLAGS = -g
LDLIBS = -lm
 
SRCS = ar.c ranlib.c endian.c
OBJS = $(patsubst %.c,%.o,$(SRCS))
BIN = ar
 
.PHONY: all install clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/bin
cp $(BIN) $(BUILD)/bin
 
$(BIN): $(OBJS)
$(CC) $(LDFLAGS) -o $(BIN) $(OBJS) $(LDLIBS)
 
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
 
depend.mak:
$(CC) -MM -MG $(CFLAGS) $(SRCS) > depend.mak
 
-include depend.mak
 
clean:
rm -f *~ $(OBJS) $(BIN) depend.mak
/binutils/as/as.c
0,0 → 1,2175
/*
* as.c -- ECO32 assembler
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <unistd.h>
 
#include "../include/a.out.h"
 
 
/**************************************************************/
 
 
#define NUM_REGS 32
#define AUX_REG 1
 
#define LINE_SIZE 200
 
#define TOK_EOL 0
#define TOK_LABEL 1
#define TOK_IDENT 2
#define TOK_STRING 3
#define TOK_NUMBER 4
#define TOK_REGISTER 5
#define TOK_PLUS 6
#define TOK_MINUS 7
#define TOK_STAR 8
#define TOK_SLASH 9
#define TOK_PERCENT 10
#define TOK_LSHIFT 11
#define TOK_RSHIFT 12
#define TOK_LPAREN 13
#define TOK_RPAREN 14
#define TOK_COMMA 15
#define TOK_TILDE 16
#define TOK_AMPER 17
#define TOK_BAR 18
#define TOK_CARET 19
 
#define STATUS_UNKNOWN 0 /* symbol is not yet defined */
#define STATUS_DEFINED 1 /* symbol is defined */
#define STATUS_GLOBREF 2 /* local entry refers to a global one */
 
#define GLOBAL_TABLE 0 /* global symbol table identifier */
#define LOCAL_TABLE 1 /* local symbol table identifier */
 
#define MSB ((unsigned int) 1 << (sizeof(unsigned int) * 8 - 1))
 
 
/**************************************************************/
 
 
#define OP_ADD 0x00
#define OP_ADDI 0x01
#define OP_SUB 0x02
#define OP_SUBI 0x03
 
#define OP_MUL 0x04
#define OP_MULI 0x05
#define OP_MULU 0x06
#define OP_MULUI 0x07
#define OP_DIV 0x08
#define OP_DIVI 0x09
#define OP_DIVU 0x0A
#define OP_DIVUI 0x0B
#define OP_REM 0x0C
#define OP_REMI 0x0D
#define OP_REMU 0x0E
#define OP_REMUI 0x0F
 
#define OP_AND 0x10
#define OP_ANDI 0x11
#define OP_OR 0x12
#define OP_ORI 0x13
#define OP_XOR 0x14
#define OP_XORI 0x15
#define OP_XNOR 0x16
#define OP_XNORI 0x17
 
#define OP_SLL 0x18
#define OP_SLLI 0x19
#define OP_SLR 0x1A
#define OP_SLRI 0x1B
#define OP_SAR 0x1C
#define OP_SARI 0x1D
 
#define OP_LDHI 0x1F
 
#define OP_BEQ 0x20
#define OP_BNE 0x21
#define OP_BLE 0x22
#define OP_BLEU 0x23
#define OP_BLT 0x24
#define OP_BLTU 0x25
#define OP_BGE 0x26
#define OP_BGEU 0x27
#define OP_BGT 0x28
#define OP_BGTU 0x29
 
#define OP_J 0x2A
#define OP_JR 0x2B
#define OP_JAL 0x2C
#define OP_JALR 0x2D
 
#define OP_TRAP 0x2E
#define OP_RFX 0x2F
 
#define OP_LDW 0x30
#define OP_LDH 0x31
#define OP_LDHU 0x32
#define OP_LDB 0x33
#define OP_LDBU 0x34
 
#define OP_STW 0x35
#define OP_STH 0x36
#define OP_STB 0x37
 
#define OP_MVFS 0x38
#define OP_MVTS 0x39
#define OP_TBS 0x3A
#define OP_TBWR 0x3B
#define OP_TBRI 0x3C
#define OP_TBWI 0x3D
 
 
/**************************************************************/
 
 
int debugToken = 0;
int debugCode = 0;
int debugFixup = 0;
 
char codeName[L_tmpnam];
char dataName[L_tmpnam];
char *outName = NULL;
char *inName = NULL;
 
FILE *codeFile = NULL;
FILE *dataFile = NULL;
FILE *outFile = NULL;
FILE *inFile = NULL;
 
char line[LINE_SIZE];
char *lineptr;
int lineno;
 
int token;
int tokenvalNumber;
char tokenvalString[LINE_SIZE];
 
int allowSyn = 1;
int currSeg = SEGMENT_CODE;
unsigned int segPtr[4] = { 0, 0, 0, 0 };
char *segName[4] = { "ABS", "CODE", "DATA", "BSS" };
char *methodName[5] = { "H16", "L16", "R16", "R26", "W32" };
 
 
typedef struct fixup {
int segment; /* in which segment */
unsigned int offset; /* at which offset */
int method; /* what kind of coding method is to be used */
int value; /* known part of value */
int base; /* segment which this ref is relative to */
/* valid only when used for relocation */
struct fixup *next; /* next fixup */
} Fixup;
 
 
typedef struct symbol {
char *name; /* name of symbol */
int status; /* status of symbol */
int segment; /* the symbol's segment */
int value; /* the symbol's value */
Fixup *fixups; /* list of locations to fix */
struct symbol *globref; /* set if this local refers to a global */
struct symbol *left; /* left son in binary search tree */
struct symbol *right; /* right son in binary search tree */
int skip; /* this symbol is not defined here nor is */
/* it used here: don't write to object file */
} Symbol;
 
 
/**************************************************************/
 
 
void error(char *fmt, ...) {
va_list ap;
 
va_start(ap, fmt);
fprintf(stderr, "Error: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
if (codeFile != NULL) {
fclose(codeFile);
codeFile = NULL;
}
if (dataFile != NULL) {
fclose(dataFile);
dataFile = NULL;
}
if (outFile != NULL) {
fclose(outFile);
outFile = NULL;
}
if (inFile != NULL) {
fclose(inFile);
inFile = NULL;
}
if (codeName != NULL) {
unlink(codeName);
}
if (dataName != NULL) {
unlink(dataName);
}
if (outName != NULL) {
unlink(outName);
}
exit(1);
}
 
 
void *allocateMemory(unsigned int size) {
void *p;
 
p = malloc(size);
if (p == NULL) {
error("out of memory");
}
return p;
}
 
 
void freeMemory(void *p) {
free(p);
}
 
 
/**************************************************************/
 
 
int getNextToken(void) {
char *p;
int base;
int digit;
 
while (*lineptr == ' ' || *lineptr == '\t') {
lineptr++;
}
if (*lineptr == '\n' || *lineptr == '\0' || *lineptr == ';') {
return TOK_EOL;
}
if (isalpha((int) *lineptr) || *lineptr == '_' || *lineptr == '.') {
p = tokenvalString;
while (isalnum((int) *lineptr) || *lineptr == '_' || *lineptr == '.') {
*p++ = *lineptr++;
}
*p = '\0';
if (*lineptr == ':') {
lineptr++;
return TOK_LABEL;
} else {
return TOK_IDENT;
}
}
if (isdigit((int) *lineptr)) {
base = 10;
tokenvalNumber = 0;
if (*lineptr == '0') {
lineptr++;
if (*lineptr == 'x' || *lineptr == 'X') {
base = 16;
lineptr++;
} else
if (isdigit((int) *lineptr)) {
base = 8;
} else {
return TOK_NUMBER;
}
}
while (isxdigit((int) *lineptr)) {
digit = *lineptr++ - '0';
if (digit >= 'A' - '0') {
if (digit >= 'a' - '0') {
digit += '0' - 'a' + 10;
} else {
digit += '0' - 'A' + 10;
}
}
if (digit >= base) {
error("illegal digit value %d in line %d", digit, lineno);
}
tokenvalNumber *= base;
tokenvalNumber += digit;
}
return TOK_NUMBER;
}
if (*lineptr == '\'') {
lineptr++;
if (!isprint((int) *lineptr)) {
error("cannot quote character 0x%02X in line %d", *lineptr, lineno);
}
tokenvalNumber = *lineptr;
lineptr++;
if (*lineptr != '\'') {
error("unbalanced quote in line %d", lineno);
}
lineptr++;
return TOK_NUMBER;
}
if (*lineptr == '\"') {
lineptr++;
p = tokenvalString;
while (1) {
if (*lineptr == '\n' || *lineptr == '\0') {
error("unterminated string constant in line %d", lineno);
}
if (!isprint((int) *lineptr)) {
error("string contains illegal character 0x%02X in line %d",
*lineptr, lineno);
}
if (*lineptr == '\"') {
break;
}
*p++ = *lineptr++;
}
lineptr++;
*p = '\0';
return TOK_STRING;
}
if (*lineptr == '$') {
lineptr++;
if (!isdigit((int) *lineptr)) {
error("register number expected after '$' in line %d", lineno);
}
tokenvalNumber = 0;
while (isdigit((int) *lineptr)) {
digit = *lineptr++ - '0';
tokenvalNumber *= 10;
tokenvalNumber += digit;
}
if (tokenvalNumber < 0 || tokenvalNumber >= NUM_REGS) {
error("illegal register number %d in line %d", tokenvalNumber, lineno);
}
return TOK_REGISTER;
}
if (*lineptr == '+') {
lineptr++;
return TOK_PLUS;
}
if (*lineptr == '-') {
lineptr++;
return TOK_MINUS;
}
if (*lineptr == '*') {
lineptr++;
return TOK_STAR;
}
if (*lineptr == '/') {
lineptr++;
return TOK_SLASH;
}
if (*lineptr == '%') {
lineptr++;
return TOK_PERCENT;
}
if (*lineptr == '<' && *(lineptr + 1) == '<') {
lineptr += 2;
return TOK_LSHIFT;
}
if (*lineptr == '>' && *(lineptr + 1) == '>') {
lineptr += 2;
return TOK_RSHIFT;
}
if (*lineptr == '(') {
lineptr++;
return TOK_LPAREN;
}
if (*lineptr == ')') {
lineptr++;
return TOK_RPAREN;
}
if (*lineptr == ',') {
lineptr++;
return TOK_COMMA;
}
if (*lineptr == '~') {
lineptr++;
return TOK_TILDE;
}
if (*lineptr == '&') {
lineptr++;
return TOK_AMPER;
}
if (*lineptr == '|') {
lineptr++;
return TOK_BAR;
}
if (*lineptr == '^') {
lineptr++;
return TOK_CARET;
}
error("illegal character 0x%02X in line %d", *lineptr, lineno);
return 0;
}
 
 
void showToken(void) {
printf("DEBUG: ");
switch (token) {
case TOK_EOL:
printf("token = TOK_EOL\n");
break;
case TOK_LABEL:
printf("token = TOK_LABEL, value = %s\n", tokenvalString);
break;
case TOK_IDENT:
printf("token = TOK_IDENT, value = %s\n", tokenvalString);
break;
case TOK_STRING:
printf("token = TOK_STRING, value = %s\n", tokenvalString);
break;
case TOK_NUMBER:
printf("token = TOK_NUMBER, value = 0x%x\n", tokenvalNumber);
break;
case TOK_REGISTER:
printf("token = TOK_REGISTER, value = %d\n", tokenvalNumber);
break;
case TOK_PLUS:
printf("token = TOK_PLUS\n");
break;
case TOK_MINUS:
printf("token = TOK_MINUS\n");
break;
case TOK_STAR:
printf("token = TOK_STAR\n");
break;
case TOK_SLASH:
printf("token = TOK_SLASH\n");
break;
case TOK_PERCENT:
printf("token = TOK_PERCENT\n");
break;
case TOK_LSHIFT:
printf("token = TOK_LSHIFT\n");
break;
case TOK_RSHIFT:
printf("token = TOK_RSHIFT\n");
break;
case TOK_LPAREN:
printf("token = TOK_LPAREN\n");
break;
case TOK_RPAREN:
printf("token = TOK_RPAREN\n");
break;
case TOK_COMMA:
printf("token = TOK_COMMA\n");
break;
case TOK_TILDE:
printf("token = TOK_TILDE\n");
break;
case TOK_AMPER:
printf("token = TOK_AMPER\n");
break;
case TOK_BAR:
printf("token = TOK_BAR\n");
break;
case TOK_CARET:
printf("token = TOK_CARET\n");
break;
default:
error("illegal token %d in showToken()", token);
}
}
 
 
void getToken(void) {
token = getNextToken();
if (debugToken) {
showToken();
}
}
 
 
static char *tok2str[] = {
"end-of-line",
"label",
"identifier",
"string",
"number",
"register",
"+",
"-",
"*",
"/",
"%",
"<<",
">>",
"(",
")",
",",
"~",
"&",
"|",
"^"
};
 
 
void expect(int expected) {
if (token != expected) {
error("'%s' expected, got '%s' in line %d",
tok2str[expected], tok2str[token], lineno);
}
}
 
 
/**************************************************************/
 
 
Fixup *fixupList = NULL;
 
 
Fixup *newFixup(int segment, unsigned int offset, int method, int value) {
Fixup *f;
 
f = allocateMemory(sizeof(Fixup));
f->segment = segment;
f->offset = offset;
f->method = method;
f->value = value;
f->base = 0;
f->next = NULL;
return f;
}
 
 
void addFixup(Symbol *s,
int segment, unsigned int offset, int method, int value) {
Fixup *f;
 
if (debugFixup) {
printf("DEBUG: fixup (s:%s, o:%08X, m:%s, v:%08X) added to '%s'\n",
segName[segment], offset, methodName[method], value, s->name);
}
f = newFixup(segment, offset, method, value);
f->next = s->fixups;
s->fixups = f;
}
 
 
/**************************************************************/
 
 
Symbol *globalTable = NULL;
Symbol *localTable = NULL;
 
 
Symbol *deref(Symbol *s) {
if (s->status == STATUS_GLOBREF) {
return s->globref;
} else {
return s;
}
}
 
 
Symbol *newSymbol(char *name) {
Symbol *p;
 
p = allocateMemory(sizeof(Symbol));
p->name = allocateMemory(strlen(name) + 1);
strcpy(p->name, name);
p->status = STATUS_UNKNOWN;
p->segment = 0;
p->value = 0;
p->fixups = NULL;
p->globref = NULL;
p->left = NULL;
p->right = NULL;
return p;
}
 
 
Symbol *lookupEnter(char *name, int whichTable) {
Symbol *p, *q, *r;
int cmp;
 
if (whichTable == GLOBAL_TABLE) {
p = globalTable;
} else {
p = localTable;
}
if (p == NULL) {
r = newSymbol(name);
if (whichTable == GLOBAL_TABLE) {
globalTable = r;
} else {
localTable = r;
}
return r;
}
while (1) {
q = p;
cmp = strcmp(name, q->name);
if (cmp == 0) {
return q;
}
if (cmp < 0) {
p = q->left;
} else {
p = q->right;
}
if (p == NULL) {
r = newSymbol(name);
if (cmp < 0) {
q->left = r;
} else {
q->right = r;
}
return r;
}
}
}
 
 
static void linkSymbol(Symbol *s) {
Fixup *f;
 
if (s->status == STATUS_UNKNOWN) {
error("undefined symbol '%s'", s->name);
}
if (s->status == STATUS_GLOBREF) {
if (s->fixups != NULL) {
error("local fixups detected with global symbol '%s'", s->name);
}
} else {
if (debugFixup) {
printf("DEBUG: link '%s' (s:%s, v:%08X)\n",
s->name, segName[s->segment], s->value);
}
while (s->fixups != NULL) {
/* get next fixup record */
f = s->fixups;
s->fixups = f->next;
/* add the symbol's value to the value in the record */
/* and remember the symbol's segment */
if (debugFixup) {
printf(" (s:%s, o:%08X, m:%s, v:%08X --> %08X, b:%s)\n",
segName[f->segment], f->offset, methodName[f->method],
f->value, f->value + s->value, segName[s->segment]);
}
f->value += s->value;
f->base = s->segment;
/* transfer the record to the fixup list */
f->next = fixupList;
fixupList = f;
}
}
}
 
 
static void linkTree(Symbol *s) {
if (s == NULL) {
return;
}
linkTree(s->left);
linkSymbol(s);
linkTree(s->right);
freeMemory(s->name);
freeMemory(s);
}
 
 
void linkLocals(void) {
linkTree(localTable);
localTable = NULL;
fseek(codeFile, 0, SEEK_END);
fseek(dataFile, 0, SEEK_END);
}
 
 
/**************************************************************/
 
 
void emitByte(unsigned int byte) {
byte &= 0x000000FF;
if (debugCode) {
printf("DEBUG: byte @ segment = %s, offset = %08X",
segName[currSeg], segPtr[currSeg]);
printf(", value = %02X\n", byte);
}
switch (currSeg) {
case SEGMENT_ABS:
error("illegal segment in emitByte()");
break;
case SEGMENT_CODE:
fputc(byte, codeFile);
break;
case SEGMENT_DATA:
fputc(byte, dataFile);
break;
case SEGMENT_BSS:
break;
}
segPtr[currSeg] += 1;
}
 
 
void emitHalf(unsigned int half) {
half &= 0x0000FFFF;
if (debugCode) {
printf("DEBUG: half @ segment = %s, offset = %08X",
segName[currSeg], segPtr[currSeg]);
printf(", value = %02X%02X\n",
(half >> 8) & 0xFF, half & 0xFF);
}
switch (currSeg) {
case SEGMENT_ABS:
error("illegal segment in emitHalf()");
break;
case SEGMENT_CODE:
fputc((half >> 8) & 0xFF, codeFile);
fputc(half & 0xFF, codeFile);
break;
case SEGMENT_DATA:
fputc((half >> 8) & 0xFF, dataFile);
fputc(half & 0xFF, dataFile);
break;
case SEGMENT_BSS:
break;
}
segPtr[currSeg] += 2;
}
 
 
void emitWord(unsigned int word) {
if (debugCode) {
printf("DEBUG: word @ segment = %s, offset = %08X",
segName[currSeg], segPtr[currSeg]);
printf(", value = %02X%02X%02X%02X\n",
(word >> 24) & 0xFF, (word >> 16) & 0xFF,
(word >> 8) & 0xFF, word & 0xFF);
}
switch (currSeg) {
case SEGMENT_ABS:
error("illegal segment in emitWord()");
break;
case SEGMENT_CODE:
fputc((word >> 24) & 0xFF, codeFile);
fputc((word >> 16) & 0xFF, codeFile);
fputc((word >> 8) & 0xFF, codeFile);
fputc(word & 0xFF, codeFile);
break;
case SEGMENT_DATA:
fputc((word >> 24) & 0xFF, dataFile);
fputc((word >> 16) & 0xFF, dataFile);
fputc((word >> 8) & 0xFF, dataFile);
fputc(word & 0xFF, dataFile);
break;
case SEGMENT_BSS:
break;
}
segPtr[currSeg] += 4;
}
 
 
/**************************************************************/
 
 
typedef struct {
int con;
Symbol *sym;
} Value;
 
 
Value parseExpression(void);
 
 
Value parsePrimaryExpression(void) {
Value v;
Symbol *s;
 
if (token == TOK_NUMBER) {
v.con = tokenvalNumber;
v.sym = NULL;
getToken();
} else
if (token == TOK_IDENT) {
s = deref(lookupEnter(tokenvalString, LOCAL_TABLE));
if (s->status == STATUS_DEFINED && s->segment == SEGMENT_ABS) {
v.con = s->value;
v.sym = NULL;
} else {
v.con = 0;
v.sym = s;
}
getToken();
} else
if (token == TOK_LPAREN) {
getToken();
v = parseExpression();
expect(TOK_RPAREN);
getToken();
} else {
error("illegal primary expression, line %d", lineno);
}
return v;
}
 
 
Value parseUnaryExpression(void) {
Value v;
 
if (token == TOK_PLUS) {
getToken();
v = parseUnaryExpression();
} else
if (token == TOK_MINUS) {
getToken();
v = parseUnaryExpression();
if (v.sym != NULL) {
error("cannot negate symbol '%s' in line %d", v.sym->name, lineno);
}
v.con = -v.con;
} else
if (token == TOK_TILDE) {
getToken();
v = parseUnaryExpression();
if (v.sym != NULL) {
error("cannot complement symbol '%s' in line %d", v.sym->name, lineno);
}
v.con = ~v.con;
} else {
v = parsePrimaryExpression();
}
return v;
}
 
 
Value parseMultiplicativeExpression(void) {
Value v1, v2;
 
v1 = parseUnaryExpression();
while (token == TOK_STAR || token == TOK_SLASH || token == TOK_PERCENT) {
if (token == TOK_STAR) {
getToken();
v2 = parseUnaryExpression();
if (v1.sym != NULL || v2.sym != NULL) {
error("multiplication of symbols not supported, line %d", lineno);
}
v1.con *= v2.con;
} else
if (token == TOK_SLASH) {
getToken();
v2 = parseUnaryExpression();
if (v1.sym != NULL || v2.sym != NULL) {
error("division of symbols not supported, line %d", lineno);
}
if (v2.con == 0) {
error("division by zero, line %d", lineno);
}
v1.con /= v2.con;
} else
if (token == TOK_PERCENT) {
getToken();
v2 = parseUnaryExpression();
if (v1.sym != NULL || v2.sym != NULL) {
error("division of symbols not supported, line %d", lineno);
}
if (v2.con == 0) {
error("division by zero, line %d", lineno);
}
v1.con %= v2.con;
}
}
return v1;
}
 
 
Value parseAdditiveExpression(void) {
Value v1, v2;
 
v1 = parseMultiplicativeExpression();
while (token == TOK_PLUS || token == TOK_MINUS) {
if (token == TOK_PLUS) {
getToken();
v2 = parseMultiplicativeExpression();
if (v1.sym != NULL && v2.sym != NULL) {
error("addition of symbols not supported, line %d", lineno);
}
if (v2.sym != NULL) {
v1.sym = v2.sym;
}
v1.con += v2.con;
} else
if (token == TOK_MINUS) {
getToken();
v2 = parseMultiplicativeExpression();
if (v2.sym != NULL) {
error("subtraction of symbols not supported, line %d", lineno);
}
v1.con -= v2.con;
}
}
return v1;
}
 
 
Value parseShiftExpression(void) {
Value v1, v2;
 
v1 = parseAdditiveExpression();
while (token == TOK_LSHIFT || token == TOK_RSHIFT) {
if (token == TOK_LSHIFT) {
getToken();
v2 = parseAdditiveExpression();
if (v1.sym != NULL || v2.sym != NULL) {
error("shifting of symbols not supported, line %d", lineno);
}
v1.con <<= v2.con;
} else
if (token == TOK_RSHIFT) {
getToken();
v2 = parseAdditiveExpression();
if (v1.sym != NULL || v2.sym != NULL) {
error("shifting of symbols not supported, line %d", lineno);
}
v1.con >>= v2.con;
}
}
return v1;
}
 
 
Value parseAndExpression(void) {
Value v1, v2;
 
v1 = parseShiftExpression();
while (token == TOK_AMPER) {
getToken();
v2 = parseShiftExpression();
if (v2.sym != NULL) {
error("bitwise 'and' of symbols not supported, line %d", lineno);
}
v1.con &= v2.con;
}
return v1;
}
 
 
Value parseExclusiveOrExpression(void) {
Value v1, v2;
 
v1 = parseAndExpression();
while (token == TOK_CARET) {
getToken();
v2 = parseAndExpression();
if (v2.sym != NULL) {
error("bitwise 'xor' of symbols not supported, line %d", lineno);
}
v1.con ^= v2.con;
}
return v1;
}
 
 
Value parseInclusiveOrExpression(void) {
Value v1, v2;
 
v1 = parseExclusiveOrExpression();
while (token == TOK_BAR) {
getToken();
v2 = parseExclusiveOrExpression();
if (v2.sym != NULL) {
error("bitwise 'or' of symbols not supported, line %d", lineno);
}
v1.con |= v2.con;
}
return v1;
}
 
 
Value parseExpression(void) {
Value v;
 
v = parseInclusiveOrExpression();
return v;
}
 
 
/**************************************************************/
 
 
void dotSyn(unsigned int code) {
allowSyn = 1;
}
 
 
void dotNosyn(unsigned int code) {
allowSyn = 0;
}
 
 
void dotCode(unsigned int code) {
currSeg = SEGMENT_CODE;
}
 
 
void dotData(unsigned int code) {
currSeg = SEGMENT_DATA;
}
 
 
void dotBss(unsigned int code) {
currSeg = SEGMENT_BSS;
}
 
 
void dotExport(unsigned int code) {
Symbol *global;
Symbol *local;
Fixup *f;
 
while (1) {
expect(TOK_IDENT);
global = lookupEnter(tokenvalString, GLOBAL_TABLE);
if (global->status != STATUS_UNKNOWN) {
error("exported symbol '%s' multiply defined in line %d",
global->name, lineno);
}
local = lookupEnter(tokenvalString, LOCAL_TABLE);
if (local->status == STATUS_GLOBREF) {
error("exported symbol '%s' multiply exported in line %d",
local->name, lineno);
}
global->status = local->status;
global->segment = local->segment;
global->value = local->value;
while (local->fixups != NULL) {
f = local->fixups;
local->fixups = f->next;
f->next = global->fixups;
global->fixups = f;
}
local->status = STATUS_GLOBREF;
local->globref = global;
getToken();
if (token != TOK_COMMA) {
break;
}
getToken();
}
}
 
 
void dotImport(unsigned int code) {
Symbol *global;
Symbol *local;
Fixup *f;
 
while (1) {
expect(TOK_IDENT);
global = lookupEnter(tokenvalString, GLOBAL_TABLE);
local = lookupEnter(tokenvalString, LOCAL_TABLE);
if (local->status != STATUS_UNKNOWN) {
error("imported symbol '%s' multiply defined in line %d",
local->name, lineno);
}
while (local->fixups != NULL) {
f = local->fixups;
local->fixups = f->next;
f->next = global->fixups;
global->fixups = f;
}
local->status = STATUS_GLOBREF;
local->globref = global;
getToken();
if (token != TOK_COMMA) {
break;
}
getToken();
}
}
 
 
int countBits(unsigned int x) {
int n;
 
n = 0;
while (x != 0) {
x &= x - 1;
n++;
}
return n;
}
 
 
void dotAlign(unsigned int code) {
Value v;
unsigned int mask;
 
v = parseExpression();
if (v.sym != NULL) {
error("absolute expression expected in line %d", lineno);
}
if (countBits(v.con) != 1) {
error("argument must be a power of 2 in line %d", lineno);
}
mask = v.con - 1;
while ((segPtr[currSeg] & mask) != 0) {
emitByte(0);
}
}
 
 
void dotSpace(unsigned int code) {
Value v;
int i;
 
v = parseExpression();
if (v.sym != NULL) {
error("absolute expression expected in line %d", lineno);
}
for (i = 0; i < v.con; i++) {
emitByte(0);
}
}
 
 
void dotLocate(unsigned int code) {
Value v;
 
v = parseExpression();
if (v.sym != NULL) {
error("absolute expression expected in line %d", lineno);
}
while (segPtr[currSeg] != v.con) {
emitByte(0);
}
}
 
 
void dotByte(unsigned int code) {
Value v;
char *p;
 
while (1) {
if (token == TOK_STRING) {
p = tokenvalString;
while (*p != '\0') {
emitByte(*p);
p++;
}
getToken();
} else {
v = parseExpression();
if (v.sym != NULL) {
error("absolute expression expected in line %d", lineno);
}
emitByte(v.con);
}
if (token != TOK_COMMA) {
break;
}
getToken();
}
}
 
 
void dotHalf(unsigned int code) {
Value v;
 
while (1) {
v = parseExpression();
if (v.sym != NULL) {
error("absolute expression expected in line %d", lineno);
}
emitHalf(v.con);
if (token != TOK_COMMA) {
break;
}
getToken();
}
}
 
 
void dotWord(unsigned int code) {
Value v;
 
while (1) {
v = parseExpression();
if (v.sym == NULL) {
emitWord(v.con);
} else {
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_W32, v.con);
emitWord(0);
}
if (token != TOK_COMMA) {
break;
}
getToken();
}
}
 
 
void dotSet(unsigned int code) {
Value v;
Symbol *symbol;
 
expect(TOK_IDENT);
symbol = deref(lookupEnter(tokenvalString, LOCAL_TABLE));
if (symbol->status != STATUS_UNKNOWN) {
error("symbol '%s' multiply defined in line %d",
symbol->name, lineno);
}
getToken();
expect(TOK_COMMA);
getToken();
v = parseExpression();
if (v.sym == NULL) {
symbol->status = STATUS_DEFINED;
symbol->segment = SEGMENT_ABS;
symbol->value = v.con;
} else {
error("illegal type of symbol '%s' in expression, line %d",
v.sym->name, lineno);
}
}
 
 
void formatN(unsigned int code) {
Value v;
unsigned int immed;
 
/* opcode with no operands */
if (token != TOK_EOL) {
/* in exceptional cases (trap) there may be one constant operand */
v = parseExpression();
if (v.sym != NULL) {
error("operand must be a constant, line %d", lineno);
}
immed = v.con;
} else {
immed = 0;
}
emitWord(code << 26 | (immed & 0x03FFFFFF));
}
 
 
void formatRH(unsigned int code) {
int reg;
Value v;
 
/* opcode with one register and a half operand */
expect(TOK_REGISTER);
reg = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
v = parseExpression();
if (v.sym == NULL) {
emitHalf(code << 10 | reg);
emitHalf(v.con);
} else {
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
emitHalf(code << 10 | reg);
emitHalf(0);
}
}
 
 
void formatRHH(unsigned int code) {
int reg;
Value v;
 
/* opcode with one register and a half operand */
/* ATTENTION: high order 16 bits encoded in instruction */
expect(TOK_REGISTER);
reg = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
v = parseExpression();
if (v.sym == NULL) {
emitHalf(code << 10 | reg);
emitHalf(v.con >> 16);
} else {
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
emitHalf(code << 10 | reg);
emitHalf(0);
}
}
 
 
void formatRRH(unsigned int code) {
int dst, src;
Value v;
 
/* opcode with two registers and a half operand */
expect(TOK_REGISTER);
dst = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
expect(TOK_REGISTER);
src = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
v = parseExpression();
if (allowSyn) {
if (v.sym == NULL) {
if ((v.con & 0xFFFF0000) == 0) {
/* code: op dst,src,con */
emitHalf(code << 10 | src << 5 | dst);
emitHalf(v.con);
} else {
/* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
emitHalf(OP_LDHI << 10 | AUX_REG);
emitHalf(v.con >> 16);
emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
emitHalf(v.con);
emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
emitHalf(AUX_REG << 11);
emitHalf(code << 10 | AUX_REG << 5 | dst);
emitHalf(0);
}
} else {
/* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
emitHalf(OP_LDHI << 10 | AUX_REG);
emitHalf(0);
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
emitHalf(0);
emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
emitHalf(AUX_REG << 11);
emitHalf(code << 10 | AUX_REG << 5 | dst);
emitHalf(0);
}
} else {
if (v.sym == NULL) {
emitHalf(code << 10 | src << 5 | dst);
emitHalf(v.con);
} else {
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
emitHalf(code << 10 | src << 5 | dst);
emitHalf(0);
}
}
}
 
 
void formatRRS(unsigned int code) {
int dst, src;
Value v;
 
/* opcode with two registers and a signed half operand */
expect(TOK_REGISTER);
dst = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
expect(TOK_REGISTER);
src = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
v = parseExpression();
if (allowSyn) {
if (v.sym == NULL) {
if ((v.con & 0xFFFF8000) == 0x00000000 ||
(v.con & 0xFFFF8000) == 0xFFFF8000) {
/* code: op dst,src,con */
emitHalf(code << 10 | src << 5 | dst);
emitHalf(v.con);
} else {
/* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
emitHalf(OP_LDHI << 10 | AUX_REG);
emitHalf(v.con >> 16);
emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
emitHalf(v.con);
emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
emitHalf(AUX_REG << 11);
emitHalf(code << 10 | AUX_REG << 5 | dst);
emitHalf(0);
}
} else {
/* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
emitHalf(OP_LDHI << 10 | AUX_REG);
emitHalf(0);
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
emitHalf(0);
emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
emitHalf(AUX_REG << 11);
emitHalf(code << 10 | AUX_REG << 5 | dst);
emitHalf(0);
}
} else {
if (v.sym == NULL) {
emitHalf(code << 10 | src << 5 | dst);
emitHalf(v.con);
} else {
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
emitHalf(code << 10 | src << 5 | dst);
emitHalf(0);
}
}
}
 
 
void formatRRR(unsigned int code) {
int dst, src1, src2;
 
/* opcode with three register operands */
expect(TOK_REGISTER);
dst = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
expect(TOK_REGISTER);
src1 = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
expect(TOK_REGISTER);
src2 = tokenvalNumber;
getToken();
emitHalf(code << 10 | src1 << 5 | src2);
emitHalf(dst << 11);
}
 
 
void formatRRX(unsigned int code) {
int dst, src1, src2;
Value v;
 
/* opcode with three register operands
or two registers and a half operand */
expect(TOK_REGISTER);
dst = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
expect(TOK_REGISTER);
src1 = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
if (token == TOK_REGISTER) {
src2 = tokenvalNumber;
getToken();
emitHalf(code << 10 | src1 << 5 | src2);
emitHalf(dst << 11);
} else {
v = parseExpression();
if (allowSyn) {
if (v.sym == NULL) {
if ((v.con & 0xFFFF0000) == 0) {
/* code: op dst,src,con */
emitHalf((code + 1) << 10 | src1 << 5 | dst);
emitHalf(v.con);
} else {
if ((v.con & 0x0000FFFF) == 0) {
/* code: ldhi $1,con; op dst,src,$1 */
emitHalf(OP_LDHI << 10 | AUX_REG);
emitHalf(v.con >> 16);
emitHalf(code << 10 | src1 << 5 | AUX_REG);
emitHalf(dst << 11);
} else {
/* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
emitHalf(OP_LDHI << 10 | AUX_REG);
emitHalf(v.con >> 16);
emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
emitHalf(v.con);
emitHalf(code << 10 | src1 << 5 | AUX_REG);
emitHalf(dst << 11);
}
}
} else {
/* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
emitHalf(OP_LDHI << 10 | AUX_REG);
emitHalf(0);
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
emitHalf(0);
emitHalf(code << 10 | src1 << 5 | AUX_REG);
emitHalf(dst << 11);
}
} else {
if (v.sym == NULL) {
emitHalf((code + 1) << 10 | src1 << 5 | dst);
emitHalf(v.con);
} else {
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
emitHalf((code + 1) << 10 | src1 << 5 | dst);
emitHalf(0);
}
}
}
}
 
 
void formatRRY(unsigned int code) {
int dst, src1, src2;
Value v;
 
/* opcode with three register operands
or two registers and a signed half operand */
expect(TOK_REGISTER);
dst = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
expect(TOK_REGISTER);
src1 = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
if (token == TOK_REGISTER) {
src2 = tokenvalNumber;
getToken();
emitHalf(code << 10 | src1 << 5 | src2);
emitHalf(dst << 11);
} else {
v = parseExpression();
if (allowSyn) {
if (v.sym == NULL) {
if ((v.con & 0xFFFF8000) == 0x00000000 ||
(v.con & 0xFFFF8000) == 0xFFFF8000) {
/* code: op dst,src,con */
emitHalf((code + 1) << 10 | src1 << 5 | dst);
emitHalf(v.con);
} else {
if ((v.con & 0x0000FFFF) == 0) {
/* code: ldhi $1,con; op dst,src,$1 */
emitHalf(OP_LDHI << 10 | AUX_REG);
emitHalf(v.con >> 16);
emitHalf(code << 10 | src1 << 5 | AUX_REG);
emitHalf(dst << 11);
} else {
/* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
emitHalf(OP_LDHI << 10 | AUX_REG);
emitHalf(v.con >> 16);
emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
emitHalf(v.con);
emitHalf(code << 10 | src1 << 5 | AUX_REG);
emitHalf(dst << 11);
}
}
} else {
/* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
emitHalf(OP_LDHI << 10 | AUX_REG);
emitHalf(0);
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
emitHalf(0);
emitHalf(code << 10 | src1 << 5 | AUX_REG);
emitHalf(dst << 11);
}
} else {
if (v.sym == NULL) {
emitHalf((code + 1) << 10 | src1 << 5 | dst);
emitHalf(v.con);
} else {
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
emitHalf((code + 1) << 10 | src1 << 5 | dst);
emitHalf(0);
}
}
}
}
 
 
void formatRRB(unsigned int code) {
int src1, src2;
Value v;
unsigned int immed;
 
/* opcode with two registers and a 16 bit signed offset operand */
expect(TOK_REGISTER);
src1 = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
expect(TOK_REGISTER);
src2 = tokenvalNumber;
getToken();
expect(TOK_COMMA);
getToken();
v = parseExpression();
if (v.sym == NULL) {
immed = (v.con - ((signed) segPtr[currSeg] + 4)) / 4;
} else {
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_R16, v.con);
immed = 0;
}
emitHalf(code << 10 | src1 << 5 | src2);
emitHalf(immed);
}
 
 
void formatJ(unsigned int code) {
Value v;
unsigned int immed;
int target;
 
/* opcode with no registers and a 26 bit signed offset operand or
opcode with a single register */
if (token == TOK_REGISTER) {
target = tokenvalNumber;
getToken();
emitWord((code + 1) << 26 | target << 21);
} else {
v = parseExpression();
if (v.sym == NULL) {
immed = (v.con - ((signed) segPtr[currSeg] + 4)) / 4;
} else {
addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_R26, v.con);
immed = 0;
}
emitWord(code << 26 | (immed & 0x03FFFFFF));
}
}
 
 
void formatJR(unsigned int code) {
int target;
 
/* opcode with one register operand */
expect(TOK_REGISTER);
target = tokenvalNumber;
getToken();
emitWord(code << 26 | target << 21);
}
 
 
typedef struct instr {
char *name;
void (*func)(unsigned int code);
unsigned int code;
} Instr;
 
 
Instr instrTable[] = {
 
/* pseudo instructions */
{ ".syn", dotSyn, 0 },
{ ".nosyn", dotNosyn, 0 },
{ ".code", dotCode, 0 },
{ ".data", dotData, 0 },
{ ".bss", dotBss, 0 },
{ ".export", dotExport, 0 },
{ ".import", dotImport, 0 },
{ ".align", dotAlign, 0 },
{ ".space", dotSpace, 0 },
{ ".locate", dotLocate, 0 },
{ ".byte", dotByte, 0 },
{ ".half", dotHalf, 0 },
{ ".word", dotWord, 0 },
{ ".set", dotSet, 0 },
 
/* arithmetical instructions */
{ "add", formatRRY, OP_ADD },
{ "sub", formatRRY, OP_SUB },
 
{ "mul", formatRRY, OP_MUL },
{ "mulu", formatRRX, OP_MULU },
{ "div", formatRRY, OP_DIV },
{ "divu", formatRRX, OP_DIVU },
{ "rem", formatRRY, OP_REM },
{ "remu", formatRRX, OP_REMU },
 
/* logical instructions */
{ "and", formatRRX, OP_AND },
{ "or", formatRRX, OP_OR },
{ "xor", formatRRX, OP_XOR },
{ "xnor", formatRRX, OP_XNOR },
 
/* shift instructions */
{ "sll", formatRRX, OP_SLL },
{ "slr", formatRRX, OP_SLR },
{ "sar", formatRRX, OP_SAR },
 
/* load immediate instructions */
{ "ldhi", formatRHH, OP_LDHI },
 
/* branch instructions */
{ "beq", formatRRB, OP_BEQ },
{ "bne", formatRRB, OP_BNE },
{ "ble", formatRRB, OP_BLE },
{ "bleu", formatRRB, OP_BLEU },
{ "blt", formatRRB, OP_BLT },
{ "bltu", formatRRB, OP_BLTU },
{ "bge", formatRRB, OP_BGE },
{ "bgeu", formatRRB, OP_BGEU },
{ "bgt", formatRRB, OP_BGT },
{ "bgtu", formatRRB, OP_BGTU },
 
/* jump, call & return instructions */
{ "j", formatJ, OP_J },
{ "jr", formatJR, OP_JR },
{ "jal", formatJ, OP_JAL },
{ "jalr", formatJR, OP_JALR },
 
/* interrupt related instructions */
{ "trap", formatN, OP_TRAP },
{ "rfx", formatN, OP_RFX },
 
/* load instructions */
{ "ldw", formatRRS, OP_LDW },
{ "ldh", formatRRS, OP_LDH },
{ "ldhu", formatRRS, OP_LDHU },
{ "ldb", formatRRS, OP_LDB },
{ "ldbu", formatRRS, OP_LDBU },
 
/* store instructions */
{ "stw", formatRRS, OP_STW },
{ "sth", formatRRS, OP_STH },
{ "stb", formatRRS, OP_STB },
 
/* processor control instructions */
{ "mvfs", formatRH, OP_MVFS },
{ "mvts", formatRH, OP_MVTS },
{ "tbs", formatN, OP_TBS },
{ "tbwr", formatN, OP_TBWR },
{ "tbri", formatN, OP_TBRI },
{ "tbwi", formatN, OP_TBWI }
 
};
 
 
static int cmpInstr(const void *instr1, const void *instr2) {
return strcmp(((Instr *) instr1)->name, ((Instr *) instr2)->name);
}
 
 
void sortInstrTable(void) {
qsort(instrTable, sizeof(instrTable)/sizeof(instrTable[0]),
sizeof(instrTable[0]), cmpInstr);
}
 
 
Instr *lookupInstr(char *name) {
int lo, hi, tst;
int res;
 
lo = 0;
hi = sizeof(instrTable) / sizeof(instrTable[0]) - 1;
while (lo <= hi) {
tst = (lo + hi) / 2;
res = strcmp(instrTable[tst].name, name);
if (res == 0) {
return &instrTable[tst];
}
if (res < 0) {
lo = tst + 1;
} else {
hi = tst - 1;
}
}
return NULL;
}
 
 
/**************************************************************/
 
 
void roundupSegments(void) {
while (segPtr[SEGMENT_CODE] & 3) {
fputc(0, codeFile);
segPtr[SEGMENT_CODE] += 1;
}
while (segPtr[SEGMENT_DATA] & 3) {
fputc(0, dataFile);
segPtr[SEGMENT_DATA] += 1;
}
while (segPtr[SEGMENT_BSS] & 3) {
segPtr[SEGMENT_BSS] += 1;
}
}
 
 
void asmModule(void) {
Symbol *label;
Instr *instr;
 
allowSyn = 1;
currSeg = SEGMENT_CODE;
lineno = 0;
while (fgets(line, LINE_SIZE, inFile) != NULL) {
lineno++;
lineptr = line;
getToken();
while (token == TOK_LABEL) {
label = deref(lookupEnter(tokenvalString, LOCAL_TABLE));
if (label->status != STATUS_UNKNOWN) {
error("label '%s' multiply defined in line %d",
label->name, lineno);
}
label->status = STATUS_DEFINED;
label->segment = currSeg;
label->value = segPtr[currSeg];
getToken();
}
if (token == TOK_IDENT) {
instr = lookupInstr(tokenvalString);
if (instr == NULL) {
error("unknown instruction '%s' in line %d",
tokenvalString, lineno);
}
getToken();
(*instr->func)(instr->code);
}
if (token != TOK_EOL) {
error("garbage in line %d", lineno);
}
}
roundupSegments();
}
 
 
/**************************************************************/
 
 
unsigned int read4FromEco(unsigned char *p) {
return (unsigned int) p[0] << 24 |
(unsigned int) p[1] << 16 |
(unsigned int) p[2] << 8 |
(unsigned int) p[3] << 0;
}
 
 
void write4ToEco(unsigned char *p, unsigned int data) {
p[0] = data >> 24;
p[1] = data >> 16;
p[2] = data >> 8;
p[3] = data >> 0;
}
 
 
void conv4FromEcoToNative(unsigned char *p) {
unsigned int data;
 
data = read4FromEco(p);
* (unsigned int *) p = data;
}
 
 
void conv4FromNativeToEco(unsigned char *p) {
unsigned int data;
 
data = * (unsigned int *) p;
write4ToEco(p, data);
}
 
 
/**************************************************************/
 
 
static ExecHeader execHeader;
static int numSymbols;
static int crelSize;
static int drelSize;
static int symtblSize;
static int stringSize;
 
 
static void walkTree(Symbol *s, void (*fp)(Symbol *sp)) {
if (s == NULL) {
return;
}
walkTree(s->left, fp);
(*fp)(s);
walkTree(s->right, fp);
}
 
 
void writeDummyHeader(void) {
fwrite(&execHeader, sizeof(ExecHeader), 1, outFile);
}
 
 
void writeRealHeader(void) {
rewind(outFile);
execHeader.magic = EXEC_MAGIC;
execHeader.csize = segPtr[SEGMENT_CODE];
execHeader.dsize = segPtr[SEGMENT_DATA];
execHeader.bsize = segPtr[SEGMENT_BSS];
execHeader.crsize = crelSize;
execHeader.drsize = drelSize;
execHeader.symsize = symtblSize;
execHeader.strsize = stringSize;
conv4FromNativeToEco((unsigned char *) &execHeader.magic);
conv4FromNativeToEco((unsigned char *) &execHeader.csize);
conv4FromNativeToEco((unsigned char *) &execHeader.dsize);
conv4FromNativeToEco((unsigned char *) &execHeader.bsize);
conv4FromNativeToEco((unsigned char *) &execHeader.crsize);
conv4FromNativeToEco((unsigned char *) &execHeader.drsize);
conv4FromNativeToEco((unsigned char *) &execHeader.symsize);
conv4FromNativeToEco((unsigned char *) &execHeader.strsize);
fwrite(&execHeader, sizeof(ExecHeader), 1, outFile);
}
 
 
void writeCode(void) {
int data;
 
rewind(codeFile);
while (1) {
data = fgetc(codeFile);
if (data == EOF) {
break;
}
fputc(data, outFile);
}
}
 
 
void writeData(void) {
int data;
 
rewind(dataFile);
while (1) {
data = fgetc(dataFile);
if (data == EOF) {
break;
}
fputc(data, outFile);
}
}
 
 
void transferFixupsForSymbol(Symbol *s) {
Fixup *f;
 
if (s->status != STATUS_UNKNOWN && s->status != STATUS_DEFINED) {
/* this should never happen */
error("global symbol is neither unknown nor defined");
}
if (s->status == STATUS_UNKNOWN && s->fixups == NULL) {
/* this symbol is neither defined here nor referenced here: skip */
s->skip = 1;
return;
}
s->skip = 0;
while (s->fixups != NULL) {
/* get next fixup record */
f = s->fixups;
s->fixups = f->next;
/* use the 'base' component to store the current symbol number */
f->base = MSB | numSymbols;
/* transfer the record to the fixup list */
f->next = fixupList;
fixupList = f;
}
numSymbols++;
}
 
 
void transferFixups(void) {
numSymbols = 0;
walkTree(globalTable, transferFixupsForSymbol);
}
 
 
void writeCodeRelocs(void) {
Fixup *f;
RelocRecord relRec;
 
crelSize = 0;
f = fixupList;
while (f != NULL) {
if (f->segment != SEGMENT_CODE && f->segment != SEGMENT_DATA) {
/* this should never happan */
error("fixup found in a segment other than code or data");
}
if (f->segment == SEGMENT_CODE) {
relRec.offset = f->offset;
relRec.method = f->method;
relRec.value = f->value;
relRec.base = f->base;
conv4FromNativeToEco((unsigned char *) &relRec.offset);
conv4FromNativeToEco((unsigned char *) &relRec.method);
conv4FromNativeToEco((unsigned char *) &relRec.value);
conv4FromNativeToEco((unsigned char *) &relRec.base);
fwrite(&relRec, sizeof(RelocRecord), 1, outFile);
crelSize += sizeof(RelocRecord);
}
f = f->next;
}
}
 
 
void writeDataRelocs(void) {
Fixup *f;
RelocRecord relRec;
 
drelSize = 0;
f = fixupList;
while (f != NULL) {
if (f->segment != SEGMENT_CODE && f->segment != SEGMENT_DATA) {
/* this should never happan */
error("fixup found in a segment other than code or data");
}
if (f->segment == SEGMENT_DATA) {
relRec.offset = f->offset;
relRec.method = f->method;
relRec.value = f->value;
relRec.base = f->base;
conv4FromNativeToEco((unsigned char *) &relRec.offset);
conv4FromNativeToEco((unsigned char *) &relRec.method);
conv4FromNativeToEco((unsigned char *) &relRec.value);
conv4FromNativeToEco((unsigned char *) &relRec.base);
fwrite(&relRec, sizeof(RelocRecord), 1, outFile);
drelSize += sizeof(RelocRecord);
}
f = f->next;
}
}
 
 
void writeSymbol(Symbol *s) {
SymbolRecord symRec;
 
if (s->skip) {
/* this symbol is neither defined here nor referenced here: skip */
return;
}
symRec.name = stringSize;
if (s->status == STATUS_UNKNOWN) {
symRec.type = MSB;
symRec.value = 0;
} else {
symRec.type = s->segment;
symRec.value = s->value;
}
conv4FromNativeToEco((unsigned char *) &symRec.name);
conv4FromNativeToEco((unsigned char *) &symRec.type);
conv4FromNativeToEco((unsigned char *) &symRec.value);
fwrite(&symRec, sizeof(SymbolRecord), 1, outFile);
symtblSize += sizeof(SymbolRecord);
stringSize += strlen(s->name) + 1;
}
 
 
void writeSymbols(void) {
symtblSize = 0;
stringSize = 0;
walkTree(globalTable, writeSymbol);
}
 
 
void writeString(Symbol *s) {
if (s->skip) {
/* this symbol is neither defined here nor referenced here: skip */
return;
}
fputs(s->name, outFile);
fputc('\0', outFile);
}
 
 
void writeStrings(void) {
walkTree(globalTable, writeString);
}
 
 
/**************************************************************/
 
 
void usage(char *myself) {
fprintf(stderr, "Usage: %s\n", myself);
fprintf(stderr, " [-o objfile] set object file name\n");
fprintf(stderr, " file source file name\n");
fprintf(stderr, " [files...] additional source files\n");
exit(1);
}
 
 
int main(int argc, char *argv[]) {
int i;
char *argp;
 
sortInstrTable();
tmpnam(codeName);
tmpnam(dataName);
outName = "a.out";
for (i = 1; i < argc; i++) {
argp = argv[i];
if (*argp != '-') {
break;
}
argp++;
switch (*argp) {
case 'o':
if (i == argc - 1) {
usage(argv[0]);
}
outName = argv[++i];
break;
default:
usage(argv[0]);
}
}
if (i == argc) {
usage(argv[0]);
}
codeFile = fopen(codeName, "w+b");
if (codeFile == NULL) {
error("cannot create temporary code file '%s'", codeName);
}
dataFile = fopen(dataName, "w+b");
if (dataFile == NULL) {
error("cannot create temporary data file '%s'", dataName);
}
outFile = fopen(outName, "wb");
if (outFile == NULL) {
error("cannot open output file '%s'", outName);
}
do {
inName = argv[i];
if (*inName == '-') {
usage(argv[0]);
}
inFile = fopen(inName, "rt");
if (inFile == NULL) {
error("cannot open input file '%s'", inName);
}
fprintf(stderr, "Assembling module '%s'...\n", inName);
asmModule();
if (inFile != NULL) {
fclose(inFile);
inFile = NULL;
}
linkLocals();
} while (++i < argc);
writeDummyHeader();
writeCode();
writeData();
transferFixups();
writeCodeRelocs();
writeDataRelocs();
writeSymbols();
writeStrings();
writeRealHeader();
if (codeFile != NULL) {
fclose(codeFile);
codeFile = NULL;
}
if (dataFile != NULL) {
fclose(dataFile);
dataFile = NULL;
}
if (outFile != NULL) {
fclose(outFile);
outFile = NULL;
}
if (codeName != NULL) {
unlink(codeName);
}
if (dataName != NULL) {
unlink(dataName);
}
return 0;
}
/binutils/as/Makefile
0,0 → 1,36
#
# Makefile for ECO32 assembler
#
 
BUILD = ../../build
 
CC = gcc -m32
CFLAGS = -g -Wall
LDFLAGS = -g
LDLIBS = -lm
 
SRCS = as.c
OBJS = $(patsubst %.c,%.o,$(SRCS))
BIN = as
 
.PHONY: all install clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/bin
cp $(BIN) $(BUILD)/bin
 
$(BIN): $(OBJS)
$(CC) $(LDFLAGS) -o $(BIN) $(OBJS) $(LDLIBS)
 
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
 
depend.mak:
$(CC) -MM -MG $(CFLAGS) $(SRCS) > depend.mak
 
-include depend.mak
 
clean:
rm -f *~ $(OBJS) $(BIN) depend.mak
/binutils/include/ar.h
0,0 → 1,28
/*
* ar.h -- structure of archives (object libraries)
*/
 
 
#ifndef _AR_H_
#define _AR_H_
 
 
#define AR_MAGIC 0x0412CF03 /* archive file magic number */
#define MAX_NAME 60 /* max length of member name */
 
 
/*
* The following structure is stored once per archive member.
*/
 
typedef struct {
char name[MAX_NAME];
time_t date;
int uid;
int gid;
int mode;
off_t size;
} ArHeader;
 
 
#endif /* _AR_H_ */
/binutils/include/a.out.h
0,0 → 1,52
/*
* a.out.h -- structure of linkable object and executable files
*/
 
 
#ifndef _A_OUT_H_
#define _A_OUT_H_
 
 
#define EXEC_MAGIC 0x1AA09232
 
#define METHOD_H16 0 /* write 16 bits with high part of value */
#define METHOD_L16 1 /* write 16 bits with low part of value */
#define METHOD_R16 2 /* write 16 bits with value relative to PC */
#define METHOD_R26 3 /* write 26 bits with value relative to PC */
#define METHOD_W32 4 /* write full 32 bit word with value */
 
#define SEGMENT_ABS 0 /* absolute values */
#define SEGMENT_CODE 1 /* code segment */
#define SEGMENT_DATA 2 /* initialized data segment */
#define SEGMENT_BSS 3 /* uninitialized data segment */
 
 
typedef struct {
unsigned int magic; /* must be EXEC_MAGIC */
unsigned int csize; /* size of code in bytes */
unsigned int dsize; /* size of initialized data in bytes */
unsigned int bsize; /* size of uninitialized data in bytes */
unsigned int crsize; /* size of code relocation info in bytes */
unsigned int drsize; /* size of data relocation info in bytes */
unsigned int symsize; /* size of symbol table in bytes */
unsigned int strsize; /* size of string space in bytes */
} ExecHeader;
 
typedef struct {
unsigned int offset; /* where to relocate */
int method; /* how to relocate */
int value; /* additive part of value */
int base; /* if MSB = 0: segment number */
/* if MSB = 1: symbol table index */
} RelocRecord;
 
typedef struct {
unsigned int name; /* offset in string space */
int type; /* if MSB = 0: the symbol's segment */
/* if MSB = 1: the symbol is undefined */
int value; /* if symbol defined: the symbol's value */
/* if symbol not defined: meaningless */
} SymbolRecord;
 
 
#endif /* _A_OUT_H_ */
/binutils/include/README
0,0 → 1,162
 
Format of Object and Executable Files
-------------------------------------
 
0) General
 
The "a.out" file format is used as format for assembler output
("object files") as well as for linker output ("executable files").
The difference of these two is the size of certain sections of
the file being zero in case of executable files.
 
The file consists of a header and up to 6 sections:
- code
- initialized data
- code relocation records
- data relocation records
- symbol table records
- symbol string storage
 
 
1) Header
 
The header specifies the sizes of all following sections,
but has itself a fixed length (and is always present):
 
typedef struct {
unsigned int magic; /* must be EXEC_MAGIC */
unsigned int csize; /* size of code in bytes */
unsigned int dsize; /* size of initialized data in bytes */
unsigned int bsize; /* size of uninitialized data in bytes */
unsigned int crsize; /* size of code relocation info in bytes */
unsigned int drsize; /* size of data relocation info in bytes */
unsigned int symsize; /* size of symbol table in bytes */
unsigned int strsize; /* size of string space in bytes */
} ExecHeader;
 
The magic number is used to distinguish executable files from
other file types. This field must have the value EXEC_MAGIC.
 
The code size is given in bytes, but is always a multiple of 4.
This is the exact size of the code section in the executable file.
For the code size in memory see "executing an executable" below.
 
The initialized data size is given in bytes, but is always a
multiple of 4. This is the exact size of the initialized data
section in the executable file. For the data size in memory see
"executing an executable" below.
 
The uninitialized data size is given in bytes, but is always a
multiple of 4. There is no corresponding section to this value
contained within the executable. See "executing an executable"
below for the semantics of this value.
 
The code relocation info size is given in bytes, but is always
a multiple of sizeof(RelocRecord). These records describe the
changes to be applied to the code section during the link step.
This size is zero if the file is an executable.
 
The data relocation info size is given in bytes, but is always
a multiple of sizeof(RelocRecord). These records describe the
changes to be applied to the data section during the link step.
This size is zero if the file is an executable.
 
The size of the symbol table is given in bytes, but is always
a multiple of sizeof(SymbolRecord). The symbol table contains
information about symbols which are exported from or imported
into this object file. It is mainly used during the link step
and may not be present (size = 0) if the file is an executable.
 
The string space is used to store the names of the symbols in
the symbol table.
 
 
2) Code/Initialized Data
 
These sections contain the instructions and the initialized data
of the program, respectively.
 
 
3) Code/Data Relocation Records
 
The relocation records have the following structure:
 
typedef struct {
unsigned int offset; /* where to relocate */
int method; /* how to relocate */
int value; /* additive part of value */
int base; /* if MSB = 0: segment number */
/* if MSB = 1: symbol table index */
} RelocRecord;
 
The offset gives the position where the relocation has to be done,
in the form of a byte offset from the beginning of the section.
 
The method determines how the relocation is performed, and must
be one of the following constants:
METHOD_H16 /* write 16 bits with high part of value */
METHOD_L16 /* write 16 bits with low part of value */
METHOD_R16 /* write 16 bits with value relative to PC */
METHOD_R26 /* write 26 bits with value relative to PC */
METHOD_W32 /* write full 32 bit word with value */
 
"Value" and "base" together are used to compute the final value of
the relocated code or data item. The value is added to the value of
the base. The base is either the start address of a segment in memory,
or the value of an imported symbol. In the former case, which is marked
by an MSB of 0, the base is specified as one of the following constants:
SEGMENT_ABS /* absolute values */
SEGMENT_CODE /* code segment */
SEGMENT_DATA /* initialized data segment */
SEGMENT_BSS /* uninitialized data segment */
In the latter case, which is marked by an MSB of 1, the remaining bits
specify the index of the symbol in the symbol table.
 
 
4) Symbol Table Records
 
For every symbol which is imported into or exported from the current
object file, there is a corresponding symbol table record:
 
typedef struct {
unsigned int name; /* offset in string space */
int type; /* if MSB = 0: the symbol's segment */
/* if MSB = 1: the symbol is undefined */
int value; /* if symbol defined: the symbol's value */
/* if symbol not defined: meaningless */
} SymbolRecord;
 
The name of the symbol is given as an offset into the string space.
 
If the "type" has an MSB of 0, the symbol is defined here (i.e.,
it is exported), and the "type" specifies the segment (for the
segment constants see above) in which the symbol is defined, while
the "value" holds its value. Otherwise, the symbol is not defined
here (i.e., it is imported), and the "value" has no meaning.
 
 
5) Symbol String Storage
 
The strings are null-terminated and stored without any padding.
 
 
6) Executing an Executable
 
When an executable file is loaded into memory for execution, three
logical segments are set up: the code segment, the data segment (with
initialized data, followed by uninitialized data, which starts off
as all 0), and a stack.
 
The code segment begins at address 0 in virtual memory and is loaded
with the contents of the code section from the executable file.
 
The data segment begins at the next page boundary (multiple of 4 KB)
after the code segment. It is loaded with the contents of the data
section from the executable file and is followed immediately by the
"uninitialized data", which must be zeroed by the loader. The data
area is expanded upwards as requested by explicit "brk" system calls.
 
The stack is located in the highest possible locations in the virtual
address space, which are accessible in user mode, and thus expanding
downwards from (but excluding) the address 0x80000000. It is extended
automatically by the operating system.
/binutils/dof/dof.c
0,0 → 1,386
/*
* dof.c -- dump object file
*/
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
 
#include "../include/a.out.h"
 
 
#define MSB ((unsigned int) 1 << (sizeof(unsigned int) * 8 - 1))
 
 
/**************************************************************/
 
 
FILE *inFile;
ExecHeader execHeader;
char *segmentName[4] = { "ABS", "CODE", "DATA", "BSS" };
char *methodName[5] = { "H16", "L16", "R16", "R26", "W32" };
 
 
/**************************************************************/
 
 
void error(char *fmt, ...) {
va_list ap;
 
va_start(ap, fmt);
printf("Error: ");
vprintf(fmt, ap);
printf("\n");
va_end(ap);
exit(1);
}
 
 
/**************************************************************/
 
 
unsigned int read4FromEco(unsigned char *p) {
return (unsigned int) p[0] << 24 |
(unsigned int) p[1] << 16 |
(unsigned int) p[2] << 8 |
(unsigned int) p[3] << 0;
}
 
 
void write4ToEco(unsigned char *p, unsigned int data) {
p[0] = data >> 24;
p[1] = data >> 16;
p[2] = data >> 8;
p[3] = data >> 0;
}
 
 
void conv4FromEcoToNative(unsigned char *p) {
unsigned int data;
 
data = read4FromEco(p);
* (unsigned int *) p = data;
}
 
 
void conv4FromNativeToEco(unsigned char *p) {
unsigned int data;
 
data = * (unsigned int *) p;
write4ToEco(p, data);
}
 
 
/**************************************************************/
 
 
#define CODE_START (sizeof(ExecHeader))
#define DATA_START (CODE_START + execHeader.csize)
#define CRELOC_START (DATA_START + execHeader.dsize)
#define DRELOC_START (CRELOC_START + execHeader.crsize)
#define SYMTBL_START (DRELOC_START + execHeader.drsize)
#define STRING_START (SYMTBL_START + execHeader.symsize)
 
 
void dumpHeader(void) {
if (fseek(inFile, 0, SEEK_SET) < 0) {
error("cannot seek to exec header");
}
if (fread(&execHeader, sizeof(ExecHeader), 1, inFile) != 1) {
error("cannot read exec header");
}
conv4FromEcoToNative((unsigned char *) &execHeader.magic);
conv4FromEcoToNative((unsigned char *) &execHeader.csize);
conv4FromEcoToNative((unsigned char *) &execHeader.dsize);
conv4FromEcoToNative((unsigned char *) &execHeader.bsize);
conv4FromEcoToNative((unsigned char *) &execHeader.crsize);
conv4FromEcoToNative((unsigned char *) &execHeader.drsize);
conv4FromEcoToNative((unsigned char *) &execHeader.symsize);
conv4FromEcoToNative((unsigned char *) &execHeader.strsize);
if (execHeader.magic != EXEC_MAGIC) {
error("wrong magic number in exec header");
}
printf("Header\n");
printf(" size of code : %8u bytes\n", execHeader.csize);
printf(" size of data : %8u bytes\n", execHeader.dsize);
printf(" size of bss : %8u bytes\n", execHeader.bsize);
printf(" size of code relocs : %8u bytes\n", execHeader.crsize);
printf(" size of data relocs : %8u bytes\n", execHeader.drsize);
printf(" size of symbol table : %8u bytes\n", execHeader.symsize);
printf(" size of string space : %8u bytes\n", execHeader.strsize);
}
 
 
void dumpBytes(unsigned int totalSize) {
unsigned int currSize;
unsigned char line[16];
int n, i;
unsigned char c;
 
currSize = 0;
while (currSize < totalSize) {
if (totalSize - currSize >= 16) {
n = 16;
} else {
n = totalSize - currSize;
}
for (i = 0; i < n; i++) {
line[i] = fgetc(inFile);
}
printf("%08X: ", currSize);
for (i = 0; i < 16; i++) {
if (i < n) {
c = line[i];
printf("%02X", c);
} else {
printf(" ");
}
printf(" ");
}
printf(" ");
for (i = 0; i < 16; i++) {
if (i < n) {
c = line[i];
if (c >= 32 && c <= 126) {
printf("%c", c);
} else {
printf(".");
}
} else {
printf(" ");
}
}
printf("\n");
currSize += n;
}
}
 
 
void dumpCode(void) {
if (fseek(inFile, CODE_START, SEEK_SET) < 0) {
error("cannot seek to code section");
}
printf("\nCode Segment\n");
dumpBytes(execHeader.csize);
}
 
 
void dumpData(void) {
if (fseek(inFile, DATA_START, SEEK_SET) < 0) {
error("cannot seek to data section");
}
printf("\nData Segment\n");
dumpBytes(execHeader.dsize);
}
 
 
void dumpRelocs(unsigned int totalSize) {
unsigned int currSize;
int n;
RelocRecord relRec;
 
currSize = 0;
n = 0;
while (currSize < totalSize) {
if (fread(&relRec, sizeof(RelocRecord), 1, inFile) != 1) {
error("cannot read relocation record");
}
conv4FromEcoToNative((unsigned char *) &relRec.offset);
conv4FromEcoToNative((unsigned char *) &relRec.method);
conv4FromEcoToNative((unsigned char *) &relRec.value);
conv4FromEcoToNative((unsigned char *) &relRec.base);
printf(" %d:\n", n);
printf(" offset = 0x%08X\n", relRec.offset);
if (relRec.method < 0 || relRec.method > 4) {
error("illegal relocation method");
}
printf(" method = %s\n", methodName[relRec.method]);
printf(" value = 0x%08X\n", relRec.value);
if (relRec.base & MSB) {
printf(" base = symbol # %d\n", relRec.base & ~MSB);
} else {
if (relRec.base < 0 || relRec.base > 3) {
error("base contains an illegal segment number");
}
printf(" base = %s\n", segmentName[relRec.base]);
}
currSize += sizeof(RelocRecord);
n++;
}
}
 
 
void dumpCodeRelocs(void) {
if (fseek(inFile, CRELOC_START, SEEK_SET) < 0) {
error("cannot seek to code relocation section");
}
printf("\nCode Relocation Records\n");
dumpRelocs(execHeader.crsize);
}
 
 
void dumpDataRelocs(void) {
if (fseek(inFile, DRELOC_START, SEEK_SET) < 0) {
error("cannot seek to data relocation section");
}
printf("\nData Relocation Records\n");
dumpRelocs(execHeader.drsize);
}
 
 
void dumpString(unsigned int offset) {
long pos;
int c;
 
pos = ftell(inFile);
if (fseek(inFile, STRING_START + offset, SEEK_SET) < 0) {
error("cannot seek to string");
}
while (1) {
c = fgetc(inFile);
if (c == EOF) {
error("unexpected end of file");
}
if (c == 0) {
break;
}
fputc(c, stdout);
}
fseek(inFile, pos, SEEK_SET);
}
 
 
void dumpSymbolTable(void) {
unsigned int currSize;
int n;
SymbolRecord symRec;
 
if (fseek(inFile, SYMTBL_START, SEEK_SET) < 0) {
error("cannot seek to symbol table section");
}
printf("\nSymbol Table Records\n");
currSize = 0;
n = 0;
while (currSize < execHeader.symsize) {
if (fread(&symRec, sizeof(SymbolRecord), 1, inFile) != 1) {
error("cannot read symbol record");
}
conv4FromEcoToNative((unsigned char *) &symRec.name);
conv4FromEcoToNative((unsigned char *) &symRec.type);
conv4FromEcoToNative((unsigned char *) &symRec.value);
printf(" %d:\n", n);
printf(" name = ");
dumpString(symRec.name);
printf("\n");
if (symRec.type & MSB) {
printf(" --- undefined ---\n");
} else {
if (symRec.type < 0 || symRec.type > 3) {
error("type contains an illegal segment number");
}
printf(" segment = %s\n", segmentName[symRec.type]);
printf(" value = 0x%08X\n", symRec.value);
}
currSize += sizeof(SymbolRecord);
n++;
}
}
 
 
/**************************************************************/
 
 
void usage(char *myself) {
printf("Usage: %s\n", myself);
printf(" [-c] dump code\n");
printf(" [-d] dump data\n");
printf(" [-x] dump code relocations\n");
printf(" [-y] dump data relocations\n");
printf(" [-s] dump symbol table\n");
printf(" [-a] dump all\n");
printf(" file object file to be dumped\n");
exit(1);
}
 
 
int main(int argc, char *argv[]) {
int i;
char *argp;
int optionCode;
int optionData;
int optionCodeRelocs;
int optionDataRelocs;
int optionSymbolTable;
char *inName;
 
optionCode = 0;
optionData = 0;
optionCodeRelocs = 0;
optionDataRelocs = 0;
optionSymbolTable = 0;
inName = NULL;
for (i = 1; i < argc; i++) {
argp = argv[i];
if (*argp == '-') {
argp++;
switch (*argp) {
case 'c':
optionCode = 1;
break;
case 'd':
optionData = 1;
break;
case 'x':
optionCodeRelocs = 1;
break;
case 'y':
optionDataRelocs = 1;
break;
case 's':
optionSymbolTable = 1;
break;
case 'a':
optionCode = 1;
optionData = 1;
optionCodeRelocs = 1;
optionDataRelocs = 1;
optionSymbolTable = 1;
break;
default:
usage(argv[0]);
}
} else {
if (inName != NULL) {
usage(argv[0]);
}
inName = argp;
}
}
if (inName == NULL) {
usage(argv[0]);
}
inFile = fopen(inName, "r");
if (inFile == NULL) {
error("cannot open input file '%s'", inName);
}
dumpHeader();
if (optionCode) {
dumpCode();
}
if (optionData) {
dumpData();
}
if (optionCodeRelocs) {
dumpCodeRelocs();
}
if (optionDataRelocs) {
dumpDataRelocs();
}
if (optionSymbolTable) {
dumpSymbolTable();
}
fclose(inFile);
return 0;
}
/binutils/dof/Makefile
0,0 → 1,36
#
# Makefile for ECO32 object file dumper
#
 
BUILD = ../../build
 
CC = gcc -m32
CFLAGS = -g -Wall
LDFLAGS = -g
LDLIBS = -lm
 
SRCS = dof.c
OBJS = $(patsubst %.c,%.o,$(SRCS))
BIN = dof
 
.PHONY: all install clean
 
all: $(BIN)
 
install: $(BIN)
mkdir -p $(BUILD)/bin
cp $(BIN) $(BUILD)/bin
 
$(BIN): $(OBJS)
$(CC) $(LDFLAGS) -o $(BIN) $(OBJS) $(LDLIBS)
 
%.o: %.c
$(CC) $(CFLAGS) -o $@ -c $<
 
depend.mak:
$(CC) -MM -MG $(CFLAGS) $(SRCS) > depend.mak
 
-include depend.mak
 
clean:
rm -f *~ $(OBJS) $(BIN) depend.mak
/binutils/Makefile
0,0 → 1,25
#
# Makefile for building the assembler tool chain
#
 
BUILD = ../build
 
DIRS = ar as dof ld
 
.PHONY: all install clean
 
all:
for i in $(DIRS) ; do \
$(MAKE) -C $$i all ; \
done
 
install:
for i in $(DIRS) ; do \
$(MAKE) -C $$i install ; \
done
 
clean:
for i in $(DIRS) ; do \
$(MAKE) -C $$i clean ; \
done
rm -f *~
/Makefile
4,7 → 4,7
 
VERSION = 0.23
 
DIRS = doc
DIRS = doc binutils
BUILD = `pwd`/build
 
.PHONY: all compiler builddir clean dist

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.