/* * (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 */ }