/* radare - Apache 2.0 - Copyright 2013 - Adam Pridgen <dso@rice.edu || adam.pridgen@thecoverofnight.com> */
#include <r_anal.h>

#ifndef R2_JAVA_OPS_H
#define R2_JAVA_OPS_H

enum {
	R_ANAL_JAVA_ILL_OP = -1,   /* illegal instruction // trap */
	R_ANAL_JAVA_NULL_OP = 0,
	R_ANAL_JAVA_NOP = 1, /* does nothing */
	R_ANAL_JAVA_STORE_OP = 1 << 20,  // Load or Store memory operation
	R_ANAL_JAVA_LOAD_OP = 1 << 21,  // Load or Store memory operation
	R_ANAL_JAVA_REG_OP = 1 << 22,  // register operation
	R_ANAL_JAVA_OBJ_OP = 1 << 23,  // operates on an object
	R_ANAL_JAVA_STACK_OP = 1 << 25,  // stack based operation
	R_ANAL_JAVA_BIN_OP = 1 << 26,  // binary operation
	R_ANAL_JAVA_CODE_OP = 1 << 27,  // operates on code
	R_ANAL_JAVA_DATA_OP = 1 << 28,  // operates on data
	R_ANAL_JAVA_UNK_OP = 1 << 29,  /* unknown opcode type */
	R_ANAL_JAVA_REP_OP = 1 << 30,  /* repeats next instruction N times */
	R_ANAL_JAVA_COND_OP = 1U << 31,
};

enum {
	R_ANAL_JAVA_TYPE_REF_NULL = 0,
	R_ANAL_JAVA_TYPE_REF_UNK = 1 << 1,
	R_ANAL_JAVA_TYPE_REF = 1 << 2,
	R_ANAL_JAVA_TYPE_SIGNED	= 1 << 3,
	R_ANAL_JAVA_TYPE_PRIM = 1 << 4,
	R_ANAL_JAVA_TYPE_CONST = 1 << 5,
	R_ANAL_JAVA_TYPE_STATIC	= 1 << 6,
	R_ANAL_JAVA_TYPE_VOLATILE = 1 << 7,
	R_ANAL_JAVA_TYPE_PUBLIC	= 1 << 8,

	R_ANAL_JAVA_TYPE_BOOL   = 1 << 10,
	R_ANAL_JAVA_TYPE_BYTE   = 1 << 11,
	R_ANAL_JAVA_TYPE_SHORT  = 1 << 12,
	R_ANAL_JAVA_TYPE_INT32  = 1 << 13,
	R_ANAL_JAVA_TYPE_INTEGER = 1 << 13,
	R_ANAL_JAVA_TYPE_INT64  = 1 << 14,
	R_ANAL_JAVA_TYPE_LONG   = 1 << 14,
	R_ANAL_JAVA_TYPE_FLOAT  = 1 << 15,
	R_ANAL_JAVA_TYPE_DOUBLE = 1 << 16,
	R_ANAL_JAVA_TYPE_STRING = 1 << 17,
	R_ANAL_JAVA_TYPE_CHAR   = 1 << 18,
	R_ANAL_JAVA_TYPE_VOID   = 1 << 19,
};

// code ops
enum {
	R_ANAL_JAVA_CODEOP_JMP	= 1 << 1  | R_ANAL_JAVA_CODE_OP,/* mandatory jump */
	R_ANAL_JAVA_CODEOP_CALL   = 1 << 2  | R_ANAL_JAVA_CODE_OP,/* call to subroutine (branch+link) */
	R_ANAL_JAVA_CODEOP_RET	= 1 << 3  | R_ANAL_JAVA_CODE_OP,/* returns from subrutine */
	R_ANAL_JAVA_CODEOP_TRAP   = 1 << 4  | R_ANAL_JAVA_CODE_OP,/* it's a trap! */
	R_ANAL_JAVA_CODEOP_SWI	= 1 << 5  | R_ANAL_JAVA_CODE_OP,/* syscall  software interrupt */
	R_ANAL_JAVA_CODEOP_IO	 = 1 << 6  | R_ANAL_JAVA_CODE_OP,
	R_ANAL_JAVA_CODEOP_LEAVE  = 1 << 7  | R_ANAL_JAVA_CODE_OP,
	R_ANAL_JAVA_CODEOP_SWITCH = 1 << 8  | R_ANAL_JAVA_CODE_OP,
	R_ANAL_JAVA_CODEOP_CJMP   = R_ANAL_JAVA_COND_OP | R_ANAL_JAVA_CODE_OP | R_ANAL_JAVA_CODEOP_JMP,
	R_ANAL_JAVA_CODEOP_EOB	= R_ANAL_JAVA_CODEOP_JMP | R_ANAL_JAVA_CODEOP_RET | R_ANAL_JAVA_CODEOP_LEAVE | R_ANAL_JAVA_CODEOP_SWITCH,
};

enum {
	// call return types
	R_ANAL_JAVA_RET_TYPE_REF_NULL = 1 << 10,
	R_ANAL_JAVA_RET_TYPE_REF = 1 << 11 ,
	R_ANAL_JAVA_RET_TYPE_PRIM = 1 << 12 ,
	R_ANAL_JAVA_RET_TYPE_CONST = 1 << 13,
	R_ANAL_JAVA_RET_TYPE_STATIC = 1 << 14,
};

// jmp conditionals
enum {
	// TODO these should be mapped to some sort of
	// flags register
	R_ANAL_JAVA_COND_EQ  = 1 << 11,
	R_ANAL_JAVA_COND_NE  = 1 << 12,
	R_ANAL_JAVA_COND_GE  = 1 << 13,
	R_ANAL_JAVA_COND_GT  = 1 << 14,
	R_ANAL_JAVA_COND_LE  = 1 << 15,
	R_ANAL_JAVA_COND_LT  = 1 << 16,
	R_ANAL_JAVA_COND_AL  = 1 << 17,
	R_ANAL_JAVA_COND_NV  = 1 << 18,
	R_ANAL_JAVA_COND_NULL  = 1 << 19,
};

// bin ops
enum {
	R_ANAL_JAVA_BINOP_NEG = 0 | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_XCHG = 1 << 1 | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_CMP  = 1 << 2  | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_ADD  = 1 << 3  | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_SUB  = 1 << 4  | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_MUL  = 1 << 6  | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_DIV  = 1 << 7  | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_SHR  = 1 << 8  | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_SHL  = 1 << 9  | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_SAL  = 1 << 10 | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_SAR  = 1 << 11 | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_OR   = 1 << 12 | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_AND  = 1 << 14 | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_XOR  = 1 << 15 | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_NOT  = 1 << 16 | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_MOD  = 1 << 17 | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_ROR  = 1 << 18 | R_ANAL_JAVA_BIN_OP,
	R_ANAL_JAVA_BINOP_ROL  = 1 << 19 | R_ANAL_JAVA_BIN_OP,
};

// Object ops
enum {
	R_ANAL_JAVA_OBJOP_CAST  = 1 << 0 | R_ANAL_JAVA_OBJ_OP,
	R_ANAL_JAVA_OBJOP_CHECK = 1 << 1 | R_ANAL_JAVA_OBJ_OP,
	R_ANAL_JAVA_OBJOP_NEW   = 1 << 2 | R_ANAL_JAVA_OBJ_OP,
	R_ANAL_JAVA_OBJOP_DEL   = 1 << 3 | R_ANAL_JAVA_OBJ_OP,
	R_ANAL_JAVA_OBJOP_SIZE   = 1 << 4 | R_ANAL_JAVA_OBJ_OP,
};


// Memory or Data Operations
// Locations of item loaded (base of indirect)
enum {
	R_ANAL_JAVA_LDST_FROM_REF   =  1 << 1,
	R_ANAL_JAVA_LDST_FROM_MEM   =  1 << 1,

	R_ANAL_JAVA_LDST_FROM_REG   =  1 << 2,
	R_ANAL_JAVA_LDST_FROM_STACK =  1 << 3,
	R_ANAL_JAVA_LDST_FROM_CONST =  1 << 4,
	R_ANAL_JAVA_LDST_FROM_VAR   =  1 << 5,

	// If indirect load, where are we getting the indirection,
	R_ANAL_JAVA_LDST_INDIRECT_REF  = 1 << 6,
	R_ANAL_JAVA_LDST_INDIRECT_MEM  = 1 << 6,

	R_ANAL_JAVA_LDST_INDIRECT_REG   =  1 << 7,
	R_ANAL_JAVA_LDST_INDIRECT_STACK =  1 << 8,
	R_ANAL_JAVA_LDST_INDIRECT_IDX   =  1 << 9,
	R_ANAL_JAVA_LDST_INDIRECT_VAR   =  1 << 10,

	// Location to put the item,
	R_ANAL_JAVA_LDST_TO_REF  = 1 << 11,
	R_ANAL_JAVA_LDST_TO_MEM  = 1 << 11,

	R_ANAL_JAVA_LDST_TO_REG = 1 << 12,
	R_ANAL_JAVA_LDST_TO_STACK =  1 << 13,
	R_ANAL_JAVA_LDST_TO_VAR =    1 << 14,

	// Stack, Memory, Register, Bss, Data ,
	R_ANAL_JAVA_LDST_OP_PUSH  = 1 << 15  ,
	R_ANAL_JAVA_LDST_OP_POP   = 1 << 16,
	R_ANAL_JAVA_LDST_OP_MOV   = 1 << 17 ,
	R_ANAL_JAVA_LDST_OP_EFF_ADDR   = 1 << 18,
};

enum {

	R_ANAL_JAVA_LDST_LOAD_FROM_CONST_REF_TO_STACK = R_ANAL_JAVA_LDST_OP_PUSH |\
		R_ANAL_JAVA_LOAD_OP |\
		R_ANAL_JAVA_LDST_FROM_REF |\
		R_ANAL_JAVA_LDST_FROM_CONST |\
		R_ANAL_JAVA_LDST_TO_STACK |\
		R_ANAL_JAVA_TYPE_REF,

	R_ANAL_JAVA_LDST_LOAD_FROM_CONST_TO_STACK = R_ANAL_JAVA_LDST_OP_PUSH |\
		R_ANAL_JAVA_LOAD_OP |\
		R_ANAL_JAVA_LDST_FROM_CONST |\
		R_ANAL_JAVA_LDST_TO_STACK,

	R_ANAL_JAVA_LDST_LOAD_FROM_CONST_INDIRECT_TO_STACK = R_ANAL_JAVA_LDST_OP_PUSH |\
		R_ANAL_JAVA_LOAD_OP |\
		R_ANAL_JAVA_LDST_FROM_CONST |\
		R_ANAL_JAVA_LDST_INDIRECT_IDX |\
		R_ANAL_JAVA_LDST_TO_STACK,

	R_ANAL_JAVA_LDST_LOAD_FROM_VAR_INDIRECT_TO_STACK = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_LOAD_OP |\
		 R_ANAL_JAVA_LDST_FROM_VAR |\
		 R_ANAL_JAVA_LDST_INDIRECT_IDX |\
		 R_ANAL_JAVA_LDST_TO_STACK,

	R_ANAL_JAVA_LDST_LOAD_FROM_VAR_INDIRECT_TO_STACK_REF = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_LOAD_OP |\
		 R_ANAL_JAVA_LDST_FROM_VAR |\
		 R_ANAL_JAVA_LDST_INDIRECT_IDX |\
		 R_ANAL_JAVA_LDST_TO_STACK,

	R_ANAL_JAVA_LDST_LOAD_FROM_VAR_TO_STACK = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_LOAD_OP |\
		 R_ANAL_JAVA_LDST_FROM_VAR |\
		 R_ANAL_JAVA_LDST_INDIRECT_IDX |\
		 R_ANAL_JAVA_LDST_TO_STACK,

	R_ANAL_JAVA_LDST_LOAD_FROM_VAR_TO_STACK_REF = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_LOAD_OP |\
		 R_ANAL_JAVA_LDST_FROM_VAR |\
		 R_ANAL_JAVA_LDST_INDIRECT_IDX |\
		 R_ANAL_JAVA_LDST_TO_STACK,

	R_ANAL_JAVA_LDST_LOAD_FROM_REF_INDIRECT_TO_STACK = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_LOAD_OP |\
		 R_ANAL_JAVA_LDST_FROM_REF |\
		 R_ANAL_JAVA_LDST_INDIRECT_IDX |\
		 R_ANAL_JAVA_LDST_TO_STACK,

	R_ANAL_JAVA_LDST_LOAD_FROM_REF_INDIRECT_TO_STACK_REF = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_LOAD_OP |\
		 R_ANAL_JAVA_LDST_FROM_REF |\
		 R_ANAL_JAVA_LDST_INDIRECT_IDX |\
		 R_ANAL_JAVA_LDST_TO_STACK,

	R_ANAL_JAVA_LDST_STORE_FROM_STACK_INDIRECT_TO_VAR = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_STORE_OP |\
		 R_ANAL_JAVA_LDST_FROM_STACK |\
		 R_ANAL_JAVA_LDST_INDIRECT_IDX |\
		 R_ANAL_JAVA_LDST_TO_VAR,

	R_ANAL_JAVA_LDST_STORE_FROM_STACK_INDIRECT_TO_VAR_REF = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_STORE_OP |\
		 R_ANAL_JAVA_LDST_FROM_STACK |\
		 R_ANAL_JAVA_LDST_INDIRECT_IDX |\
		 R_ANAL_JAVA_LDST_TO_VAR,

	R_ANAL_JAVA_LDST_STORE_FROM_STACK_TO_VAR = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_STORE_OP |\
		 R_ANAL_JAVA_LDST_FROM_STACK |\
		 R_ANAL_JAVA_LDST_TO_VAR,

	R_ANAL_JAVA_LDST_STORE_FROM_STACK_TO_VAR_REF = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_STORE_OP |\
		 R_ANAL_JAVA_LDST_FROM_STACK |\
		 R_ANAL_JAVA_LDST_TO_VAR,

	R_ANAL_JAVA_LDST_STORE_FROM_STACK_INDIRECT_TO_REF = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_STORE_OP |\
		 R_ANAL_JAVA_LDST_FROM_STACK |\
		 R_ANAL_JAVA_LDST_TO_REF,

	R_ANAL_JAVA_LDST_STORE_FROM_STACK_INDIRECT_TO_REF_REF = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_STORE_OP |\
		 R_ANAL_JAVA_LDST_FROM_STACK |\
		 R_ANAL_JAVA_LDST_TO_REF,

	R_ANAL_JAVA_LDST_LOAD_FROM_REF_TO_STACK = R_ANAL_JAVA_LDST_OP_PUSH |\
		 R_ANAL_JAVA_LOAD_OP |\
		 R_ANAL_JAVA_LDST_FROM_REF |\
		 R_ANAL_JAVA_LDST_TO_STACK |\
		 R_ANAL_JAVA_TYPE_PRIM,

	R_ANAL_JAVA_LDST_LOAD_FROM_PRIM_VAR_TO_STACK = R_ANAL_JAVA_LDST_OP_PUSH |\
		   R_ANAL_JAVA_LOAD_OP |\
		   R_ANAL_JAVA_LDST_FROM_VAR |\
		   R_ANAL_JAVA_TYPE_PRIM,

	R_ANAL_JAVA_LDST_LOAD_GET_STATIC = R_ANAL_JAVA_LDST_OP_PUSH |\
		R_ANAL_JAVA_LOAD_OP |\
		R_ANAL_JAVA_LDST_FROM_REF |\
		R_ANAL_JAVA_LDST_TO_STACK |\
		R_ANAL_JAVA_TYPE_REF,

	R_ANAL_JAVA_LDST_STORE_PUT_STATIC = R_ANAL_JAVA_LDST_OP_POP |\
		R_ANAL_JAVA_STORE_OP |\
		R_ANAL_JAVA_LDST_FROM_STACK |\
		R_ANAL_JAVA_LDST_TO_REF |\
		R_ANAL_JAVA_TYPE_REF,

	R_ANAL_JAVA_LDST_LOAD_GET_FIELD = R_ANAL_JAVA_LDST_OP_PUSH |\
		R_ANAL_JAVA_LOAD_OP |\
		R_ANAL_JAVA_LDST_FROM_REF |\
		R_ANAL_JAVA_LDST_TO_STACK |\
		R_ANAL_JAVA_TYPE_REF,

	R_ANAL_JAVA_LDST_STORE_PUT_FIELD = R_ANAL_JAVA_LDST_OP_POP |\
		R_ANAL_JAVA_STORE_OP |\
		R_ANAL_JAVA_LDST_FROM_STACK |\
		R_ANAL_JAVA_LDST_TO_REF |\
		R_ANAL_JAVA_TYPE_REF,
};

#endif
