/* caudit.h
   Definitions for compiler audit suite.
   Copyright (C) 1991 by James R. Larus (larus@cs.wisc.edu).
   All rights reserved. */

/* $Header: /var/home/larus/CAudit/RCS/caudit.h,v 1.10 1991/12/11 22:49:22 larus Exp larus $ */


#ifndef STACK_SIZE
#define STACK_SIZE 100000
#endif

/* Data types: */

typedef unsigned long  INST;

typedef unsigned long  ADDR;

typedef unsigned long  DATUM;

typedef unsigned long  TIME;


typedef struct			/* Information a procedure */
{
  int index;			/* Index in proc_tbl */
  ADDR addr;			/* Starting address of procedure */
  char *name;			/* Name of procedure */
  int user_code;                /* == 1 if usercode */
  int user_decided;             /* == 1 if userdecided */ 
} proc_info;


typedef struct list_cell
{
  int car;
  struct list_cell *cdr;
} list_cell, *list;

#define CAR(x) (x->car)

#define CDR(x) (x->cdr)

#ifndef NULL
#define NULL (0)
#endif


/* These are the interesting categories of instructions. */

typedef enum
{
  COND_REL,			/* PC-relative conditional branch */
  COND_ABS,			/* Absolute conditional branch */
  UN_COND_REL,			/* PC-relative unconditional branch */
  UN_COND_ABS,			/* Absolute unconditional branch */
  UN_COND_IND,			/* Indirect unconditional branch */
  SUBR_ABS,			/* Absolute subroutine call */
  SUBR_REL,			/* Relative subroutine call */
  SUBR_IND,			/* Indirect subroutine call */
  SUBR_RET,			/* Subroutine return */
  SYS_CALL,			/* System call */
  MEM_LOAD,			/* Memory load */
  MEM_STORE,			/* Memory store */
  OTHER				/* Anything else */
} INST_TYPE;

/* Type large enough to hold a single bit for each register that could be
   part of a slice of an address calculation.

   For MIPS, we use $k0, $k1 (26, 27) for lo and hi since user code
   should never play with $k0 and $k1.  */

typedef long REG_SET;


/* Exported functions: */

proc_info *addr_to_proc_info (ADDR);
list cons (int, list);
int could_begin_switch (INST);
void fatal_error ();
ADDR find_switch_tbl (ADDR, INST, int *, int *, ADDR *);
INST_TYPE inst_category (INST);
int is_delayed (INST, int);
void read_aout (char *);
char *string_copy (char *);
ADDR switch_tbl_entry (ADDR, ADDR);
ADDR target_address (ADDR, INST);
void warn ();
char *xmalloc (int);

#define CONS(A, B) cons((int)A, (list)B)


/* Exported variables: */

INST *text_seg;			/* Instructions in text segment */

ADDR text_start;		/* Starting address of text segment */

ADDR text_end;			/* First address beyond text segment */

#define DATA INST

DATA *data_seg;

ADDR data_start;

ADDR data_end;

/* The next two variables were earlier on local to caudit.c. But now
   they are needed in flow.c 
   */

proc_info *proc_tbl;            /* Address information on procedures */

int num_procs;                  /* Number of procedures in a.out */

/* Definitions: */

#define GET_INST(pc) (text_seg [((pc) - text_start) / sizeof(INST)])

#define GET_DATA(addr) (data_seg [((addr) - data_start) / sizeof(DATA)])

#define INST_SIZE(inst) (sizeof (INST))

#define DELAY_SLOT_SIZE(inst) (sizeof (INST))


#define CLEAR_REG_SET(SET) SET = 0

#define REG_IN_SET(SET, REG) ((SET) & (1 << (REG)))

#define PUT_REG_IN_SET(SET, REG) (SET) |= (1 << (REG))

#define REG_SET_INTER(S1, S2) ((S1) & (S2))

#define REG_SET_EMPTY(SET) ((SET) == 0)

#define DEFINES_REG(PC) inst_defines (PC, PC + INST_SIZE (GET_INST (PC)))


/* Compute hash code */

#define HASHBITS 30

#ifndef HASH_TBL_SIZE
#define HASH_TBL_SIZE 100003
#endif

#define HASH_FUNC(ADDR) \
  ((((int) (ADDR) + ((int) (ADDR) >> 16)) & ((1 << HASHBITS) - 1))	\
   % HASH_TBL_SIZE)


/* Operations on a general stack */

#define PUSH(X) if (stack_ptr == STACK_SIZE)				\
		  fatal_error ("Stack overflow\n");			\
		else							\
		  stack[stack_ptr++] = (long)(X)

#define POP(T, X) if (stack_ptr == 0)					\
		  fatal_error ("Stack underflow\n");			\
		else							\
		  X = (T)stack[--stack_ptr]


#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define MAX(A, B) ((A) > (B) ? (A) : (B))

#define streq(a, b) !strcmp(a, b)
#define strneq(a, b, n) !strncmp(a, b, n)



/* MIPS-specific definitions: */

/* Register names (MIPS): */

#define R_ZERO	0
#define R_AT	1
#define R_V0	2
#define R_V1	3
#define R_A0	4
#define R_A1	5
#define R_A2	6
#define R_A3	7
#define R_T0	8
#define R_T1	9
#define R_T2	10
#define R_T3	11
#define R_T4	12
#define R_T5	13
#define R_T6	14
#define R_T7	15
#define R_S0	16
#define R_S1	17
#define R_S2	18
#define R_S3	19
#define R_S4	20
#define R_S5	21
#define R_S6	22
#define R_S7	23
#define R_T8	24
#define R_T9	25
#define R_K0	26
#define R_K1	27
#define R_GP	28
#define R_SP	29
#define R_S8	30
#define R_RA	31

#define R_HI R_K0		/* K0/K1 can't be used by user programs */
#define R_LO R_K1

#define F0	32
#define F2	34
#define F4	36
#define F6	38
#define F8	40
#define F10	42
#define F12	44
#define F14	46
#define F16	48
#define F18	50
#define F20	52
#define F22	54
#define F24	56
#define F26	58
#define F28	60
#define F30	62


/* MIPS opcodes (defined by bits 31-26) */

#define    OP_MASK   0xfc000000
#define    OP_SHIFT  26
#define    sOP_MASK  0x3f

#define    SPECIAL  0x00000000
#define    sSPECIAL ((0x00000000 >> OP_SHIFT) & sOP_MASK)
#define    BCOND    0x04000000
#define    sBCOND   ((0x04000000 >> OP_SHIFT) & sOP_MASK)
#define    J        0x08000000
#define    sJ       ((0x08000000 >> OP_SHIFT) & sOP_MASK)
#define    JAL      0x0c000000
#define    sJAL     ((0x0c000000 >> OP_SHIFT) & sOP_MASK)
#define    BEQ      0x10000000
#define    sBEQ     ((0x10000000 >> OP_SHIFT) & sOP_MASK)
#define    BNE      0x14000000
#define    sBNE     ((0x14000000 >> OP_SHIFT) & sOP_MASK)
#define    BLEZ     0x18000000
#define    sBLEZ    ((0x18000000 >> OP_SHIFT) & sOP_MASK)
#define    BGTZ     0x1c000000
#define    sBGTZ    ((0x1c000000 >> OP_SHIFT) & sOP_MASK)
#define    ADDI     0x20000000
#define    sADDI    ((0x20000000 >> OP_SHIFT) & sOP_MASK)
#define    ADDIU    0x24000000
#define    sADDIU   ((0x24000000 >> OP_SHIFT) & sOP_MASK)
#define    SLTI     0x28000000
#define    sSLTI    ((0x28000000 >> OP_SHIFT) & sOP_MASK)
#define    SLTIU    0x2c000000
#define    sSLTIU   ((0x2c000000 >> OP_SHIFT) & sOP_MASK)
#define    ANDI     0x30000000
#define    sANDI    ((0x30000000 >> OP_SHIFT) & sOP_MASK)
#define    ORI      0x34000000
#define    sORI     ((0x34000000 >> OP_SHIFT) & sOP_MASK)
#define    XORI     0x38000000
#define    sXORI    ((0x38000000 >> OP_SHIFT) & sOP_MASK)
#define    LUI      0x3c000000
#define    sLUI     ((0x3c000000 >> OP_SHIFT) & sOP_MASK)
#define    COP0     0x40000000
#define    sCOP0    ((0x40000000 >> OP_SHIFT) & sOP_MASK)
#define    COP1     0x44000000
#define    sCOP1    ((0x44000000 >> OP_SHIFT) & sOP_MASK)
#define    COP2     0x48000000
#define    sCOP2    ((0x48000000 >> OP_SHIFT) & sOP_MASK)
#define    COP3     0x4c000000
#define    sCOP3    ((0x4c000000 >> OP_SHIFT) & sOP_MASK)
#define    LB       0x80000000
#define    sLB      ((0x80000000 >> OP_SHIFT) & sOP_MASK)
#define    LH       0x84000000
#define    sLH      ((0x84000000 >> OP_SHIFT) & sOP_MASK)
#define    LWL      0x88000000
#define    sLWL     ((0x88000000 >> OP_SHIFT) & sOP_MASK)
#define    LW       0x8c000000
#define    sLW      ((0x8c000000 >> OP_SHIFT) & sOP_MASK)
#define    LBU      0x90000000
#define    sLBU     ((0x90000000 >> OP_SHIFT) & sOP_MASK)
#define    LHU      0x94000000
#define    sLHU     ((0x94000000 >> OP_SHIFT) & sOP_MASK)
#define    LWR      0x98000000
#define    sLWR     ((0x98000000 >> OP_SHIFT) & sOP_MASK)
#define    SB       0xa0000000
#define    sSB      ((0xa0000000 >> OP_SHIFT) & sOP_MASK)
#define    SH       0xa4000000
#define    sSH      ((0xa4000000 >> OP_SHIFT) & sOP_MASK)
#define    SWL      0xa8000000
#define    sSWL     ((0xa8000000 >> OP_SHIFT) & sOP_MASK)
#define    SW       0xac000000
#define    sSW      ((0xac000000 >> OP_SHIFT) & sOP_MASK)
#define    SWR      0xb8000000
#define    sSWR     ((0xb8000000 >> OP_SHIFT) & sOP_MASK)
#define    LWC0     0xc0000000
#define    sLWC0    ((0xc0000000 >> OP_SHIFT) & sOP_MASK)
#define    SWC0     0xe0000000
#define    sSWC0    ((0xe0000000 >> OP_SHIFT) & sOP_MASK)
#define    LWC1     0xc4000000
#define    sLWC1    ((0xc4000000 >> OP_SHIFT) & sOP_MASK)
#define    SWC1     0xe4000000
#define    sSWC1    ((0xe4000000 >> OP_SHIFT) & sOP_MASK)
#define    LWC2     0xc8000000
#define    sLWC2    ((0xc8000000 >> OP_SHIFT) & sOP_MASK)
#define    SWC2     0xe8000000
#define    sSWC2    ((0xe8000000 >> OP_SHIFT) & sOP_MASK)
#define    LWC3     0xcc000000
#define    sLWC3    ((0xcc000000 >> OP_SHIFT) & sOP_MASK)
#define    SWC3     0xec000000
#define    sSWC3    ((0xec000000 >> OP_SHIFT) & sOP_MASK)


/* Sub-codes of opcode SPECIAL (defined by bits 5-0) */

#define    SPEC_MASK 0x3f
#define    SLL       00
#define    SRL       02
#define    SRA       03
#define    SLLV      04
#define    SRLV      06
#define    SRAV      07
#define    JR       010
#define    JALR     011
#define    SYSCALL  014
#define    BREAK    015
#define    MFHI     020
#define    MTHI     021
#define    MFLO     022
#define    MTLO     023
#define    MULT     030
#define    MULTU    031
#define    DIV      032
#define    DIVU     033
#define    ADD      040
#define    ADDU     041
#define    SUB      042
#define    SUBU     043
#define    AND      044
#define    OR       045
#define    XOR      046
#define    NOR      047
#define    SLT      052
#define    SLTU     053


/* Sub-codes of opcode BCOND (defined by bits 20-16) */

#define    BCOND_MASK  0x001f0000
#define    BCOND_SHIFT 16

#define    BLTZ      0x00000000
#define    sBLTZ     (0x00000000 >> BCOND_SHIFT)
#define    BGEZ      0x00010000
#define    sBGEZ     (0x00010000 >> BCOND_SHIFT)
#define    BLTZAL    0x00100000
#define    sBLTZAL   (0x00100000 >> BCOND_SHIFT)
#define    BGEZAL    0x00110000
#define    sBGEZAL   (0x00110000 >> BCOND_SHIFT)


/* Sub-codes of opcode COP0 (defined by bits 5-0) */

#define    COP0_MASK 0x3f
#define    TLBR      01
#define    TLBWI     02
#define    TLBWR     06
#define    TLBP     010
#define    RFE      020


/* Not all sub-codes of opcode COP1-3 (defined by bits 22,21,16,25,24,23) */

#define    BCz_MASK 0x03610000
#define    Cz_MASK  0x03e00000
#define    BCF      0x01000000
#define    BCT      0x01010000
#define    MFC      0x00000000
#define    MTC      0x00800000
#define    CFC      0x00400000
#define    CTC      0x00c00000


/* FPU operations */

#define	   F_FMT_SHIFT 21
#define	   F_FMT_MASK (0x1f << F_FMT_SHIFT)
#define	   F_S	    (16 << F_FMT_SHIFT)
#define	   F_D	    (17 << F_FMT_SHIFT)
#define	   F_W	    (20 << F_FMT_SHIFT)

#define	   FT_SHIFT 16
#define	   FT_MASK  (0x1f << FT_SHIFT)

#define	   FS_SHIFT 11
#define	   FS_MASK  (0x1f << FS_SHIFT)

#define	   FD_SHIFT 6
#define	   FD_MASK  (0x1f << FD_SHIFT)

#define	   F_FUNC   0x3f
#define	   F_ADD    0
#define	   F_SUB    1
#define	   F_MUL    2
#define	   F_DIV    3
#define	   F_ABS    5
#define	   F_MOV    6
#define	   F_NEG    7
#define	   F_CS     32		/* cvt.s */
#define	   F_CD     33		/* cvt.d */
#define	   F_CW     36		/* cvt.w */


/* Masks for looking at register ops in MIPS instructions */

#define BASE_MASK 0x03e00000
#define BASE_SHIFT 21
#define RS_MASK BASE_MASK
#define RS_SHIFT BASE_SHIFT
#define RT_MASK 0x001f0000
#define RT_SHIFT 16
#define RD_MASK 0x0000f800
#define RD_SHIFT 11

#define IMM_MASK  0x0000ffff
#define LUI_SHIFT 16
#define J_MASK    0x3ffffff
#define J_SHIFT   2

#define SHAMT_MASK 0x000007c0
#define SHAMT_SHIFT 6

#define IMM(INST) (((INST) & IMM_MASK) & 0x8000 ? (INST) & IMM_MASK  | 0xffff0000 : (INST) & IMM_MASK)














