1 |
/* |
2 |
* Cisco 7200 (Predator) simulation platform. |
3 |
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
4 |
*/ |
5 |
|
6 |
#ifndef __DYNAMIPS_H__ |
7 |
#define __DYNAMIPS_H__ |
8 |
|
9 |
#include <libelf.h> |
10 |
|
11 |
#include "utils.h" |
12 |
|
13 |
/* Debugging flags */ |
14 |
#define DEBUG_BLOCK_SCAN 0 |
15 |
#define DEBUG_BLOCK_COMPILE 0 |
16 |
#define DEBUG_BLOCK_PATCH 0 |
17 |
#define DEBUG_BLOCK_CHUNK 0 |
18 |
#define DEBUG_BLOCK_TIMESTAMP 0 /* block timestamping (little overhead) */ |
19 |
#define DEBUG_SYM_TREE 0 /* use symbol tree (slow) */ |
20 |
#define DEBUG_MTS_MAP_DEV 0 |
21 |
#define DEBUG_MTS_MAP_VIRT 0 |
22 |
#define DEBUG_MTS_ACC_U 1 /* undefined memory */ |
23 |
#define DEBUG_MTS_ACC_T 1 /* tlb exception */ |
24 |
#define DEBUG_MTS_ACC_AE 1 /* address error exception */ |
25 |
#define DEBUG_MTS_DEV 0 /* debugging for device access */ |
26 |
#define DEBUG_MTS_STATS 1 /* MTS64 cache performance */ |
27 |
#define DEBUG_INSN_PERF_CNT 0 /* Instruction performance counter */ |
28 |
#define DEBUG_BLOCK_PERF_CNT 0 /* Block performance counter */ |
29 |
#define DEBUG_TLB_ACTIVITY 0 |
30 |
#define DEBUG_SYSCALL 0 |
31 |
#define DEBUG_CACHE 0 |
32 |
#define DEBUG_JR0 0 /* Debug register jumps to 0 */ |
33 |
|
34 |
/* Feature flags */ |
35 |
#define MEMLOG_ENABLE 0 /* Memlogger (MTS ASM must be disabled) */ |
36 |
#define BREAKPOINT_ENABLE 0 /* Virtual Breakpoints */ |
37 |
#define NJM_STATS_ENABLE 1 /* Non-JIT mode stats (little overhead) */ |
38 |
#define MTSASM_ENABLE 1 /* Optimized-assembly MTS */ |
39 |
|
40 |
/* Size of executable page area (in Mb) */ |
41 |
#ifndef __CYGWIN__ |
42 |
#define MIPS_EXEC_AREA_SIZE 64 |
43 |
#else |
44 |
#define MIPS_EXEC_AREA_SIZE 16 |
45 |
#endif |
46 |
|
47 |
/* Buffer size for JIT code generation */ |
48 |
#define MIPS_JIT_BUFSIZE 32768 |
49 |
|
50 |
/* Maximum number of X86 chunks */ |
51 |
#define INSN_MAX_CHUNKS 32 |
52 |
|
53 |
/* Translated block function pointer */ |
54 |
typedef m_uint64_t (*insn_tblock_fptr)(void); |
55 |
|
56 |
/* Instruction jump patch */ |
57 |
struct insn_patch { |
58 |
u_char *jit_insn; |
59 |
m_uint64_t mips_pc; |
60 |
}; |
61 |
|
62 |
/* Instruction patch table */ |
63 |
#define INSN_PATCH_TABLE_SIZE 32 |
64 |
|
65 |
struct insn_patch_table { |
66 |
struct insn_patch patches[INSN_PATCH_TABLE_SIZE]; |
67 |
u_int cur_patch; |
68 |
struct insn_patch_table *next; |
69 |
}; |
70 |
|
71 |
/* Exec page */ |
72 |
struct insn_exec_page { |
73 |
u_char *ptr; |
74 |
insn_exec_page_t *next; |
75 |
}; |
76 |
|
77 |
/* Instruction block */ |
78 |
struct insn_block { |
79 |
m_uint64_t start_pc; |
80 |
u_char **jit_insn_ptr; |
81 |
m_uint64_t acc_count; |
82 |
m_uint32_t phys_page; |
83 |
mips_insn_t *mips_code; |
84 |
u_int mips_trans_pos; |
85 |
u_int jit_chunk_pos; |
86 |
u_char *jit_ptr; |
87 |
insn_exec_page_t *jit_buffer; |
88 |
insn_exec_page_t *jit_chunks[INSN_MAX_CHUNKS]; |
89 |
struct insn_patch_table *patch_table; |
90 |
insn_block_t *prev,*next; |
91 |
#if DEBUG_BLOCK_TIMESTAMP |
92 |
m_uint64_t tm_first_use,tm_last_use; |
93 |
#endif |
94 |
}; |
95 |
|
96 |
/* MIPS instruction recognition */ |
97 |
struct insn_tag { |
98 |
int (*emit)(cpu_mips_t *cpu,struct insn_block *,mips_insn_t); |
99 |
m_uint32_t mask,value; |
100 |
int delay_slot; |
101 |
}; |
102 |
|
103 |
/* MIPS jump instruction (for block scan) */ |
104 |
struct insn_jump { |
105 |
char *name; |
106 |
m_uint32_t mask,value; |
107 |
int offset_bits; |
108 |
int relative; |
109 |
}; |
110 |
|
111 |
/* Symbol */ |
112 |
struct symbol { |
113 |
m_uint64_t addr; |
114 |
char name[0]; |
115 |
}; |
116 |
|
117 |
/* ROM identification tag */ |
118 |
#define ROM_ID 0x1e94b3df |
119 |
|
120 |
/* Global log file */ |
121 |
extern FILE *log_file; |
122 |
|
123 |
/* Software version */ |
124 |
extern const char *sw_version; |
125 |
|
126 |
/* Get the JIT instruction pointer in a compiled block */ |
127 |
static forced_inline |
128 |
u_char *insn_block_get_jit_ptr(struct insn_block *block,m_uint64_t vaddr) |
129 |
{ |
130 |
m_uint64_t offset; |
131 |
|
132 |
offset = (vaddr - block->start_pc) >> 2; |
133 |
return(block->jit_insn_ptr[offset]); |
134 |
} |
135 |
|
136 |
/* Check if there are pending IRQ */ |
137 |
extern void mips64_check_pending_irq(struct insn_block *b); |
138 |
|
139 |
/* Initialize instruction lookup table */ |
140 |
void mips64_jit_create_ilt(void); |
141 |
|
142 |
/* Initialize the JIT structure */ |
143 |
int mips64_jit_init(cpu_mips_t *cpu); |
144 |
|
145 |
/* Flush the JIT */ |
146 |
u_int mips64_jit_flush(cpu_mips_t *cpu,u_int threshold); |
147 |
|
148 |
/* Shutdown the JIT */ |
149 |
void mips64_jit_shutdown(cpu_mips_t *cpu); |
150 |
|
151 |
/* Find the JIT code emitter for the specified MIPS instruction */ |
152 |
struct insn_tag *insn_tag_find(mips_insn_t ins); |
153 |
|
154 |
/* Check if the specified MIPS instruction is a jump */ |
155 |
struct insn_jump *insn_jump_find(mips_insn_t ins); |
156 |
|
157 |
/* Fetch a MIPS instruction and emit corresponding x86 translated code */ |
158 |
struct insn_tag *insn_fetch_and_emit(cpu_mips_t *cpu,struct insn_block *block, |
159 |
int delay_slot); |
160 |
|
161 |
/* Record a patch to apply in a compiled block */ |
162 |
int insn_block_record_patch(struct insn_block *block,u_char *x86_ptr, |
163 |
m_uint64_t vaddr); |
164 |
|
165 |
/* Free an instruction block */ |
166 |
void insn_block_free(cpu_mips_t *cpu,insn_block_t *block,int list_removal); |
167 |
|
168 |
/* Tree comparison function */ |
169 |
int insn_block_cmp(m_uint64_t *vaddr,struct insn_block *b); |
170 |
|
171 |
/* Check if the specified address belongs to the specified block */ |
172 |
int insn_block_local_addr(struct insn_block *block,m_uint64_t vaddr, |
173 |
u_char **x86_addr); |
174 |
|
175 |
/* Execute a compiled MIPS code */ |
176 |
void *insn_block_execute(cpu_mips_t *cpu); |
177 |
|
178 |
/* Dump the instruction block tree */ |
179 |
void insn_block_dump_tree(cpu_mips_t *cpu); |
180 |
|
181 |
/* Delete all objects */ |
182 |
void dynamips_reset(void); |
183 |
|
184 |
#endif |