📄 outco68.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 "gen68.h"
#include "diag.h"
#include "lists.h"
#define FULLVERSION
extern struct slit *strtab;
extern ASMNAME oplst[];
extern int global_flag;
extern enum e_sg curseg;
extern SYM *currentfunc;
extern int prm_asmfile;
extern DBGBLOCK *DbgBlocks[];
extern int prm_debug;
extern int prm_68020;
extern int prm_smalldata;
#define PUTWORD(p,x) { tempstore = (x) ; \
*(*(p))++=(((tempstore)>>8)&255); \
*(*(p))++=((tempstore)&255); }
static int fpcop = 1;
static int tempstore; // used in PUTWORD
int outcode_base_address;
EMIT_TAB segs[MAX_SEGS];
LINEBUF *linelist, *linetail;
VIRTUAL_LIST *virtualFirst, *virtualLast;
static LABEL **labelbuf;
void outcode_file_init(void)
{
int i;
labelbuf = xalloc(400 *sizeof(LABEL*));
for (i = 0; i < MAX_SEGS; i++)
memset(&segs[i], 0, sizeof(segs[i]));
linelist = 0;
virtualFirst = virtualLast = 0;
} void outcode_func_init(void)
{
int i;
// memset(labelbuf,0,400 * sizeof(LABEL *)) ;
for (i = 0; i < MAX_SEGS; i++)
segs[i].curbase = segs[i].curlast;
if (currentfunc)
if (curseg == virtseg)
{
currentfunc->mainsym->offset = outcode_base_address = 0;
}
else
currentfunc->mainsym->offset = outcode_base_address =
segs[codeseg].curbase;
}
//-------------------------------------------------------------------------
void InsertLabel(int lbl, int address, int seg)
{
int x = lbl / 512;
if (!labelbuf[x])
{
global_flag++;
labelbuf[x] = xalloc(512 *sizeof(LABEL));
global_flag--;
}
labelbuf[x][lbl % 512].address = address;
labelbuf[x][lbl % 512].seg = seg;
}
//-------------------------------------------------------------------------
int LabelAddress(int lbl)
{
if (labelbuf)
{
LABEL *p = labelbuf[lbl / 512];
if (p)
return p[lbl % 512].address;
}
return - 1;
// return labelbuf[lbl/512][lbl%512].address ;
}
//-------------------------------------------------------------------------
int LabelSeg(int lbl)
{
return labelbuf[lbl / 512][lbl % 512].seg;
}
//-------------------------------------------------------------------------
void InsertLine(int address, int line, int file)
{
LINEBUF *l;
global_flag++;
l = xalloc(sizeof(LINEBUF));
global_flag--;
l->address = address;
l->lineno = line;
l->file = file;
if (linelist)
linetail = linetail->next = l;
else
linelist = linetail = l;
}
//-------------------------------------------------------------------------
EMIT_TAB *gettab(int seg)
{
if (seg == virtseg)
return virtualLast->seg;
else
{
EMIT_TAB *rv = &segs[seg];
if (!rv->first)
{
global_flag++;
rv->first = rv->last = xalloc(sizeof(EMIT_LIST));
global_flag--;
}
return rv;
}
}
//-------------------------------------------------------------------------
void emit(int seg, unsigned char *data, int len)
{
EMIT_TAB *tab = gettab(seg);
int ofs = 0;
if (!tab->first)
{
global_flag++;
tab->first = tab->last = xalloc(sizeof(EMIT_LIST));
global_flag--;
}
tab->last->lastfilled = tab->last->filled;
tab->curlast += len;
while (len)
{
int size = len >= 1024 ? 1024 : len;
if (tab->last->filled + len > 1024)
{
int address = tab->last->address + tab->last->filled;
global_flag++;
tab->last = tab->last->next = xalloc(sizeof(EMIT_LIST));
tab->last->address = address;
global_flag++;
}
memcpy(tab->last->data + tab->last->filled, data + ofs, size);
tab->last->filled += size;
len -= size;
ofs += size;
}
}
//-------------------------------------------------------------------------
void reverseemit(int seg, unsigned char *data, int len)
{
char buf[256];
int i;
for (i = 0; i < len; i++)
buf[len - i - 1] = data[i];
emit(seg, buf, len);
}
//-------------------------------------------------------------------------
void write_to_seg(int seg, int offset, char *value, int len)
{
EMIT_TAB *tab = gettab(seg);
EMIT_LIST *lst = tab->first;
while (lst->address + lst->filled < offset)
lst = lst->next;
memcpy(lst->data + offset - lst->address, value, len);
}
//-------------------------------------------------------------------------
void gen_symbol_fixup(enum mode xmode, int seg, int address, SYM *pub, int size,
int ofs)
{
FIXUP *fixup;
EMIT_TAB *tab = gettab(seg);
global_flag++;
fixup = xalloc(sizeof(FIXUP));
global_flag--;
fixup->fmode = xmode;
fixup->address = address;
fixup->size = size;
fixup->ofs = ofs;
fixup->sym = pub;
if (tab->last->fixups)
tab->last->lastfixup = tab->last->lastfixup->next = fixup;
else
tab->last->fixups = tab->last->lastfixup = fixup;
} void gen_label_fixup(enum mode xmode, int seg, int address, int lab, int size,
int ofs)
{
FIXUP *fixup;
EMIT_TAB *tab = gettab(seg);
global_flag++;
fixup = xalloc(sizeof(FIXUP));
global_flag--;
fixup->fmode = xmode;
fixup->address = address;
fixup->size = size;
fixup->ofs = ofs;
fixup->label = lab;
if (tab->last->fixups)
tab->last->lastfixup = tab->last->lastfixup->next = fixup;
else
tab->last->fixups = tab->last->lastfixup = fixup;
} void outcode_dump_muldivval(void){}
void outcode_dump_browsedata(unsigned char *buf, int len)
{
emit(browseseg, buf, len);
}
//-------------------------------------------------------------------------
void outcode_dumplits(void)
{
struct slit *v = strtab;
int val = 0;
xstringseg();
while (v != 0)
{
InsertLabel(v->label, segs[stringseg].curlast, stringseg);
emit(curseg, v->str, v->len - 1);
if (v->type)
emit(curseg, (unsigned char*) &val, 2);
else
emit(curseg, (unsigned char*) &val, 1);
v = v->next;
} nl();
}
//-------------------------------------------------------------------------
void outcode_genref(SYM *sp, int offset)
{
EMIT_TAB *seg = gettab(curseg);
reverseemit(curseg, &offset, 4);
gen_symbol_fixup(fm_symbol, curseg, seg->last->address + seg->last
->lastfilled, sp, 4, offset);
}
//-------------------------------------------------------------------------
void outcode_gen_labref(int n)
{
int i = 0;
EMIT_TAB *seg = gettab(curseg);
emit(curseg, &i, 4);
gen_label_fixup(fm_label, curseg, seg->last->address + seg->last
->lastfilled, n, 4, 0);
}
/* the labels will already be resolved well enough by this point */
void outcode_gen_labdifref(int n1, int n2)
{
int i = LabelAddress(n1) - LabelAddress(n2);
EMIT_TAB *seg = gettab(curseg);
emit(curseg, &i, 4);
}
//-------------------------------------------------------------------------
void outcode_gensrref(SYM *sp, int val)
{
int vv = 0;
EMIT_TAB *seg = gettab(curseg);
emit(curseg, &vv, 4);
gen_symbol_fixup(fm_symbol, curseg, seg->last->address + seg->last
->lastfilled, sp, 4, 0);
reverseemit(curseg, &val, 4);
}
//-------------------------------------------------------------------------
void outcode_genstorage(int len)
{
char buf[256];
memset(buf, 0, 256);
while (len >= 256)
{
emit(curseg, buf, 256);
len -= 256;
}
if (len)
emit(curseg, buf, len);
}
//-------------------------------------------------------------------------
void outcode_genfloat(long double val)
{
float f = val;
reverseemit(curseg, &f, 4);
}
//-------------------------------------------------------------------------
void outcode_gendouble(long double val)
{
double d = val;
reverseemit(curseg, &d, 8);
}
//-------------------------------------------------------------------------
void outcode_genlongdouble(long double val)
{
reverseemit(curseg, &val, 10);
}
//-------------------------------------------------------------------------
void outcode_genstring(char *string, int len)
{
emit(curseg, string, len);
}
//-------------------------------------------------------------------------
void outcode_genbyte(int val)
{
emit(curseg, &val, 1);
}
//-------------------------------------------------------------------------
void outcode_genword(int val)
{
reverseemit(curseg, &val, 2);
}
//-------------------------------------------------------------------------
void outcode_genlong(int val)
{
reverseemit(curseg, &val, 4);
}
//-------------------------------------------------------------------------
void outcode_genlonglong(LLONG_TYPE val)
{
int vv = val;
#ifdef BCC32
val = val < 0 ? - 1: 0;
#else
val = val >> 32;
#endif
reverseemit(curseg, &val, 4);
reverseemit(curseg, &vv, 4);
}
//-------------------------------------------------------------------------
void outcode_align(int size)
{
EMIT_TAB *seg = gettab(curseg);
int adr = seg->last->address + seg->last->filled;
adr = size - adr % size;
if (size != adr)
outcode_genstorage(adr);
}
//-------------------------------------------------------------------------
void outcode_put_label(int lab)
{
EMIT_TAB *seg = gettab(curseg);
InsertLabel(lab, seg->last->address + seg->last->filled, curseg);
}
///////////////////////////////////////////////////
static int putbased(OCODE *ins, AMODE *data, int reg, unsigned char **p)
{
long val;
int resolved = 1;
val = ResolveOffset(ins, data->offset, &resolved);
if (!resolved)
{
if (prm_68020)
{
PUTWORD(p, 0x130 + (data->sreg << 12) + (data->mode ==
am_baseindxdata ? 0 : 0x8000) + (data->scale << 9) + (data->sz
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -