📄 cc4.c
字号:
dumpstage();
snext = 0;
}
/*
** dump the staging buffer
*/
dumpstage()
{
int i;
stail = snext;
snext = stage;
while(snext < stail)
{
if(optimize)
{
restart:
i = -1;
while(++i <= HIGH_SEQ)
if(peep(seq[i]))
{
#ifdef DISOPT
if(isatty(output))
fprintf(stderr, " optimized %2u\n", i);
#endif
goto restart;
}
}
outcode(snext[0], snext[1]);
snext += 2;
}
}
/*
** change to a new segment
** may be called with NULL, CODESEG, or DATASEG
** With NASM the section names are case-sensitive
*/
toseg(newseg)
int newseg;
{
if(oldseg == newseg)
return;
/* if(oldseg == CODESEG)
outline("_TEXT ENDS");
else if(oldseg == DATASEG)
outline("_DATA ENDS"); <-- */
/* - FASM
if(newseg == CODESEG)
{
outline("SECTION .text");
}
else if(newseg == DATASEG)
outline("SECTION .data");
*/
oldseg = newseg;
}
/*
** declare entry point
*/
public(ident) int ident;{
if(ident == FUNCTION)
toseg(CODESEG);
else toseg(DATASEG);
/* - FASM
outstr("GLOBAL ");
outname(ssname);
*/
newline();
outname(ssname);
if(ident == FUNCTION) {
colon();
newline();
}
}
/*
** declare external reference
*/
external(name, size, ident) char *name; int size, ident; {
if(ident == FUNCTION)
toseg(CODESEG);
else toseg(DATASEG);
/* - FASM
outstr("EXTERN ");
outname(name);
/# colon();
outsize(size, ident); <-- #/
newline();
*/
}
/*
** output the size of the object pointed to.
*/
outsize(size, ident) int size, ident;
{
/* why not size on FUNCTION and POINTER ? */
if (ident == FUNCTION)
outstr("NEAR");
else if (ident == POINTER)
outstr("DWORD");
else if(size == 1)
outstr("BYTE");
else if(size == 2)
outstr("WORD");
else
outstr("DWORD");
}
/*
** point to following object(s)
*/
point() {
outline(" DW $+2");
}
/*
** dump the literal pool
*/
dumplits(size) int size;
{
int j, k;
k = 0;
while (k < litptr)
{
if(size == 1)
{
gen(BYTE_, NULL);
}
else if (size == 2)
{
gen(WORD_, NULL);
}
else
{
gen(DWORD_,NULL);
}
j = 10;
while(j--)
{
outdec(getint(litq + k, size));
k += size;
if(j == 0 || k >= litptr)
{
newline();
break;
}
fputc(',', output);
}
}
}
/*
** dump zeroes for default initial values
*/
dumpzero(size, count)
int size, count;
{
if(count > 0)
{
if(size == 1)
gen(BYTEr0, count);
else if (size == 2)
gen(WORDr0, count);
else
gen(DWORDr0, count);
}
}
/******************** optimizer functions ***********************/
/*
** Try to optimize sequence at snext in the staging buffer.
*/
peep(seq) int *seq; {
int *next, *count, *pop, n, skip, tmp, reply;
char c;
next = snext;
count = seq++;
while(*seq) {
switch(*seq) {
case any: if(next < stail) break; return (NO);
case pfree: if(isfree(PRI, next)) break; return (NO);
case sfree: if(isfree(SEC, next)) break; return (NO);
case comm: if(*next & COMMUTES) break; return (NO);
case _pop: if(pop = getpop(next)) break; return (NO);
default: if(next >= stail || *next != *seq) return (NO);
}
next += 2; ++seq;
}
/****** have a match, now optimize it ******/
*count += 1;
reply = skip = NO;
while(*(++seq) || skip) {
if(skip) {
if(*seq == 0) skip = NO;
continue;
}
if(*seq >= PCODES) {
c = *seq & 0xFF; /* get low byte of command */
n = c; /* and sign extend into n */
switch(*seq & 0xFF00) {
case ife: if(snext[1] != n) skip = YES; break;
case ifl: if(snext[1] >= n) skip = YES; break;
case go: snext += (n<<1); break;
case gc: snext[0] = snext[(n<<1)]; goto done;
case gv: snext[1] = snext[(n<<1)+1]; goto done;
case sum: snext[1] += snext[(n<<1)+1]; goto done;
case neg: snext[1] = -snext[1]; goto done;
case topop: pop[0] = n; pop[1] = snext[1]; goto done;
case swv: tmp = snext[1];
snext[1] = snext[(n<<1)+1];
snext[(n<<1)+1] = tmp;
done: reply = YES;
break;
}
}
else snext[0] = *seq; /* set p-code */
}
return (reply);
}
/*
** Is the primary or secondary register free?
** Is it zapped or unused by the p-code at pp
** or a successor? If the primary register is
** unused by it still may not be free if the
** context uses the value of the expression.
*/
isfree(reg, pp) int reg, *pp; {
char *cp;
while(pp < stail) {
cp = code[*pp];
if(*cp & USES & reg) return (NO);
if(*cp & ZAPS & reg) return (YES);
pp += 2;
}
if(usexpr) return (reg & 001); /* PRI => NO, SEC => YES at end */
else return (YES);
}
/*
** Get place where the currently pushed value is popped?
** NOTE: Function arguments are not popped, they are
** wasted with an ADDSP.
*/
getpop(next) int *next; {
char *cp;
int level; level = 0;
while(YES) {
if(next >= stail) /* compiler error */
return 0;
if(*next == POP2)
if(level) --level;
else return next; /* have a matching POP2 */
else if(*next == ADDSP) { /* after func call */
if((level -= (next[1]>>LBPW)) < 0)
return 0;
}
else {
cp = code[*next]; /* code string ptr */
if(*cp & PUSHES) ++level; /* must be a push */
}
next += 2;
}
}
/******************* output functions *********************/
colon() {
fputc(':', output);
}
newline() {
fputc('\15', output);
fputc(NEWLINE, output);
}
/*
** output assembly code.
**
*/
outcode(pcode, value)
int pcode, value;
{
int part, skip, count;
int byte_opt;
char *cp, *back;
int loc_label;
part = back = 0;
skip = NO;
byte_opt = 0;
cp = code[pcode] + 1; /* skip 1st byte of code string */
#ifdef _MSC_VER
switch (pcode)
{
case BYTE_:
case BYTEn:
case BYTEr0:
case WORD_:
case WORDn:
case WORDr0:
case DWORD_:
case DWORDn:
case DWORDr0:
case REFm:
case COMMAn:
case PLUSn:
break;
default:
dump_debug (pcode, value);
outtab ();
}
#endif
if (pcode == ADD1n)
{
if (value < 0)
{
pcode = SUB1n;
value = -value;
}
if (value < 128)
{
byte_opt = 1;
}
}
while(*cp)
{
if(*cp == '<')
{
++cp; /* skip to action code */
if(skip == NO)
switch(*cp)
{
case 'm':
outname(value+NAME);
break; /* mem ref by label */
case 'n':
if (byte_opt)
{
outstr ("BYTE ");
}
outdec(value);
break; /* numeric constant */
case 'o':
offset(value);
break; /* numeric constant */
case 'l':
outdec(litlab);
break; /* current literal label */
case 'g': /* generate local label */
loc_label = getlabel ();
break;
case 'd': /* dump local label */
outdec(loc_label);
break;
}
cp += 2; /* skip past > */
}
else if(*cp == '?') /* ?..if value...?...if not value...? */
{
switch(++part)
{
case 1:
if(value == 0)
skip = YES;
break;
case 2:
skip = !skip;
break;
case 3:
part = 0;
skip = NO;
break;
}
++cp; /* skip past ? */
}
else if(*cp == '#')
{ /* repeat #...# value times */
++cp;
if(back == 0)
{
if((count = value) < 1)
{
while(*cp && *cp++ != '#')
;
continue;
}
back = cp;
continue;
}
if(--count > 0)
cp = back;
else
back = 0;
}
else if(skip == NO)
fputc(*cp++, output);
else
++cp;
}
}
outdec(number) int number; {
int k, zs;
char c, *q, *r;
zs = 0;
k = 1000000000;
#ifdef _MSC_VER
// fprintf(output, "/* %d */", number);
#endif
if(number < 0) {
number = -number;
fputc('-', output);
}
while (k >= 1) {
q = 0;
r = number;
while(r >= k) {++q; r = r - k;}
c = q + '0';
if(c != '0' || k == 1 || zs) {
zs = 1;
fputc(c, output);
}
number = r;
k /= 10;
}
}
offset(number)
int number;
{
int k, zs;
char c, *q, *r;
zs = 0;
k = 1000000000;
if(number < 0) {
number = -number;
fputc('-', output);
}
else
{
fputc('+',output);
}
while (k >= 1) {
q = 0;
r = number;
while(r >= k) {++q; r = r - k;}
c = q + '0';
if(c != '0' || k == 1 || zs) {
zs = 1;
fputc(c, output);
}
number = r;
k /= 10;
}
}
outline(ptr) char ptr[]; {
outstr(ptr);
newline();
}
outname(ptr) char ptr[]; {
outstr("_");
while(*ptr >= ' ') fputc(*ptr++, output);
}
outstr(ptr) char ptr[]; {
while(*ptr == '\t' || *ptr >= ' ') fputc(*ptr++, output);
}
outtab ()
{
fputc ('\t', output);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -