ack/util/ego/cs/cs_partit.c
1987-03-09 19:15:41 +00:00

376 lines
10 KiB
C

/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* Functions to partition the huge set of EM-instructions. */
#include "../../../h/em_mnem.h"
#include "../../../h/em_pseu.h"
#include "../../../h/em_reg.h"
#include "../../../h/em_spec.h"
#include "../share/types.h"
#include "../share/aux.h"
#include "../share/debug.h"
#include "../share/global.h"
#include "cs.h"
#include "cs_stack.h"
#define XXX (-1)
#define ARGW 0
#define WS 1
#define PS 2
#define FEF 3
#define FIF 4
#define CVT 5
#define ANY 0
#define PTR 1
#define FLT 2
STATIC struct {
byte i_group; /* Group of instruction. */
byte i_op1; /* Indication of size of operand of unary operator. */
/* Idem for 1st operand of binary operator. */
byte i_op2; /* Idem for 2nd operand of binary operator. */
byte i_av; /* Idem for result of operators. */
byte i_regtype; /* ANY, PTR, FLT. */
} info[] = {
XXX, XXX, XXX, XXX, XXX,
/* aar */ TERNAIR_OP, XXX, XXX, PS, PTR,
/* adf */ BINAIR_OP, ARGW, ARGW, ARGW, FLT,
/* adi */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* adp */ EXPENSIVE_LOAD, XXX, XXX, XXX, PTR,
/* ads */ BINAIR_OP, PS, ARGW, PS, PTR,
/* adu */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* and */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* asp */ FIDDLE_STACK, XXX, XXX, XXX, XXX,
/* ass */ FIDDLE_STACK, XXX, XXX, XXX, XXX,
/* beq */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* bge */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* bgt */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* ble */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* blm */ HOPELESS, XXX, XXX, XXX, XXX,
/* bls */ HOPELESS, XXX, XXX, XXX, XXX,
/* blt */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* bne */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* bra */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* cai */ SIDE_EFFECTS, XXX, XXX, XXX, XXX,
/* cal */ SIDE_EFFECTS, XXX, XXX, XXX, XXX,
/* cff */ TERNAIR_OP, XXX, XXX, CVT, FLT,
/* cfi */ TERNAIR_OP, XXX, XXX, CVT, ANY,
/* cfu */ TERNAIR_OP, XXX, XXX, CVT, ANY,
/* cif */ TERNAIR_OP, XXX, XXX, CVT, FLT,
/* cii */ TERNAIR_OP, XXX, XXX, CVT, ANY,
/* ciu */ TERNAIR_OP, XXX, XXX, CVT, ANY,
/* cmf */ BINAIR_OP, ARGW, ARGW, WS, ANY,
/* cmi */ BINAIR_OP, ARGW, ARGW, WS, ANY,
/* cmp */ BINAIR_OP, PS, PS, WS, ANY,
/* cms */ BINAIR_OP, ARGW, ARGW, WS, ANY,
/* cmu */ BINAIR_OP, ARGW, ARGW, WS, ANY,
/* com */ UNAIR_OP, ARGW, XXX, ARGW, ANY,
/* csa */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* csb */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* cuf */ TERNAIR_OP, XXX, XXX, CVT, FLT,
/* cui */ TERNAIR_OP, XXX, XXX, CVT, ANY,
/* cuu */ TERNAIR_OP, XXX, XXX, CVT, ANY,
/* dch */ UNAIR_OP, PS, XXX, PS, PTR,
/* dec */ UNAIR_OP, WS, XXX, WS, ANY,
/* dee */ KILL_ENTITY, XXX, XXX, XXX, XXX,
/* del */ KILL_ENTITY, XXX, XXX, XXX, XXX,
/* dup */ FIDDLE_STACK, XXX, XXX, XXX, XXX,
/* dus */ FIDDLE_STACK, XXX, XXX, XXX, XXX,
/* dvf */ BINAIR_OP, ARGW, ARGW, ARGW, FLT,
/* dvi */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* dvu */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* exg */ FIDDLE_STACK, XXX, XXX, XXX, XXX,
/* fef */ UNAIR_OP, ARGW, XXX, FEF, XXX,
/* fif */ BINAIR_OP, ARGW, ARGW, FIF, XXX,
/* fil */ IGNORE, XXX, XXX, XXX, XXX,
/* gto */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* inc */ UNAIR_OP, WS, XXX, WS, ANY,
/* ine */ KILL_ENTITY, XXX, XXX, XXX, XXX,
/* inl */ KILL_ENTITY, XXX, XXX, XXX, XXX,
/* inn */ BINAIR_OP, ARGW, WS, WS, ANY,
/* ior */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* lae */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* lal */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* lar */ LOAD_ARRAY, XXX, XXX, XXX, ANY,
/* ldc */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* lde */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* ldf */ EXPENSIVE_LOAD, XXX, XXX, XXX, ANY,
/* ldl */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* lfr */ FIDDLE_STACK, XXX, XXX, XXX, XXX,
/* lil */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* lim */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* lin */ IGNORE, XXX, XXX, XXX, XXX,
/* lni */ IGNORE, XXX, XXX, XXX, XXX,
/* loc */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* loe */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* lof */ EXPENSIVE_LOAD, XXX, XXX, XXX, ANY,
/* loi */ EXPENSIVE_LOAD, XXX, XXX, XXX, ANY,
/* lol */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* lor */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* los */ FIDDLE_STACK, XXX, XXX, XXX, XXX,
/* lpb */ UNAIR_OP, PS, XXX, PS, PTR,
/* lpi */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* lxa */ EXPENSIVE_LOAD, XXX, XXX, XXX, PTR,
/* lxl */ EXPENSIVE_LOAD, XXX, XXX, XXX, PTR,
/* mlf */ BINAIR_OP, ARGW, ARGW, ARGW, FLT,
/* mli */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* mlu */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* mon */ HOPELESS, XXX, XXX, XXX, XXX,
/* ngf */ UNAIR_OP, ARGW, XXX, ARGW, FLT,
/* ngi */ UNAIR_OP, ARGW, XXX, ARGW, ANY,
/* nop */ IGNORE, XXX, XXX, XXX, XXX,
/* rck */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* ret */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* rmi */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* rmu */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* rol */ BINAIR_OP, ARGW, WS, ARGW, ANY,
/* ror */ BINAIR_OP, ARGW, WS, ARGW, ANY,
/* rtt */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* sar */ STORE_ARRAY, XXX, XXX, XXX, XXX,
/* sbf */ BINAIR_OP, ARGW, ARGW, ARGW, FLT,
/* sbi */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* sbs */ BINAIR_OP, PS, PS, ARGW, ANY,
/* sbu */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* sde */ STORE_DIRECT, XXX, XXX, XXX, XXX,
/* sdf */ STORE_INDIR, XXX, XXX, XXX, XXX,
/* sdl */ STORE_DIRECT, XXX, XXX, XXX, XXX,
/* set */ UNAIR_OP, WS, XXX, ARGW, ANY,
/* sig */ FIDDLE_STACK, XXX, XXX, XXX, XXX,
/* sil */ STORE_INDIR, XXX, XXX, XXX, XXX,
/* sim */ STORE_DIRECT, XXX, XXX, XXX, XXX,
/* sli */ BINAIR_OP, ARGW, WS, ARGW, ANY,
/* slu */ BINAIR_OP, ARGW, WS, ARGW, ANY,
/* sri */ BINAIR_OP, ARGW, WS, ARGW, ANY,
/* sru */ BINAIR_OP, ARGW, WS, ARGW, ANY,
/* ste */ STORE_DIRECT, XXX, XXX, XXX, XXX,
/* stf */ STORE_INDIR, XXX, XXX, XXX, XXX,
/* sti */ STORE_INDIR, XXX, XXX, XXX, XXX,
/* stl */ STORE_DIRECT, XXX, XXX, XXX, XXX,
/* str */ HOPELESS, XXX, XXX, XXX, XXX,
/* sts */ HOPELESS, XXX, XXX, XXX, XXX,
/* teq */ UNAIR_OP, WS, XXX, WS, ANY,
/* tge */ UNAIR_OP, WS, XXX, WS, ANY,
/* tgt */ UNAIR_OP, WS, XXX, WS, ANY,
/* tle */ UNAIR_OP, WS, XXX, WS, ANY,
/* tlt */ UNAIR_OP, WS, XXX, WS, ANY,
/* tne */ UNAIR_OP, WS, XXX, WS, ANY,
/* trp */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* xor */ BINAIR_OP, ARGW, ARGW, ARGW, ANY,
/* zeq */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* zer */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* zge */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* zgt */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* zle */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* zlt */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* zne */ BBLOCK_END, XXX, XXX, XXX, XXX,
/* zre */ KILL_ENTITY, XXX, XXX, XXX, XXX,
/* zrf */ SIMPLE_LOAD, XXX, XXX, XXX, XXX,
/* zrl */ KILL_ENTITY, XXX, XXX, XXX, XXX
};
#define GROUP(n) (info[n].i_group)
#define OP1SIZE(l) (info[INSTR(l)].i_op1)
#define OP2SIZE(l) (info[INSTR(l)].i_op2)
#define AVSIZE(l) (info[INSTR(l)].i_av)
#define REGTYPE(n) (info[n].i_regtype)
int instrgroup(lnp)
line_p lnp;
{
if (INSTR(lnp) == op_lor && SHORT(lnp) == 1) {
/* We can't do anything with the stackpointer. */
return FIDDLE_STACK;
}
if (INSTR(lnp) < sp_fmnem || INSTR(lnp) > sp_lmnem) {
VI((short) INSTR(lnp));
return IGNORE;
}
return GROUP(INSTR(lnp));
}
bool stack_group(instr)
int instr;
{
/* Is this an instruction that only does something to the top of
* the stack?
*/
switch (GROUP(instr)) {
case SIMPLE_LOAD:
case EXPENSIVE_LOAD:
case LOAD_ARRAY:
case UNAIR_OP:
case BINAIR_OP:
case TERNAIR_OP:
return TRUE;
default:
return FALSE;
}
}
STATIC offset argw(lnp)
line_p lnp;
{
/* Some EM-instructions have their argument either on the same line,
* or on top of the stack. We give up when the argument is on top of
* the stack.
*/
struct token dummy;
if (TYPE(lnp) != OPNO) {
return off_set(lnp);
} else {
Pop(&dummy, (offset) ws);
return UNKNOWN_SIZE;
}
}
offset op11size(lnp)
line_p lnp;
{
/* Returns the size of the first argument of
* the unary operator in lnp.
*/
switch (OP1SIZE(lnp)) {
case ARGW:
return argw(lnp);
case WS:
return ws;
case PS:
return ps;
default:
assert(FALSE);
}
/* NOTREACHED */
}
offset op12size(lnp)
line_p lnp;
{
/* Same for first of binary. */
switch (OP1SIZE(lnp)) {
case ARGW:
return argw(lnp);
case PS:
return ps;
default:
assert(FALSE);
}
/* NOTREACHED */
}
offset op22size(lnp)
line_p lnp;
{
switch (OP2SIZE(lnp)) {
case ARGW:
return argw(lnp);
case WS:
return ws;
case PS:
return ps;
default:
assert(FALSE);
}
/* NOTREACHED */
}
/* Ternary operators are op_aar and conversions between types and/or sizes. */
offset op13size(lnp)
line_p lnp;
{
/* When the instruction is a conversion, the size of the first
* operand is the value of the second operand.
* We only handle the most likely case, namely that the second operand
* was pushed by a loc-instruction.
*/
if (INSTR(lnp) == op_aar) return ps;
if (lnp->l_prev != (line_p) 0 &&
lnp->l_prev->l_prev != (line_p) 0 &&
INSTR(lnp->l_prev->l_prev) == op_loc
)
return off_set(lnp->l_prev->l_prev);
else
return UNKNOWN_SIZE;
}
offset op23size(lnp)
line_p lnp;
{
if (INSTR(lnp) == op_aar)
return argw(lnp);
else
return ws;
}
offset op33size(lnp)
line_p lnp;
{
if (INSTR(lnp) == op_aar)
return ps;
else
return ws;
}
offset avsize(lnp)
line_p lnp;
{
/* Returns the size of the result of the instruction in lnp.
* If the instruction is a conversion this size is given on the stack.
* We only handle the case that this value was pushed by a loc.
*/
offset size;
switch (AVSIZE(lnp)) {
case ARGW:
return argw(lnp);
case WS:
return ws;
case PS:
return ps;
case FEF:
if ((size = argw(lnp)) != UNKNOWN_SIZE)
return size + ws;
else
return UNKNOWN_SIZE;
case FIF:
if ((size = argw(lnp)) != UNKNOWN_SIZE)
return size + size;
else
return UNKNOWN_SIZE;
case CVT:
if (lnp->l_prev != (line_p) 0 &&
INSTR(lnp->l_prev) == op_loc
)
return off_set(lnp->l_prev);
else
return UNKNOWN_SIZE;
default:
assert(FALSE);
break;
}
/* NOTREACHED */
}
int regtype(instr)
byte instr;
{
switch (REGTYPE(instr & BMASK)) {
case ANY:
return reg_any;
case PTR:
return reg_pointer;
case FLT:
return reg_float;
default:
assert(FALSE);
}
/* NOTREACHED */
}