home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Guide
/
c-cplusplus-interactive-guide.iso
/
c_ref
/
csource4
/
261_01
/
pop.c
< prev
next >
Wrap
Text File
|
1988-02-25
|
18KB
|
801 lines
/* pop.c - the operand field parser...
* (C) Copyright 1982 Steve Passe
* All Rights Reserved
*
* version 1.00
* created 11/8/82
*
* version 1.01
*
* 8/30/83 modified for Aztec ver. 1.05g smp
* 12/23/83 modified '*' to evaluate according to rorg smp
*
*/
/* begincode */
/* includes */
#include <stdio.h>
#include "as68.h"
#define RTERM 0x0100
#define SLASH 0x0101
#define HYPHEN 0x0102
#define PC_VALUE 0x0103
#define IMD 0x0104
#define COMMA 0x0105
#define POINT 0x0106
#define VALUE 0x0107
#define LVALUE 0x0108
#define FWRD_REF 0x0109
#define TOP 0x0200
#define BOTTOM 0x0201
#define LP 0x0202
#define RP 0x0203
#define PLUS 0x0204
#define MINUS 0x0205
#define MULT 0x0206
#define DIV 0x0207
#define LAND 0x0208
#define LOR 0x0209
#define LSHIFT 0x020a
#define RSHIFT 0x020b
#define NEGATE 0x020c
#define LIM_C 1
#define LM_C 2
#define RXP 0x0303 /* signals a forced short address */
/* externals */
extern struct _oprnd op1, op2; /* structs to hold operand val */
extern struct _symbol *symtbl;
extern char pass;
extern long loc_counter;
extern FLAG abs_long; /* default to absolute long add.*/
extern FLAG rorg;
extern char statement[STMNT_SIZE]; /* statement line buffer */
extern char *opfld_ptr;
extern long lex_val;
extern char *p;
static FLAG lv = 0;
static unsigned reg_num = 0;
static int last_typ = 0;
long val_stk[10] = {0L};
int opr_stk[10] = {BOTTOM};
static int val_sp = 0;
static int opr_sp = 0;
op_clear(op)
register struct _oprnd *op;
{
op->_long_val = op->_inxl = op->_rel_lbl = NULL;
op->_typ = NULL;
op->_regtyp = op->_iregtyp = op->_reg = op->_ireg = NULL;
}
op_eval(op)
register struct _oprnd *op;
{
/** register int r; */
register int shorty = NULL; /* force short address this line */
long val_push();
last_typ = NULL;
opr_sp = val_sp = 0;
reg_num = NULL;
/** this only works if nextfield doesn't eat up all the tabs! **/
switch (*opfld_ptr) {
case '\t':
case '\n':
case ' ':
case NULL:
return (op->_typ = _none);
case ',':
++opfld_ptr;
}
top:
switch (/**r =**/ op_scan(op)) {
case COMMA:
case NULL: /* determine operand type, finalize values in op */
reduce(TOP); /* get into one value */
switch (op->_typ) {
case _imd:
op->_data = val_stk[1];
return _imd;
case _reglst:
return _reglst;
default:
if (abs_long) op->_long_val = TRUE;
if (shorty) op->_long_val = FALSE; /* shorty overrides abs_long
AND long values in expression */
op->_addr = val_stk[1];
if (!op->_long_val && pass == 2) { /* pass 2/short, check range */
if (op->_addr & ~0xffff) {
op->_addr = 0;
return (op->_typ = LBL_RANGE);
}
}
return (op->_typ = _address);
}
case PLUS:
reduce(PLUS);
break;
case MINUS:
reduce(MINUS);
break;
case MULT:
reduce(MULT);
break;
case DIV:
reduce(DIV);
break;
case LAND:
reduce(LAND);
break;
case LOR:
reduce(LOR);
break;
case LSHIFT:
reduce(LSHIFT);
break;
case RSHIFT:
reduce(RSHIFT);
break;
case NEGATE:
reduce(NEGATE);
break;
case RXP:
reduce(RP);
if (val_sp != 1) return (op->_typ = OPRND_EVAL);
shorty = TRUE;
break;
case RP:
reduce(RP);
break;
case LP:
opr_push(LP);
break;
case PC_VALUE:
if (rorg) op->_rel_lbl = TRUE;
val_push(loc_counter);
break;
case IMD:
op->_typ = _imd;
break;
case LVALUE:
op->_long_val = TRUE;
case VALUE:
val_push(lex_val);
break;
case FWRD_REF:
/** op->_forward = TRUE; ? */
val_push(lex_val);
break;
case _an:
return (op->_typ = _an);
case _dn:
return (op->_typ = _dn);
case _pd_ani:
return (op->_typ = _pd_ani);
case _ani_pi:
return (op->_typ = _ani_pi);
case _ani:
if (val_sp == 0) {
return (op->_typ = _ani);
}
if (reduce(TOP) != 1) return (op->_typ = OPRND_EVAL);
op->_displ = val_stk[1];
return (op->_typ = _d16_ani);
case _pc:
if (reduce(TOP) != 1) return (op->_typ = OPRND_EVAL);
op->_displ = val_stk[1];
return (op->_typ = (op->_iregtyp ? _labeli : _label));
/** return (op->_typ = _labeli); **/
case _an_inx:
if (reduce(TOP) != 1) return (op->_typ = OPRND_EVAL);
op->_displ = val_stk[1];
return (op->_typ = _d8_anx);
case _ccr: return (op->_typ = _ccr);
case _sr: return (op->_typ = _sr);
case _usp: return (op->_typ = _usp);
case _reglst: return (op->_typ = _reglst);
case ERROR:
default:
return (op->_typ = OPRND_EVAL);
}
goto top;
}
reduce(tkn)
int tkn;
{
long val_push(), val_pop();
long temp;
while (opr_stk[opr_sp] >= (tkn & ~1)) {
switch (opr_stk[opr_sp--]) {
case PLUS:
val_push(val_pop() + val_pop());
continue;
case MINUS:
temp = val_pop();
val_push(val_pop() - temp);
continue;
case MULT:
val_push(val_pop() * val_pop());
continue;
case DIV:
temp = val_pop();
val_push(val_pop() / temp);
continue;
case LAND:
val_push(val_pop() & val_pop());
continue;
case LOR:
val_push(val_pop() | val_pop());
continue;
case LSHIFT:
temp = val_pop();
val_push(val_pop() << temp);
continue;
case RSHIFT:
temp = val_pop();
val_push(val_pop() >> temp);
continue;
case NEGATE:
val_push(-1 * val_pop());
continue;
case LP :
return val_sp;
case BOTTOM:
++opr_sp;
return val_sp;
}
}
opr_push(tkn);
return val_sp;
}
long
val_push(l)
long l;
{
return (val_stk[++val_sp] = l);
}
long
val_pop()
{
return (val_stk[val_sp--]);
}
opr_push(t)
int t;
{
return (opr_stk[++opr_sp] = t);
}
opr_pop()
{
return (opr_stk[opr_sp--]);
}
op_scan(op)
register struct _oprnd *op;
{
register int typ, len;
char s[32];
long _dtol(), _htol(), _btol(), _actol();
p = opfld_ptr;
if (typ = reg_scan(op)) {
opfld_ptr = p;
if (typ > 0) return typ;
goto foops;
}
switch (*opfld_ptr++) {
case '-': /* choose between NEGATE and MINUS */
switch (last_typ) {
case NULL:
case IMD:
case LP:
case PLUS:
case MINUS:
case MULT:
case DIV:
case LAND:
case LOR:
return (last_typ = NEGATE);
case RXP:
case LSHIFT:
case RSHIFT:
goto foops;
default:
return (last_typ = MINUS);
}
case '(': /* ( */
return (last_typ = LP);
case ')': /* ) */
if (opfld_ptr[0] == '.' /* ).s */
&& (opfld_ptr[1] == 's' || opfld_ptr[1] == 'S')) {
p = (opfld_ptr += 2); /* skip the '.s' */
return (last_typ = RXP);
}
else return (last_typ = RP);
case '#': /* # */
return (last_typ = IMD);
case '$': /* $ */
lex_val = _htol();
return (last_typ = (lv) ? LVALUE : VALUE);
case '%': /* % */
lex_val = _btol();
return (last_typ = VALUE);
case '*': /* * */
switch (last_typ) {
case NULL:
case IMD:
case LP:
case PLUS:
case MINUS:
case MULT:
case DIV:
case LAND:
case LOR:
case LSHIFT:
case RSHIFT:
return (last_typ = PC_VALUE);
case RXP: goto foops;
default:
return (last_typ = MULT);
}
case '/': /* / */
return (last_typ = DIV);
case '+': /* + */
return (last_typ = PLUS);
case '&': /* & */
return (last_typ = LAND);
case '!': /* ! */
return (last_typ = LOR);
case '>': /* >... */
if (*opfld_ptr++ != '>') goto foops; /* >FAIL */
return (last_typ = RSHIFT); /* >> */
case '<': /* <... */
if (*opfld_ptr++ != '<') goto foops; /* <FAIL */
return (last_typ = LSHIFT); /* << */
case '\'': /* ' */
lex_val = _actol();