* Moved lcc and q3asm into code/tools
This commit is contained in:
parent
b1cef6352e
commit
ad118b9baf
452 changed files with 0 additions and 0 deletions
365
code/tools/lcc/src/bytecode.c
Normal file
365
code/tools/lcc/src/bytecode.c
Normal file
|
@ -0,0 +1,365 @@
|
|||
#include "c.h"
|
||||
#define I(f) b_##f
|
||||
|
||||
|
||||
static void I(segment)(int n) {
|
||||
static int cseg;
|
||||
|
||||
if (cseg != n)
|
||||
switch (cseg = n) {
|
||||
case CODE: print("code\n"); return;
|
||||
case DATA: print("data\n"); return;
|
||||
case BSS: print("bss\n"); return;
|
||||
case LIT: print("lit\n"); return;
|
||||
default: assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void I(address)(Symbol q, Symbol p, long n) {
|
||||
q->x.name = stringf("%s%s%D", p->x.name, n > 0 ? "+" : "", n);
|
||||
}
|
||||
|
||||
static void I(defaddress)(Symbol p) {
|
||||
print("address %s\n", p->x.name);
|
||||
}
|
||||
|
||||
static void I(defconst)(int suffix, int size, Value v) {
|
||||
switch (suffix) {
|
||||
case I:
|
||||
if (size > sizeof (int))
|
||||
print("byte %d %D\n", size, v.i);
|
||||
else
|
||||
print("byte %d %d\n", size, v.i);
|
||||
return;
|
||||
case U:
|
||||
if (size > sizeof (unsigned))
|
||||
print("byte %d %U\n", size, v.u);
|
||||
else
|
||||
print("byte %d %u\n", size, v.u);
|
||||
return;
|
||||
case P: print("byte %d %U\n", size, (unsigned long)v.p); return;
|
||||
case F:
|
||||
if (size == 4) {
|
||||
float f = v.d;
|
||||
print("byte 4 %u\n", *(unsigned *)&f);
|
||||
} else {
|
||||
unsigned *p = (unsigned *)&v.d;
|
||||
print("byte 4 %u\n", p[swap]);
|
||||
print("byte 4 %u\n", p[1 - swap]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
static void I(defstring)(int len, char *str) {
|
||||
char *s;
|
||||
|
||||
for (s = str; s < str + len; s++)
|
||||
print("byte 1 %d\n", (*s)&0377);
|
||||
}
|
||||
|
||||
static void I(defsymbol)(Symbol p) {
|
||||
if (p->scope == CONSTANTS)
|
||||
switch (optype(ttob(p->type))) {
|
||||
case I: p->x.name = stringf("%D", p->u.c.v.i); break;
|
||||
case U: p->x.name = stringf("%U", p->u.c.v.u); break;
|
||||
case P: p->x.name = stringf("%U", p->u.c.v.p); break;
|
||||
case F:
|
||||
{ // JDC: added this to get inline floats
|
||||
unsigned temp;
|
||||
|
||||
*(float *)&temp = p->u.c.v.d;
|
||||
p->x.name = stringf("%U", temp );
|
||||
}
|
||||
break;// JDC: added this
|
||||
default: assert(0);
|
||||
}
|
||||
else if (p->scope >= LOCAL && p->sclass == STATIC)
|
||||
p->x.name = stringf("$%d", genlabel(1));
|
||||
else if (p->scope == LABELS || p->generated)
|
||||
p->x.name = stringf("$%s", p->name);
|
||||
else
|
||||
p->x.name = p->name;
|
||||
}
|
||||
|
||||
static void dumptree(Node p) {
|
||||
switch (specific(p->op)) {
|
||||
case ASGN+B:
|
||||
assert(p->kids[0]);
|
||||
assert(p->kids[1]);
|
||||
assert(p->syms[0]);
|
||||
dumptree(p->kids[0]);
|
||||
dumptree(p->kids[1]);
|
||||
print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.u);
|
||||
return;
|
||||
case RET+V:
|
||||
assert(!p->kids[0]);
|
||||
assert(!p->kids[1]);
|
||||
print("%s\n", opname(p->op));
|
||||
return;
|
||||
}
|
||||
switch (generic(p->op)) {
|
||||
case CNST: case ADDRG: case ADDRF: case ADDRL: case LABEL:
|
||||
assert(!p->kids[0]);
|
||||
assert(!p->kids[1]);
|
||||
assert(p->syms[0] && p->syms[0]->x.name);
|
||||
print("%s %s\n", opname(p->op), p->syms[0]->x.name);
|
||||
return;
|
||||
case CVF: case CVI: case CVP: case CVU:
|
||||
assert(p->kids[0]);
|
||||
assert(!p->kids[1]);
|
||||
assert(p->syms[0]);
|
||||
dumptree(p->kids[0]);
|
||||
print("%s %d\n", opname(p->op), p->syms[0]->u.c.v.i);
|
||||
return;
|
||||
case ARG: case BCOM: case NEG: case INDIR: case JUMP: case RET:
|
||||
assert(p->kids[0]);
|
||||
assert(!p->kids[1]);
|
||||
dumptree(p->kids[0]);
|
||||
print("%s\n", opname(p->op));
|
||||
return;
|
||||
case CALL:
|
||||
assert(p->kids[0]);
|
||||
assert(!p->kids[1]);
|
||||
assert(optype(p->op) != B);
|
||||
dumptree(p->kids[0]);
|
||||
print("%s\n", opname(p->op));
|
||||
if ( !p->count ) { printf("pop\n"); }; // JDC
|
||||
return;
|
||||
case ASGN: case BOR: case BAND: case BXOR: case RSH: case LSH:
|
||||
case ADD: case SUB: case DIV: case MUL: case MOD:
|
||||
assert(p->kids[0]);
|
||||
assert(p->kids[1]);
|
||||
dumptree(p->kids[0]);
|
||||
dumptree(p->kids[1]);
|
||||
print("%s\n", opname(p->op));
|
||||
return;
|
||||
case EQ: case NE: case GT: case GE: case LE: case LT:
|
||||
assert(p->kids[0]);
|
||||
assert(p->kids[1]);
|
||||
assert(p->syms[0]);
|
||||
assert(p->syms[0]->x.name);
|
||||
dumptree(p->kids[0]);
|
||||
dumptree(p->kids[1]);
|
||||
print("%s %s\n", opname(p->op), p->syms[0]->x.name);
|
||||
return;
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
static void I(emit)(Node p) {
|
||||
for (; p; p = p->link)
|
||||
dumptree(p);
|
||||
}
|
||||
|
||||
static void I(export)(Symbol p) {
|
||||
print("export %s\n", p->x.name);
|
||||
}
|
||||
|
||||
static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
|
||||
int i;
|
||||
|
||||
(*IR->segment)(CODE);
|
||||
offset = 0;
|
||||
for (i = 0; caller[i] && callee[i]; i++) {
|
||||
offset = roundup(offset, caller[i]->type->align);
|
||||
caller[i]->x.name = callee[i]->x.name = stringf("%d", offset);
|
||||
caller[i]->x.offset = callee[i]->x.offset = offset;
|
||||
offset += caller[i]->type->size;
|
||||
}
|
||||
maxargoffset = maxoffset = argoffset = offset = 0;
|
||||
gencode(caller, callee);
|
||||
print("proc %s %d %d\n", f->x.name, maxoffset, maxargoffset);
|
||||
emitcode();
|
||||
print("endproc %s %d %d\n", f->x.name, maxoffset, maxargoffset);
|
||||
|
||||
}
|
||||
|
||||
static void gen02(Node p) {
|
||||
assert(p);
|
||||
if (generic(p->op) == ARG) {
|
||||
assert(p->syms[0]);
|
||||
argoffset += (p->syms[0]->u.c.v.i < 4 ? 4 : p->syms[0]->u.c.v.i);
|
||||
} else if (generic(p->op) == CALL) {
|
||||
maxargoffset = (argoffset > maxargoffset ? argoffset : maxargoffset);
|
||||
argoffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void gen01(Node p) {
|
||||
if (p) {
|
||||
gen01(p->kids[0]);
|
||||
gen01(p->kids[1]);
|
||||
gen02(p);
|
||||
}
|
||||
}
|
||||
|
||||
static Node I(gen)(Node p) {
|
||||
Node q;
|
||||
|
||||
assert(p);
|
||||
for (q = p; q; q = q->link)
|
||||
gen01(q);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void I(global)(Symbol p) {
|
||||
print("align %d\n", p->type->align > 4 ? 4 : p->type->align);
|
||||
print("LABELV %s\n", p->x.name);
|
||||
}
|
||||
|
||||
static void I(import)(Symbol p) {
|
||||
print("import %s\n", p->x.name);
|
||||
}
|
||||
|
||||
static void I(local)(Symbol p) {
|
||||
offset = roundup(offset, p->type->align);
|
||||
p->x.name = stringf("%d", offset);
|
||||
p->x.offset = offset;
|
||||
offset += p->type->size;
|
||||
}
|
||||
|
||||
static void I(progbeg)(int argc, char *argv[]) {}
|
||||
|
||||
static void I(progend)(void) {}
|
||||
|
||||
static void I(space)(int n) {
|
||||
print("skip %d\n", n);
|
||||
}
|
||||
|
||||
//========================================================
|
||||
|
||||
// JDC: hacked up to get interleaved source lines in asm code
|
||||
static char *sourceFile;
|
||||
static char *sourcePtr;
|
||||
static int sourceLine;
|
||||
|
||||
static int filelength( FILE *f ) {
|
||||
int pos;
|
||||
int end;
|
||||
|
||||
pos = ftell (f);
|
||||
fseek (f, 0, SEEK_END);
|
||||
end = ftell (f);
|
||||
fseek (f, pos, SEEK_SET);
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
static void LoadSourceFile( const char *filename ) {
|
||||
FILE *f;
|
||||
int length;
|
||||
|
||||
f = fopen( filename, "r" );
|
||||
if ( !f ) {
|
||||
print( ";couldn't open %s\n", filename );
|
||||
sourceFile = NULL;
|
||||
return;
|
||||
}
|
||||
length = filelength( f );
|
||||
sourceFile = malloc( length + 1 );
|
||||
if ( sourceFile ) {
|
||||
fread( sourceFile, length, 1, f );
|
||||
sourceFile[length] = 0;
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
sourceLine = 1;
|
||||
sourcePtr = sourceFile;
|
||||
}
|
||||
|
||||
static void PrintToSourceLine( int line ) {
|
||||
int c;
|
||||
|
||||
if ( !sourceFile ) {
|
||||
return;
|
||||
}
|
||||
while ( sourceLine <= line ) {
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; sourcePtr[i] && sourcePtr[i] != '\n' ; i++ ) {
|
||||
}
|
||||
c = sourcePtr[i];
|
||||
if ( c == '\n' ) {
|
||||
sourcePtr[i] = 0;
|
||||
}
|
||||
print( ";%d:%s\n", sourceLine, sourcePtr );
|
||||
if ( c == 0 ) {
|
||||
sourcePtr += i; // end of file
|
||||
} else {
|
||||
sourcePtr += i+1;
|
||||
}
|
||||
sourceLine++;
|
||||
}
|
||||
}
|
||||
|
||||
static void I(stabline)(Coordinate *cp) {
|
||||
static char *prevfile;
|
||||
static int prevline;
|
||||
|
||||
if (cp->file && (prevfile == NULL || strcmp(prevfile, cp->file) != 0)) {
|
||||
print("file \"%s\"\n", prevfile = cp->file);
|
||||
prevline = 0;
|
||||
if ( sourceFile ) {
|
||||
free( sourceFile );
|
||||
sourceFile = NULL;
|
||||
}
|
||||
// load the new source file
|
||||
LoadSourceFile( cp->file );
|
||||
}
|
||||
if (cp->y != prevline) {
|
||||
print("line %d\n", prevline = cp->y);
|
||||
PrintToSourceLine( cp->y );
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================
|
||||
|
||||
#define b_blockbeg blockbeg
|
||||
#define b_blockend blockend
|
||||
|
||||
Interface bytecodeIR = {
|
||||
{1, 1, 0}, /* char */
|
||||
{2, 2, 0}, /* short */
|
||||
{4, 4, 0}, /* int */
|
||||
{4, 4, 0}, /* long */
|
||||
{4, 4, 0}, /* long long */
|
||||
{4, 4, 0}, /* float */ // JDC: use inline floats
|
||||
{4, 4, 0}, /* double */ // JDC: don't ever emit 8 byte double code
|
||||
{4, 4, 0}, /* long double */ // JDC: don't ever emit 8 byte double code
|
||||
{4, 4, 0}, /* T* */
|
||||
{0, 4, 0}, /* struct */
|
||||
0, /* little_endian */
|
||||
0, /* mulops_calls */
|
||||
0, /* wants_callb */
|
||||
0, /* wants_argb */
|
||||
1, /* left_to_right */
|
||||
0, /* wants_dag */
|
||||
0, /* unsigned_char */
|
||||
I(address),
|
||||
I(blockbeg),
|
||||
I(blockend),
|
||||
I(defaddress),
|
||||
I(defconst),
|
||||
I(defstring),
|
||||
I(defsymbol),
|
||||
I(emit),
|
||||
I(export),
|
||||
I(function),
|
||||
I(gen),
|
||||
I(global),
|
||||
I(import),
|
||||
I(local),
|
||||
I(progbeg),
|
||||
I(progend),
|
||||
I(segment),
|
||||
I(space),
|
||||
0, /* I(stabblock) */
|
||||
0, /* I(stabend) */
|
||||
0, /* I(stabfend) */
|
||||
0, /* I(stabinit) */
|
||||
I(stabline),
|
||||
0, /* I(stabsym) */
|
||||
0, /* I(stabtype) */
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue