📄 cc3.c
字号:
nargs = nargs + INTSIZE; /* count args*BPW */
if(match(",") == 0) break;
}
need(")");
if(ptr && (streq(ptr + NAME, "CCARGC") == 0)) /* accessing ... like va_args */
#ifdef INT32
gen(ARGCNTn, nargs >> LBPD); /* to get start of frame */
#else
gen(ARGCNTn, nargs >> LBPW); /* to get start of frame */
#endif
if(ptr)
gen(CALLm, ptr);
else
gen(CALL1, 0);
gen(ADDSP, csp + nargs);
}
/*
** true if is2's operand should be doubled
*/
fdouble (oper, is1, is2)
int oper, is1[], is2[];
{
//////////////////////////////////////////////////////
// This is a 'magic' function, its usage and function
// are not so obvious
//
// Purpose: when indexing an address we must know
// what we are pointing at so that the indexsize is
// proper, e,g,
// charptr++, should multiply index by a 1
// shortptr++, should multiply index by a 2
// intptr++, should multiply index by a 4
//
// Algorithm:
// IF
// operation is ADD12 or SUB12
// AND
// is1 is an address (pointer, array or via & operator
// AND
// is2 is NOT an address (pointer, array or via & operator
// THEN
// return the multiplication factor based on s1 (or true)
// ELSE
// return 0 (or false)
//
// Usage: The return value is used as a 'boolean'
// for nonconstant values, indicating that runtime code
// is necessary to do the necessary multiplication
// For contant value the return value is used to do a compile-time
// multiplication (shift actually)
//
if ((oper == ADD12 || oper == SUB12)
&& (is2[TA] == 0))
{
switch (is1[TA]>>2)
{
default:
case 1: // char
return (0);
case 2: // short
return (1);
case 4: // int
return (2);
}
}
return (0);
/*
- original code -
if((oper != ADD12 && oper != SUB12)
|| (is1[TA] >> 2 != BPW)
|| (is2[TA]))
return 0;
return 1;
*/
}
step (oper, is, oper2) int oper, is[], oper2; {
fetch(is);
gen(oper, is[TA] ? (is[TA] >> 2) : 1);
store(is);
if(oper2) gen(oper2, is[TA] ? (is[TA] >> 2) : 1);
}
store(is)
int is[];
{
char *ptr;
if(is[TI])
{ /* putstk */
if(is[TI] >> 2 == 1)
{
gen(PUTbp1, 0);
}
else if(is[TI] >> 2 == 2)
{
gen(PUTwp1, 0);
}
else
{
gen(PUTdp1, 0);
}
}
else
{ /* putmem */
ptr = is[ST];
if(ptr[IDENT] == POINTER)
{
#ifdef INT32 /* int and ptr-size are ALWAYS the same */
gen(PUTdm1, ptr);
#else
gen(PUTwm1, ptr);
#endif
}
else if (ptr[TYPE] >> 2 == 1)
{
gen(PUTbm1, ptr);
}
else if (ptr[TYPE] >> 2 == BPW)
{
gen(PUTwm1, ptr);
}
else
{
gen(PUTdm1, ptr);
}
}
}
fetch(is)
int is[];
{
char *ptr;
ptr = is[ST];
if(is[TI]) /* indirect */
{
if(is[TI] >> 2 == BPD) /* pointer to DWORD */
{
gen(GETd1p, 0);
}
else if(is[TI] >> 2 == BPW) /* pointer to WORD */
{
/* if INT32 must make distinction between signed/unsigned <-- */
gen(GETw1p, 0);
}
else
{
if(ptr[TYPE] & UNSIGNED)
gen(GETb1pu, 0);
else
gen(GETb1p, 0);
}
}
else
{ /* direct */
if(ptr[IDENT] == POINTER)
{
#ifdef INT32
gen(GETd1m, ptr);
#else
gen(GETw1m, ptr);
#endif
}
else if (ptr[TYPE] >> 2 == BPD)
{
gen(GETd1m, ptr);
}
else if (ptr[TYPE] >> 2 == BPW)
{
gen(GETw1m, ptr);
}
else
{
if(ptr[TYPE] & UNSIGNED)
gen(GETb1mu, ptr);
else
gen(GETb1m, ptr);
}
}
}
constant(is)
int is[];
{
int offset;
if (is[TC] = number(is + CV))
{
#ifdef INT32
gen(GETd1n, is[CV]);
#else
gen(GETw1n, is[CV]);
#endif
}
else if(is[TC] = chrcon(is + CV))
{
#ifdef INT32
gen(GETd1n, is[CV]);
#else
gen(GETw1n, is[CV]);
#endif
}
else if(string(&offset))
{
gen(POINT1l, offset);
}
else
{
return 0;
}
return 1;
}
number(value) int *value; {
int k, minus;
k = minus = 0;
while(1) {
if(match("+")) ;
else if(match("-")) minus = 1;
else break;
}
if(isdigit(ch) == 0) return 0;
if(ch == '0') {
while(ch == '0') inbyte();
if(toupper(ch) == 'X') {
inbyte();
while(isxdigit(ch)) {
if(isdigit(ch))
k = k*16 + (inbyte() - '0');
else k = k*16 + 10 + (toupper(inbyte()) - 'A');
}
}
else while (ch >= '0' && ch <= '7')
k = k*8 + (inbyte() - '0');
}
else while (isdigit(ch)) k = k*10 + (inbyte() - '0');
if(minus) {
*value = -k;
return (INT);
}
if((*value = k) < 0) return (UINT);
else return (INT);
}
chrcon(value)
int *value;
{
int k;
k = 0;
if(match("'") == 0)
return 0;
while(ch != '\'')
k = (k << 8) + (litchar() & 255);
gch();
*value = k;
return (INT);
}
string(offset) int *offset; {
char c;
if(match(quote) == 0) return 0;
*offset = litptr;
while (ch != '"') {
if(ch == 0) break;
stowlit(litchar(), 1);
}
gch();
litq[litptr++] = 0;
return 1;
}
stowlit(value, size) int value, size; {
if((litptr+size) >= LITMAX) {
error("literal queue overflow");
exit(ERRCODE);
}
putint(value, litq+litptr, size);
litptr += size;
}
litchar() {
int i, oct;
if(ch != '\\' || nch == 0) return gch();
gch();
switch(ch) {
case 'n': gch(); return NEWLINE;
case 't': gch(); return 9; /* HT */
case 'b': gch(); return 8; /* BS */
case 'f': gch(); return 12; /* FF */
}
i = 3;
oct = 0;
while((i--) > 0 && ch >= '0' && ch <= '7')
oct = (oct << 3) + gch() - '0';
if(i == 2) return gch();
else return oct;
}
/***************** pipeline functions ******************/
/*
** skim over terms adjoining || and && operators
*/
skim(opstr, tcode, dropval, endval, level, is)
char *opstr;
int tcode, dropval, endval, (*level)(), is[]; {
int k, droplab, endlab;
droplab = 0;
while(1) {
k = down1(level, is);
if(nextop(opstr)) {
bump(opsize);
if(droplab == 0) droplab = getlabel();
dropout(k, tcode, droplab, is);
}
else if(droplab) {
dropout(k, tcode, droplab, is);
#ifdef INT32
gen(GETd1n, endval);
#else
gen(GETw1n, endval);
#endif
gen(JMPm, endlab = getlabel());
gen(LABm, droplab);
#ifdef INT32
gen(GETd1n, dropval);
#else
gen(GETw1n, dropval);
#endif
gen(LABm, endlab);
is[TI] = is[TA] = is[TC] = is[CV] = is[SA] = 0;
return 0;
}
else return k;
}
}
/*
** test for early dropout from || or && sequences
*/
dropout(k, tcode, exit1, is)
int k, tcode, exit1, is[]; {
if(k) fetch(is);
else if(is[TC])
{
#ifdef INT32
gen(GETd1n, is[CV]);
#else
gen(GETw1n, is[CV]);
#endif
}
gen(tcode, exit1); /* jumps on false */
}
/*
** drop to a lower level
*/
down(opstr, opoff, level, is)
char *opstr; int opoff, (*level)(), is[]; {
int k;
k = down1(level, is);
if(nextop(opstr) == 0) return k;
if(k) fetch(is);
while(1) {
if(nextop(opstr)) {
int is2[7]; /* allocate only if needed */
null_is (is2);
bump(opsize);
opindex += opoff;
down2(op[opindex], op2[opindex], level, is, is2);
}
else return 0;
}
}
/*
** unary drop to a lower level
*/
down1(level, is) int (*level)(), is[]; {
int k, *before, *start;
setstage(&before, &start);
k = (*level)(is);
if(is[TC]) clearstage(before, 0); /* load constant later */
return k;
}
/*
** binary drop to a lower level
*/
down2(oper, oper2, level, is, is2)
int oper, oper2, (*level)(), is[], is2[]; {
int *before, *start;
char *ptr;
int value;
setstage(&before, &start);
is[SA] = 0; /* not "... op 0" syntax */
if(is[TC]) { /* consant op unknown */
if(down1(level, is2)) fetch(is2);
if(is[CV] == 0) is[SA] = snext;
gen(GETw2n, is[CV] << fdouble(oper, is2, is));
}
else { /* variable op unknown */
gen(PUSH1, 0); /* at start in the buffer */
if(down1(level, is2)) fetch(is2);
if(is2[TC]) { /* variable op constant */
if(is2[CV] == 0) is[SA] = start;
#ifdef INT32
csp += BPD; /* adjust stack and */
#else
csp += BPW; /* adjust stack and */
#endif
clearstage(before, 0); /* discard the PUSH */
if(oper == ADD12) { /* commutative */
#ifdef INT32
gen(GETd2n, is2[CV] << fdouble(oper, is, is2));
#else
gen(GETw2n, is2[CV] << fdouble(oper, is, is2));
#endif
}
else { /* non-commutative */
gen(MOVE21, 0);
#ifdef INT32
gen(GETd1n, is2[CV] << fdouble(oper, is, is2));
#else
gen(GETw1n, is2[CV] << fdouble(oper, is, is2));
#endif
}
}
else { /* variable op variable */
gen(POP2, 0);
if(value = fdouble(oper, is, is2))
{
gen(DBL1, 0); // index size 2
if (value > 1)
gen(DBL1, 0); // .. or even 4
}
if(value = fdouble(oper, is2, is))
{
gen(DBL2, 0);
if (value > 1)
gen(DBL2, 0);
}
}
}
if(oper) {
if(nosign(is) || nosign(is2)) oper = oper2;
if(is[TC] = is[TC] & is2[TC]) { /* constant result */
is[CV] = calc(is[CV], oper, is2[CV]);
clearstage(before, 0);
if(is2[TC] == UINT) is[TC] = UINT;
}
else { /* variable result */
gen(oper, 0);
if(oper == SUB12
&& is [TA] >> 2 == BPW
&& is2[TA] >> 2 == BPW) { /* difference of two word addresses */
gen(SWAP12, 0);
gen(GETw1n, 1);
gen(ASR12, 0); /* div by 2 */
}
is[OP] = oper; /* identify the operator */
}
if(oper == SUB12 || oper == ADD12) {
if(is[TA] && is2[TA]) /* addr +/- addr */
is[TA] = 0;
else if(is2[TA]) { /* value +/- addr */
is[ST] = is2[ST];
is[TI] = is2[TI];
is[TA] = is2[TA];
}
}
if(is[ST] == 0 || ((ptr = is2[ST]) && (ptr[TYPE] & UNSIGNED)))
is[ST] = is2[ST];
}
}
/*
** unsigned operand?
*/
nosign(is) int is[]; {
char *ptr;
if(is[TA]
|| is[TC] == UINT
|| ((ptr = is[ST]) && (ptr[TYPE] & UNSIGNED))
) return 1;
return 0;
}
/*
** calcualte signed constant result
*/
calc(left, oper, right) int left, oper, right; {
switch(oper) {
case ADD12: return (left + right);
case SUB12: return (left - right);
case MUL12: return (left * right);
case DIV12: return (left / right);
case MOD12: return (left % right);
case EQ12: return (left == right);
case NE12: return (left != right);
case LE12: return (left <= right);
case GE12: return (left >= right);
case LT12: return (left < right);
case GT12: return (left > right);
case AND12: return (left & right);
case OR12: return (left | right);
case XOR12: return (left ^ right);
case ASR12: return (left >> right);
case ASL12: return (left << right);
}
return (calc2(left, oper, right));
}
/*
** calcualte unsigned constant result
*/
calc2(left, oper, right) unsigned left, right; int oper; {
switch(oper) {
case MUL12u: return (left * right);
case DIV12u: return (left / right);
case MOD12u: return (left % right);
case LE12u: return (left <= right);
case GE12u: return (left >= right);
case LT12u: return (left < right);
case GT12u: return (left > right);
}
return (0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -