|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 6270 (0x187e)
Types: TextFile
Names: »instructions.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/asm/instructions.c«
#include "asm.h"
int choiceinstr (ins)
int ins;
{
choicedef *chpt;
int num, i, fits;
Long value;
static char *opdpt;
if (label && *label)
insert (label, (long) lc, &o_none, curseg, NO);
chpt = (choicedef *)optab[ins].class;
num = chpt->field;
for (opdpt = opd; num > 1; num --) {
opdpt = index (opdpt, ',');
if (opdpt == NULL) {
reporterr (E_NOPS);
return (0);
}
opdpt++;
}
value = expr (&opdpt, &i, YES);
fits = i ? NO :
(value >= chpt->lorange &&
value <= chpt->hirange &&
curseg == exprseg);
if ((i = opsrch ((fits ? chpt->rname : chpt->nname),
optab, instrlen)) >= 0) {
(optab[i].action) (i);
} else {
reporterr (E_ILLOP);
}
return (0);
}
int geninstr (ins)
int ins;
{
static Acc cons = ~0L;
int nargs, length, i, j, k;
opdclass *oclass;
insclass *iclass;
Word itemtemp, obuf[MAXBYTPERINS];
Acc mask;
char *nextopd;
itemu item;
if (label && *label)
insert (label, (long) lc, &o_none, curseg, NO);
iclass = optab[ins].class;
length = iclass->length;
if (pass == 2) {
nargs = iclass->mopds;
for (i = 0; i < MAXBYTPERINS; i++)
obuf[i] = 0;
item.l = optab[ins].mask;
for (i = 0; i < MINBYTES; i++)
obuf[i] = item.s[i];
item.l = 0L;
nextopd = opd;
for (j = 0; j < nargs; j++) {
if (j != 0) {
if (*nextopd != ',') {
reporterr (E_NOPS);
} else {
nextopd++;
}
}
oclass = iclass->type[j];
item.l = expr (&nextopd, &ignerr, NO) + oclass->offset -
(oclass->relative ? lc : 0);
mask = cons >> (LONGLEN - oclass->length);
if (item.l < 0L && !oclass->signed)
reporterr (E_NEG);
if (((item.ls < 0L && oclass->signed) ? -item.ls : item.ls) & ~mask)
reporterr (E_TOOBIG);
item.l &= mask;
if (oclass->byteswapped) {
itemtemp = item.s[BYTPERLONG - 2];
item.s[BYTPERLONG - 2] = item.s[BYTPERLONG - 1];
item.s[BYTPERLONG - 1] = itemtemp;
}
i = LONGLEN - 8 - iclass->offset[j];
item.l <<= (i % 8);
i /= 8;
k = 0;
if (i < 0)
k = -i, i = 0;
for (; k < MAXBYTPERINS && i < BYTPERLONG; k++, i++)
#ifdef NORMBYTE
obuf[k] |= item.s[i];
#else
obuf[k] |= item.s[BYTPERLONG-1-i];
#endif
}
if (optop) {
optional (optop, obuf);
free (optop);
}
putoutbin (obuf, length);
listit (linecopy, lc, obuf, length);
}
lc += length;
return (0);
}
long expr (string, errind, test)
char **string;
int *errind;
int test;
{
long exp, val;
int op, err;
int uniop = 0;
segmnt *seg1, *seg2;
*errind = NO;
if (**string == '-')
uniop = 1;
else if (**string == '~')
uniop = 2;
if (uniop)
(*string)++;
exp = getval(string, &err, test, &seg1);
if (err) goto errorexit;
if (uniop == 2)
exp = ~exp;
else if (uniop == 1)
exp = -exp;
while (!isdelim(**string)) {
if ((op = getop (string)) == NOOP) {
if (!test) reporterr (E_EXPR);
errorexit: for (; !isdelim (**string); *string++) ;
*errind = YES;
return (0);
}
val = getval (string, &err, test, &seg2);
if (err) goto errorexit;
if (seg1 && seg2 && seg1 != seg2 && pass == 1)
reporterr (E_SEG);
switch (op) {
case PLUS:
exp += val;
break;
case MINUS:
exp -= val;
break;
case MULT:
exp *= val;
break;
case DIV:
exp /= val;
break;
case MOD:
exp %= val;
break;
case OR:
exp |= val;
break;
case AND:
exp &= val;
break;
case EXOR:
exp ^= val;
break;
case SHLF:
exp <<= val;
break;
case SHRT:
exp >>= val;
break;
default:
if (!test) reporterr (E_EXPR);
}
seg1 = seg2;
}
exprseg = seg1;
return (exp);
}
/* Snag literals and variable names. The literal classes are:
[digit]....[digit] unsigned decimal number
0[hexdigit]...[hexdigit]unsigned hexadecimal number
$ current location counter
'[char] single character, right just, zero fill
"[char][char] character pair
Returns a 16 bit value. Unary operations taken care of in expr;
byte swapping done if required by geninstr.
*/
long getval (strpt, errorret, test, segment)
segmnt **segment;
char **strpt;
int *errorret;
int test;
{
long total;
char name[33], *npt;
int i;
*segment = (segmnt *) 0;
*errorret = 0;
total = 0L;
if (isdigit (**strpt)) {
if (**strpt == '0') {
while (isxdigit (**strpt)) {
total *= 16;
total += xtod (**strpt);
(*strpt)++;
}
} else {
while (isdigit (**strpt)) {
total *= 10;
total += (Long)(**strpt - '0');
(*strpt)++;
}
}
} else if (islabel (**strpt)) {
npt = name;
while (islabel (**strpt)) {
*npt++ = **strpt;
(*strpt)++;
}
*npt = '\0';
if ((i = lookup (name)) == -1) {
if (pass == 2)
if (!test) reporterr (E_UNDEF);
*errorret = 1;
total = 0L;
} else {
total = symtab[i].value;
if (pass == 2 && symtab[i].segp)
total += (symtab[i].segp)->start;
*segment = symtab[i].segp;
}
} else if (**strpt == '\'') {
(*strpt)++;
if (**strpt == '\\') {
(*strpt)++;
total = escape (strpt);
} else {
total = **strpt;
(*strpt)++;
}
} else if (**strpt == '"') {
(*strpt)++;
if (**strpt == '\\') {
(*strpt)++;
total = escape (strpt);
} else {
total = **strpt;
(*strpt)++;
}
total <<= 8;
if (**strpt == '\\') {
(*strpt)++;
total |= escape (strpt);
} else {
total |= **strpt;
(*strpt)++;
}
} else if (**strpt == '$') {
total = lc;
*segment = curseg;
(*strpt)++;
} else {
if (!test) reporterr (E_EXPR);
*errorret = 1;
}
return (total);
}
char escape (st)
char **st;
{
switch (*((*st)++)) {
case 'b':
return ('\b');
case 'n':
return ('\n');
case 'r':
return ('\r');
case '^':
return ('\033');
case 'f':
return ('\f');
case 't':
return ('\t');
case '?':
return ('\177');
case '\\':
return ('\\');
default:
(*st)--;
if (isxdigit (**st) && isxdigit (*(*st + 1))) {
*st += 2;
return (xtod (*(*st - 2)) << 4 | xtod (*(*st - 1)));
} else {
return (*(*st++));
}
}
}
int xtod (c)
char c;
{
return ((int) c - (c > '9' ? (c > 'F' ? 'W' : '7') : '0'));
}
int getop (string)
char **string;
{
static char ops[] = OPSTRING;
char *k;
for (k = ops; *k; k++)
if (*k == **string) {
(*string)++;
return ((int) (k - ops));
}
(*string)++;
return (NOOP);
}