📄 obj386.c
字号:
/*
Copyright 1994-2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
This program is derived from the cc68k complier by
Matthew Brandt (mattb@walkingdog.net)
You may contact the author of this derivative at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "gen386.h"
#include "diag.h"
#include "lists.h"
#define DEBUG_VERSION 3.1
enum omf_type
{
THEADR = 0x80, /* module header */
COMENT = 0x88, /* comment record */
LINNUM = 0x95, /* line number record */
LNAMES = 0x96, /* list of names */
SEGDEF = 0x99, /* segment definition */
GRPDEF = 0x9A, /* group definition */
EXTDEF = 0x8C, /* external definition */
PUBDEF = 0x91, /* public definition */
COMDEF = 0xB0, /* common definition */
LEDATA = 0xA1, /* logical enumerated data */
LIDATA = 0xA3, FIXUPP = 0x9D, /* fixups (relocations) */
MODEND = 0x8A /* module end */
};
extern HASHREC **templateFuncs;
extern FILELIST *incfiles;
extern VIRTUAL_LIST *virtualFirst;
extern int prm_debug;
extern FILE *outputFile;
extern char version[];
extern char *infile;
extern EMIT_TAB segs[MAX_SEGS];
extern LIST *libincludes;
extern LINEBUF *linelist;
extern HASHREC **gsyms;
extern LIST *localfuncs, *localdata;
extern int prm_bss;
extern int outcode_base_address;
static int segxlattab[MAX_SEGS];
static int dgroupVal;
static int extSize, extIndex;
static char extbuf[1024];
static char *segnames[] =
{
0, "_TEXT", "_DATA", "_BSS", "_CONST", "_STRING", "cstartup", "crundown",
"cppinit", "cppexit", "$$TYPES", "$$SYMBOLS", "$$BROWSE"
};
static char *segclasses[] =
{
0, "CODE", "DATA", "BSS", "CONST", "STRING", "INITDATA", "EXITDATA",
"CPPINIT", "CPPEXIT", "DEBTYP", "DEBSYM", "BROWSE"
};
static char DgroupText[] = "DGROUP";
int put_ident(char *buf, int ident)
{
char *p = buf;
if (ident &0xc0000000)
*p++ = 0xc0;
ident &= 0x7fff;
*p++ = ident > 127 ? (ident >> 8) | 0x80: ident;
if (ident > 127)
*p++ = ident;
return p - buf;
}
//-------------------------------------------------------------------------
void emit_record(enum omf_type type, char *data, int len)
{
int i, cs = 0;
char buf[1100];
buf[0] = type;
*(short*)(buf + 1) = len + 1;
memcpy(buf + 3, data, len);
for (i = 0; i < len + 3; i++)
cs += buf[i];
buf[len + 3] = - cs;
owrite(buf, len + 4, 1, outputFile);
}
void omfFileName(void)
{
char buf[256];
strcpy(buf + 1, fullqualify(infile));
buf[0] = strlen(buf + 1);
emit_record(THEADR, buf, buf[0] + 1);
}
//-------------------------------------------------------------------------
void omfTranslatorName(void)
{
char buf[100];
*(short*)buf = 0;
sprintf(buf + 3, "CC386 Version %s (LADSoft)", version);
buf[2] = strlen(buf + 3);
emit_record(COMENT, buf, 3+buf[2]);
}
//-------------------------------------------------------------------------
void omfFileTime(char *file)
{
unsigned short time, date;
char buf[256];
int fd;
*(short*)buf = 0xe900;
if (file)
{
if (_dos_open(file, 0, &fd))
{
time = 0;
date = 0;
}
else
{
_dos_getftime(fd, &date, &time);
_dos_close(fd);
}
*(short*)(buf + 2) = time;
*(short*)(buf + 4) = date;
memcpy(buf + 7, file, strlen(file));
buf[6] = strlen(file);
emit_record(COMENT, buf, 7+buf[6]);
}
else
emit_record(COMENT, buf, 2);
}
//-------------------------------------------------------------------------
void omfDebugMarker(void)
{
if (prm_debug)
{
char buf[3];
buf[0] = 0x40;
buf[1] = 0xe9;
emit_record(COMENT, buf, 2);
}
}
//-------------------------------------------------------------------------
void omfLNames(void)
{
char buf[1024], *p = buf;
int pos = 1, i;
*p++ = 0;
for (i = 1; i < MAX_SEGS; i++)
{
if (segs[i].curlast || i < 4)
{
segxlattab[i] = pos++;
*p = strlen(segnames[i]);
strcpy(p + 1, segnames[i]);
p += *p + 1;
*p = strlen(segclasses[i]);
strcpy(p + 1, segclasses[i]);
p += *p + 1;
}
else
segxlattab[i] = 0;
}
dgroupVal = pos;
*p = strlen(DgroupText);
strcpy(p + 1, DgroupText);
p += *p + 1;
emit_record(LNAMES, buf, p - buf);
}
//-------------------------------------------------------------------------
void omfLibMod(void)
{
if (libincludes)
{
while (libincludes)
{
char buf[256], *p;
p = strrchr(libincludes->data, '\\');
if (p)
p++;
else
p = libincludes->data;
buf[0] = 0xa3;
buf[1] = strlen(p);
strcpy(buf + 2, p);
emit_record(COMENT, buf, buf[1] + 2);
libincludes = libincludes->link;
}
}
}
//-------------------------------------------------------------------------
void omfSegs(void)
{
char buf[100];
int i;
for (i = 1; i < MAX_SEGS; i++)
{
if (segxlattab[i])
{
if (i == codeseg)
buf[0] = 0x29;
else
buf[0] = 0xA9;
*(int*)(buf + 1) = segs[i].curlast;
buf[5] = segxlattab[i] *2;
buf[6] = segxlattab[i] *2+1;
buf[7] = 1;
emit_record(SEGDEF, buf, 8);
}
}
}
//-------------------------------------------------------------------------
void omfComDefs(void)
{
VIRTUAL_LIST *v = virtualFirst;
char buf[512], name[512], *p;
while (v)
{
putsym(name, v->sp, v->sp->name);
p = buf;
*p = strlen(name) + 1;
strcpy(p + 2, name);
p[1] = '@';
p += (*p) + 1;
*p++ = 0;
if (v->data)
*p++ = segxlattab[dataseg];
else
*p++ = segxlattab[codeseg];
if (v->seg->curlast > 128)
{
*p++ = 0x88;
*((int*)p)++ = v->seg->curlast;
}
else
*p++ = v->seg->curlast;
emit_record(COMDEF, buf, p - buf);
v = v->next;
}
}
//-------------------------------------------------------------------------
void omfGroups(void)
{
char buf[100], *p = buf + 1;
buf[0] = dgroupVal * 2;
if (segxlattab[2])
{
*p++ = 0xff;
*p++ = segxlattab[2];
}
if (segxlattab[3])
{
*p++ = 0xff;
*p++ = segxlattab[3];
}
if (segxlattab[4])
{
*p++ = 0xff;
*p++ = segxlattab[4];
}
if (segxlattab[5])
{
*p++ = 0xff;
*p++ = segxlattab[5];
}
emit_record(GRPDEF, buf, p - buf);
}
//-------------------------------------------------------------------------
void FlushExtBuf(void)
{
if (extSize)
{
emit_record(EXTDEF, extbuf, extSize);
extSize = 0;
}
}
//-------------------------------------------------------------------------
void omfputext(SYM *sp)
{
char buf[512];
putsym(buf, sp, sp->name);
sp->mainsym->value.i = extIndex++;
if (strlen(buf) + extSize > 1024-2)
FlushExtBuf();
extbuf[extSize] = strlen(buf);
strcpy(extbuf + extSize + 1, buf);
extSize += extbuf[extSize] + 1;
extbuf[extSize++] = 0;
}
//-------------------------------------------------------------------------
static void omfextdumphash(HASHREC **syms)
{
int i;
SYM *sp;
for (i = 0; i < HASHTABLESIZE; i++)
{
if ((sp = (SYM*)syms[i]) != 0)
{
while (sp)
{
if (sp->storage_class == sc_externalfunc && sp->mainsym
->extflag && !(sp->tp->cflags &DF_INTRINS))
{
omfputext(sp);
}
if (sp->storage_class == sc_external && sp->mainsym->extflag)
{
omfputext(sp);
}
if (sp->storage_class == sc_defunc)
{
SYM *sp1 = sp->tp->lst.head;
while (sp1)
{
if (sp1->storage_class == sc_externalfunc && sp1
->mainsym->extflag && !(sp1->tp->cflags &DF_INTRINS)
)
{
omfputext(sp1);
}
sp1 = sp1->next;
}
}
if (sp->storage_class == sc_namespace && !sp
->value.classdata.parentns->anonymous)
omfextdumphash(sp->value.classdata.parentns->table);
sp = sp->next;
}
}
}
}
//-------------------------------------------------------------------------
void omfExtDefs(void)
{
int i;
SYM *sp;
VIRTUAL_LIST *v = virtualFirst;
LIST *lf = localfuncs;
extIndex = 1;
extSize = 0;
while (v)
{
v->sp->value.i = extIndex++ + 0xc0000000;
v = v->next;
}
omfextdumphash(gsyms);
while (lf)
{
sp = lf->data;
if (sp->storage_class == sc_externalfunc && sp->mainsym->extflag && !
(sp->tp->cflags &DF_INTRINS))
{
omfputext(sp);
}
lf = lf->link;
}
lf = localdata;
while (lf)
{
sp = lf->data;
if (sp->mainsym->extflag)
omfputext(sp);
lf = lf->link;
}
for (i = 0; i < HASHTABLESIZE; i++)
{
struct _templatelist *tl;
if ((tl = (struct templatelist*)templateFuncs[i]) != 0)
{
while (tl)
{
if (!tl->sp->value.classdata.templatedata->hasbody && tl
->finalsp)
{
omfputext(tl->finalsp);
} tl = tl->next;
}
}
}
FlushExtBuf();
}
//-------------------------------------------------------------------------
void omfputimport(SYM *sp)
{
char buf[512], obuf[512];
int l, l1;
putsym(buf, sp, sp->name);
l = strlen(buf);
*(short*)obuf = 0xa000;
obuf[2] = 1; // import
obuf[3] = 0; // import by name
obuf[4] = l;
strcpy(obuf + 5, buf);
obuf[5+l] = l1 = strlen(sp->importfile);
strcpy(obuf + 6+l, sp->importfile);
obuf[6+l + l1] = l;
strcpy(obuf + 7+l + l1, buf);
emit_record(COMENT, obuf, 7+2 * l + l1);
}
//-------------------------------------------------------------------------
void omfImports(void)
{
SYM *sp;
int i;
LIST *lf = localfuncs;
while (lf)
{
sp = lf->data;
if (sp->mainsym->importable && sp->mainsym->importfile && sp->mainsym->extflag)
{
omfputimport(sp);
}
lf = lf->link;
}
lf = localdata;
while (lf)
{
sp = lf->data;
if (sp->mainsym->importable && sp->mainsym->importfile && sp->mainsym->extflag)
{
omfputimport(sp);
}
lf = lf->link;
}
for (i = 0; i < HASHTABLESIZE; i++)
{
if ((sp = (SYM*)gsyms[i]) != 0)
{
while (sp)
{
if (sp->mainsym->importable && sp->mainsym->importfile && sp->mainsym->extflag)
{
omfputimport(sp);
}
sp = sp->next;
}
}
}
}
//-------------------------------------------------------------------------
int omfgetseg(SYM *sp)
{
if (!sp->tp)
return dataseg;
switch (sp->storage_class)
{
case sc_member:
if (sp->value.classdata.gdeclare)
sp = sp->value.classdata.gdeclare;
else
if (sp->tp->type != bt_func && sp->tp->type != bt_ifunc)
DIAG("omfGetSeg - no static member initializer");
// fall through
case sc_static:
case sc_global:
if (sp->tp->type == bt_func || sp->tp->type == bt_ifunc)
if (sp->mainsym->gennedvirtfunc)
return sp->mainsym->value.i;
else
return codeseg;
/* fall through */
case sc_external:
if (sp->tp->cflags &DF_CONST)
return constseg;
else
if (sp->init || !prm_bss)
return dataseg;
else
return bssxseg;
case sc_externalfunc:
case sc_label:
if (sp->mainsym->gennedvirtfunc)
return sp->mainsym->value.i;
else
return codeseg;
case sc_type:
if (sp->mainsym->gennedvirtfunc)
{
// vtab & xt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -