home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
appleii
/
apxa3.c
/
assm3.c
< prev
Wrap
C/C++ Source or Header
|
2018-01-01
|
12KB
|
637 lines
#include "stdio.h"
#include "assm.d1"
#include "assm.d2"
/* class 1 machine operations processor - 1 byte, no operand field */
class1()
{
if (pass == LAST_PASS) {
loadlc(loccnt, 0, 1);
loadv(opval, 0, 1);
println();
}
loccnt++;
}
/* class 2 machine operations processor - 2 byte, relative addressing */
class2(ip)
int *ip;
{
if (pass == LAST_PASS) {
loadlc(loccnt, 0, 1);
loadv(opval, 0, 1);
while (prlnbuf[++(*ip)] == ' ');
if (evaluate(ip) != 0) {
loccnt += 2;
return;
}
loccnt += 2;
if ((value -= loccnt) >= -128 && value < 128) {
loadv(value, 1, 1);
println();
}
else error("Invalid branch address");
}
else loccnt += 2;
}
/* class 3 machine operations processor - various addressing modes */
class3(ip)
int *ip;
{
char ch;
int code;
int flag;
int i;
int ztmask;
while ((ch = prlnbuf[++(*ip)]) == ' ');
switch(ch) {
case 0:
case ';':
error("Operand field missing");
return;
case 'A':
case 'a':
if ((ch = prlnbuf[*ip + 1]) == ' ' || ch == 0) {
flag = ACC;
break;
}
default:
switch(ch = prlnbuf[*ip]) {
case '#': case '=':
flag = IMM1 | IMM2;
++(*ip);
break;
case '(':
flag = IND | INDX | INDY;
++(*ip);
break;
default:
flag = ABS | ZER | ZERX | ABSX | ABSY | ABSY2 | ZERY;
}
if ((flag & (INDX | INDY | ZER | ZERX | ZERY) & opflg) != 0)
udtype = UNDEFAB;
if (evaluate(ip) != 0)
return;
if (zpref != 0) {
flag &= (ABS | ABSX | ABSY | ABSY2 | IND | IMM1 | IMM2);
ztmask = 0;
}
else ztmask = ZER | ZERX | ZERY;
code = 0;
i = 0;
while (( ch = prlnbuf[(*ip)++]) != ' ' && ch != 0 && i++ < 4) {
code *= 8;
switch(ch) {
case ')': /* ) = 4 */
++code;
case ',': /* , = 3 */
++code;
case 'X': /* X = 2 */
case 'x':
++code;
case 'Y': /* Y = 1 */
case 'y':
++code;
break;
default:
flag = 0;
}
}
switch(code) {
case 0: /* no termination characters */
flag &= (ABS | ZER | IMM1 | IMM2);
break;
case 4: /* termination = ) */
flag &= IND;
break;
case 25: /* termination = ,Y */
flag &= (ABSY | ABSY2 | ZERY);
break;
case 26: /* termination = ,X */
flag &= (ABSX | ZERX);
break;
case 212: /* termination = ,X) */
flag &= INDX;
break;
case 281: /* termination = ),Y */
flag &= INDY;
break;
default:
flag = 0;
}
}
if ((opflg &= flag) == 0) {
error("Invalid addressing mode");
return;
}
if ((opflg & ztmask) != 0)
opflg &= ztmask;
switch(opflg) {
case ACC: /* single byte - class 3 */
if (pass == LAST_PASS) {
loadlc(loccnt, 0, 1);
loadv(opval + 8, 0, 1);
println();
}
loccnt++;
return;
case ZERX: case ZERY: /* double byte - class 3 */
opval += 4;
case INDY:
opval += 8;
case IMM2:
opval += 4;
case ZER:
opval += 4;
case INDX: case IMM1:
if (pass == LAST_PASS) {
loadlc(loccnt, 0, 1);
loadv(opval, 0, 1);
loadv(value, 1, 1);
println();
}
loccnt += 2;
return;
case IND: /* triple byte - class 3 */
opval += 16;
case ABSX:
case ABSY2:
opval += 4;
case ABSY:
opval += 12;
case ABS:
if (pass == LAST_PASS) {
opval += 12;
loadlc(loccnt, 0, 1);
loadv(opval, 0, 1);
loadv(value, 1, 1);
loadv(value >> 8, 2, 1);
println();
}
loccnt += 3;
return;
default:
error("Invalid addressing mode");
return;
}
}
/* pseudo operations processor */
pseudo(ip)
int *ip;
{
int count;
int i;
int tvalue;
int hibit; /* apple requires high bit to be on for chs */
int pi;
switch(opval) {
case 0: /* .byte pseudo */
labldef(loccnt);
loadlc(loccnt, 0, 1);
while (prlnbuf[++(*ip)] == ' '); /* field */
count = 0;
do {
if (prlnbuf[*ip] == '"') {
/* check for hibit on flag for ascii chs */
hibit = 0 ;
pi = *ip;
while((i = prlnbuf[++pi]) != '"' && i != 0 );
if (i != 0 )
while(prlnbuf[++pi] == ' ' ) ;
if (prlnbuf[pi] == '1' )
hibit = 0x80 ;
while ((tvalue = prlnbuf[++(*ip)]) != '"') {
if (tvalue == 0) {
error("Unterminated ASCII string");
return;
}
if (tvalue == '\\')
switch(tvalue = prlnbuf[++(*ip)]) {
case 'n':
tvalue = '\n';
break;
case 't':
tvalue = '\t';
break;
}
loccnt++;
if (pass == LAST_PASS) {
tvalue |= hibit ;
loadv(tvalue, count, 1);
if (++count >= 3) {
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
count = 0;
loadlc(loccnt, 0, 1);
}
}
}
++(*ip);
}
else {
if (evaluate(ip) != 0) {
loccnt++;
return;
}
loccnt++;
if (value > 0xff) {
error("Operand field size error");
return;
}
else if (pass == LAST_PASS) {
loadv(value, count, 1);
if (++count >= 3) {
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
count = 0;
loadlc(loccnt, 0, 1);
}
}
}
} while (prlnbuf[(*ip)++] == ',');
if ((pass == LAST_PASS) && (count != 0))
println();
return;
case 1: /* = pseudo */
while (prlnbuf[++(*ip)] == ' ');
if (evaluate(ip) != 0)
return;
labldef(value);
if (pass == LAST_PASS) {
loadlc(value, 1, 0);
println();
}
return;
case 2: /* .word pseudo */
labldef(loccnt);
loadlc(loccnt, 0, 1);
while (prlnbuf[++(*ip)] == ' ');
do {
if (evaluate(ip) != 0) {
loccnt += 2;
return;
}
loccnt += 2;
if (pass == LAST_PASS) {
loadv(value, 0, 1);
loadv(value>>8, 1, 1);
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
loadlc(loccnt, 0, 1);
}
} while (prlnbuf[(*ip)++] == ',');
return;
case 3: /* *= pseudo */
while (prlnbuf[++(*ip)] == ' ');
if (prlnbuf[*ip] == '*') {
if (evaluate(ip) != 0)
return;
if (undef != 0) {
error("Undefined symbol in operand field.");
return;
}
tvalue = loccnt;
}
else {
if (evaluate(ip) != 0)
return;
if (undef != 0) {
error("Undefined symbol in operand field.");
return;
}
tvalue = value;
}
loccnt = value;
labldef(tvalue);
if (pass == LAST_PASS) {
objcnt = 0;
loadlc(tvalue, 1, 0);
println();
}
return;
case 4: /* .list pseudo */
if (lflag >= 0)
lflag = 1;
return;
case 5: /* .nlst pseudo */
if (lflag >= 0)
lflag = iflag;
return;
case 6: /* .dbyt pseudo */
labldef(loccnt);
loadlc(loccnt, 0, 1);
while (prlnbuf[++(*ip)] == ' ');
do {
if (evaluate(ip) != 0) {
loccnt += 2;
return;
}
loccnt += 2;
if (pass == LAST_PASS) {
loadv(value>>8, 0, 1);
loadv(value, 1, 1);
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
loadlc(loccnt, 0, 1);
}
} while (prlnbuf[(*ip)++] == ',');
return;
case 7: /* ds pseudo */
while (prlnbuf[++(*ip)] == ' ');
if (evaluate(ip) != 0)
return;
if (undef != 0) {
error("Undefined symbol in operand field.");
return;
}
tvalue = loccnt;
labldef(loccnt);
loccnt += value;
if (pass == LAST_PASS) {
objcnt = 0;
loadlc(tvalue, 1, 0);
println();
}
return;
case 8: /* asc pseudo */
labldef(loccnt);
loadlc(loccnt, 0, 1);
while (prlnbuf[++(*ip)] == ' '); /* field */
count = 0;
do {
if (prlnbuf[*ip] == '\'') {
while ((tvalue = prlnbuf[++(*ip)]) != '\'') {
if (tvalue == 0) {
error("Unterminated ASCII string");
return;
}
if (tvalue == '\\')
switch(tvalue = prlnbuf[++(*ip)]) {
case 'n':
tvalue = '\n';
break;
case 't':
tvalue = '\t';
break;
}
loccnt++;
if (pass == LAST_PASS) {
tvalue |= msb ;
loadv(tvalue, count, 1);
if (++count >= 3) {
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
count = 0;
loadlc(loccnt, 0, 1);
}
}
}
++(*ip);
}
else {
if (evaluate(ip) != 0) {
loccnt++;
return;
}
loccnt++;
if (value > 0xff) {
error("Operand field size error");
return;
}
else if (pass == LAST_PASS) {
loadv(value, count, 1);
if (++count >= 3) {
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
count = 0;
loadlc(loccnt, 0, 1);
}
}
}
} while (prlnbuf[(*ip)++] == ',');
if ((pass == LAST_PASS) && (count != 0))
println();
return;
case 13: /* msb pseudo */
while (prlnbuf[++(*ip)] == ' ');
if (pass == LAST_PASS)
println();
pi = *ip;
if (( i = 0x20|prlnbuf[pi+1] ) == 'f' ){
msb=0;
return;
}
else if (i=='n'){
msb=0x80;
return;
}
error("Invalid symbol in operand field.");
return;
}
}
/* evaluate expression */
evaluate(ip)
int *ip;
{
int tvalue;
int invalid;
int parflg, value2;
char ch;
char op;
char op2;
op = '+';
parflg = zpref = undef = value = invalid = 0;
/* hcj: zpref should reflect the value of the expression, not the value of
the intermediate symbols
*/
while ((ch=prlnbuf[*ip]) != ' ' && ch != ')' && ch != ',' && ch != ';') {
tvalue = 0;
if (ch == '$' || ch == '@' || ch == '%')
tvalue = colnum(ip);
else if (ch >= '0' && ch <= '9')
tvalue = colnum(ip);
else if (ch >= 'a' && ch <= 'z')
tvalue = symval(ip);
else if (ch >= 'A' && ch <= 'Z')
tvalue = symval(ip);
else if ((ch == '_') || (ch == '.'))
tvalue = symval(ip);
else if (ch == '*') {
tvalue = loccnt;
++(*ip);
}
else if (ch == '\'') {
++(*ip);
tvalue = prlnbuf[*ip] & 0xff;
++(*ip);
}
else if (ch == '[') {
if (parflg == 1) {
error("Too many ['s in expression");
invalid++;
}
else {
value2 = value;
op2 = op;
value = tvalue = 0;
op = '+';
parflg = 1;
}
goto next;
}
else if (ch == ']') {
if (parflg == 0) {
error("No matching [ for ] in expression");
invalid++;
}
else {
parflg = 0;
tvalue = value;
value = value2;
op = op2;
}
++(*ip);
}
switch(op) {
case '+':
value += tvalue;
break;
case '-':
value -= tvalue;
break;
case '/':
value = (unsigned) value/tvalue;
break;
case '*':
value *= tvalue;
break;
case '%':
value = (unsigned) value%tvalue;
break;
case '^':
value ^= tvalue;
break;
case '~':
value = ~tvalue;
break;
case '&':
value &= tvalue;
break;
case '|':
value |= tvalue;
break;
case '<':
tvalue >>= 8; /* fall through to '<' */
case '>':
if (value != 0) {
error("High or low byte operator not first in operand field");
}
value = tvalue & 0xff;
zpref = 0;
break;
default:
invalid++;
}
if ((op=prlnbuf[*ip]) == ' '
|| op == ')'
|| op == ','
|| op == ';')
break;
else if (op != ']')
next: ++(*ip);
}
if (parflg == 1) {
error("Missing ] in expression");
return(1);
}
if (value < 0 || value >= 256) {
zpref = 1;
}
if (undef != 0) {
if (pass != FIRST_PASS) {
error("Undefined symbol in operand field");
invalid++;
}
value = 0;
}
else if (invalid != 0)
{
error("Invalid operand field");
}
else {
/*
This is the only way out that may not signal error
*/
if (value < 0 || value >= 256) {
zpref = 1;
}
else {
zpref = 0;
}
}
return(invalid);
}
/* collect number operand */
colnum(ip)
int *ip;
{
int mul;
int nval;
char ch;
nval = 0;
if ((ch = prlnbuf[*ip]) == '$')
mul = 16;
else if (ch >= '1' && ch <= '9') {
mul = 10;
nval = ch - '0';
}
else if (ch == '@' || ch == '0')
mul = 8;
else if (ch == '%')
mul = 2;
while ((ch = prlnbuf[++(*ip)] - '0') >= 0) {
if (ch > 9) {
ch -= ('A' - '9' - 1);
if (ch > 15)
ch -= ('a' - 'A');
if (ch > 15)
break;
if (ch < 10)
break;
}
if (ch >= mul)
break;
nval = (nval * mul) + ch;
}
return(nval);
}