|
|
1.1 root 1: /*
2: * Cisco router simulation platform.
3: * Copyright (c) 2005,2006 Christophe Fillot ([email protected])
4: *
5: * PPC32 JIT compiler.
6: */
7:
8: #ifndef __PPC32_JIT_H__
9: #define __PPC32_JIT_H__
10:
11: #include "utils.h"
1.1.1.2 root 12: #include "sbox.h"
1.1 root 13:
14: /* Size of executable page area (in Mb) */
15: #ifndef __CYGWIN__
16: #define PPC_EXEC_AREA_SIZE 64
17: #else
18: #define PPC_EXEC_AREA_SIZE 16
19: #endif
20:
21: /* Buffer size for JIT code generation */
22: #define PPC_JIT_BUFSIZE 32768
23:
24: /* Maximum number of X86 chunks */
1.1.1.3 root 25: #define PPC_JIT_MAX_CHUNKS 64
1.1 root 26:
1.1.1.2 root 27: /* Size of hash for IA lookup */
28: #define PPC_JIT_IA_HASH_BITS 17
29: #define PPC_JIT_IA_HASH_MASK ((1 << PPC_JIT_IA_HASH_BITS) - 1)
30: #define PPC_JIT_IA_HASH_SIZE (1 << PPC_JIT_IA_HASH_BITS)
31:
32: /* Size of hash for physical lookup */
33: #define PPC_JIT_PHYS_HASH_BITS 16
34: #define PPC_JIT_PHYS_HASH_MASK ((1 << PPC_JIT_PHYS_HASH_BITS) - 1)
35: #define PPC_JIT_PHYS_HASH_SIZE (1 << PPC_JIT_PHYS_HASH_BITS)
36:
1.1.1.3 root 37: #define PPC_JIT_TARGET_BITMAP_INDEX(x) (((x) >> 7) & 0x1F)
38: #define PPC_JIT_TARGET_BITMAP_POS(x) (((x) >> 2) & 0x1F)
39:
1.1 root 40: /* Instruction jump patch */
41: struct ppc32_insn_patch {
1.1.1.3 root 42: struct ppc32_insn_patch *next;
1.1 root 43: u_char *jit_insn;
1.1.1.3 root 44: m_uint32_t ppc_ia;
1.1 root 45: };
46:
47: /* Instruction patch table */
48: #define PPC32_INSN_PATCH_TABLE_SIZE 32
49:
1.1.1.3 root 50: struct ppc32_jit_patch_table {
51: struct ppc32_jit_patch_table *next;
1.1 root 52: struct ppc32_insn_patch patches[PPC32_INSN_PATCH_TABLE_SIZE];
53: u_int cur_patch;
54: };
55:
56: /* PPC32 translated code block */
57: struct ppc32_jit_tcb {
58: m_uint32_t start_ia;
59: u_char **jit_insn_ptr;
60: m_uint64_t acc_count;
61: ppc_insn_t *ppc_code;
62: u_int ppc_trans_pos;
63: u_int jit_chunk_pos;
64: u_char *jit_ptr;
65: insn_exec_page_t *jit_buffer;
66: insn_exec_page_t *jit_chunks[PPC_JIT_MAX_CHUNKS];
67: struct ppc32_jit_patch_table *patch_table;
68: ppc32_jit_tcb_t *prev,*next;
1.1.1.2 root 69:
70: m_uint32_t phys_page;
71: m_uint32_t phys_hash;
72: ppc32_jit_tcb_t **phys_pprev,*phys_next;
1.1.1.3 root 73:
74: /* 1024 instructions per page, one bit per instruction */
75: m_uint32_t target_bitmap[32];
76: m_uint32_t target_undef_cnt;
1.1.1.2 root 77:
1.1 root 78: #if DEBUG_BLOCK_TIMESTAMP
79: m_uint64_t tm_first_use,tm_last_use;
80: #endif
81: };
82:
83: /* PPC instruction recognition */
84: struct ppc32_insn_tag {
85: int (*emit)(cpu_ppc_t *cpu,ppc32_jit_tcb_t *,ppc_insn_t);
86: m_uint32_t mask,value;
87: };
88:
1.1.1.3 root 89: /* Mark the specified IA as a target for further recompiling */
90: static inline void
91: ppc32_jit_tcb_set_target_bit(ppc32_jit_tcb_t *b,m_uint32_t ia)
92: {
93: int index,pos;
94:
95: index = PPC_JIT_TARGET_BITMAP_INDEX(ia);
96: pos = PPC_JIT_TARGET_BITMAP_POS(ia);
97:
98: b->target_bitmap[index] |= 1 << pos;
99: }
100:
101: /* Returns TRUE if the specified IA is in the target bitmap */
102: static inline int
103: ppc32_jit_tcb_get_target_bit(ppc32_jit_tcb_t *b,m_uint32_t ia)
104: {
105: int index,pos;
106:
107: index = PPC_JIT_TARGET_BITMAP_INDEX(ia);
108: pos = PPC_JIT_TARGET_BITMAP_POS(ia);
109:
110: return(b->target_bitmap[index] & (1 << pos));
111: }
112:
1.1 root 113: /* Get the JIT instruction pointer in a translated block */
114: static forced_inline
115: u_char *ppc32_jit_tcb_get_host_ptr(ppc32_jit_tcb_t *b,m_uint32_t vaddr)
116: {
117: m_uint32_t offset;
118:
1.1.1.2 root 119: offset = (vaddr & PPC32_MIN_PAGE_IMASK) >> 2;
1.1 root 120: return(b->jit_insn_ptr[offset]);
121: }
122:
1.1.1.2 root 123: /* Check if the specified address belongs to the specified block */
124: static forced_inline
125: int ppc32_jit_tcb_local_addr(ppc32_jit_tcb_t *block,m_uint32_t vaddr,
126: u_char **jit_addr)
127: {
128: if ((vaddr & PPC32_MIN_PAGE_MASK) == block->start_ia) {
129: *jit_addr = ppc32_jit_tcb_get_host_ptr(block,vaddr);
130: return(1);
131: }
132:
133: return(0);
134: }
135:
136: /* Check if PC register matches the compiled block virtual address */
137: static forced_inline
138: int ppc32_jit_tcb_match(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block)
139: {
140: m_uint32_t vpage;
141:
142: vpage = cpu->ia & ~PPC32_MIN_PAGE_IMASK;
143: return(block->start_ia == vpage);
144: }
145:
146: /* Compute the hash index for the specified IA value */
147: static forced_inline m_uint32_t ppc32_jit_get_ia_hash(m_uint32_t ia)
148: {
149: m_uint32_t page_hash;
150:
151: page_hash = sbox_u32(ia >> PPC32_MIN_PAGE_SHIFT);
152: return((page_hash ^ (page_hash >> 14)) & PPC_JIT_IA_HASH_MASK);
153: }
154:
155: /* Compute the hash index for the specified physical page */
156: static forced_inline m_uint32_t ppc32_jit_get_phys_hash(m_uint32_t phys_page)
157: {
158: m_uint32_t page_hash;
159:
160: page_hash = sbox_u32(phys_page);
161: return((page_hash ^ (page_hash >> 12)) & PPC_JIT_PHYS_HASH_MASK);
162: }
163:
164: /* Find the JIT block matching a physical page */
165: static inline ppc32_jit_tcb_t *
166: ppc32_jit_find_by_phys_page(cpu_ppc_t *cpu,m_uint32_t phys_page)
167: {
168: m_uint32_t page_hash = ppc32_jit_get_phys_hash(phys_page);
169: ppc32_jit_tcb_t *block;
170:
171: for(block=cpu->exec_phys_map[page_hash];block;block=block->phys_next)
172: if (block->phys_page == phys_page)
173: return block;
174:
175: return NULL;
176: }
177:
1.1.1.3 root 178: /* ======================================================================== */
179: /* JIT emit operations (generic). */
180: /* ======================================================================== */
181:
182: /* Indicate registers modified by ppc32_update_cr() functions */
183: extern void ppc32_update_cr_set_altered_hreg(cpu_ppc_t *cpu);
184:
185: /* Set opcode */
186: static inline void ppc32_op_set(cpu_ppc_t *cpu,jit_op_t *op)
187: {
188: cpu_gen_t *c = cpu->gen;
189: *c->jit_op_current = op;
190: c->jit_op_current = &op->next;
191: }
192:
193: /* EMIT_BASIC_OPCODE */
194: static inline void ppc32_op_emit_basic_opcode(cpu_ppc_t *cpu,u_int opcode)
195: {
196: jit_op_t *op = jit_op_get(cpu->gen,0,opcode);
197: ppc32_op_set(cpu,op);
198: }
199:
200: /* Trash the specified host register */
201: static inline void ppc32_op_emit_alter_host_reg(cpu_ppc_t *cpu,int host_reg)
202: {
203: jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_ALTER_HOST_REG);
204: op->param[0] = host_reg;
205: ppc32_op_set(cpu,op);
206: }
207:
208: /* EMIT_INSN_OUTPUT */
209: static inline jit_op_t *
210: ppc32_op_emit_insn_output(cpu_ppc_t *cpu,u_int size_index,char *insn_name)
211: {
212: jit_op_t *op = jit_op_get(cpu->gen,size_index,JIT_OP_INSN_OUTPUT);
213: op->arg_ptr = NULL;
214: op->insn_name = insn_name;
215: ppc32_op_set(cpu,op);
216: return op;
217: }
218:
219: /* EMIT_LOAD_GPR */
220: static inline
221: void ppc32_op_emit_load_gpr(cpu_ppc_t *cpu,int host_reg,int ppc_reg)
222: {
223: jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_LOAD_GPR);
224: op->param[0] = host_reg;
225: op->param[1] = ppc_reg;
226: op->param[2] = host_reg;
227: ppc32_op_set(cpu,op);
228: }
229:
230: /* EMIT_STORE_GPR */
231: static inline
232: void ppc32_op_emit_store_gpr(cpu_ppc_t *cpu,int ppc_reg,int host_reg)
233: {
234: jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_STORE_GPR);
235: op->param[0] = host_reg;
236: op->param[1] = ppc_reg;
237: op->param[2] = host_reg;
238: ppc32_op_set(cpu,op);
239: }
240:
241: /* EMIT_UPDATE_FLAGS */
242: static inline
243: void ppc32_op_emit_update_flags(cpu_ppc_t *cpu,int field,int is_signed)
244: {
245: jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_UPDATE_FLAGS);
246:
247: op->param[0] = field;
248: op->param[1] = is_signed;
249:
250: ppc32_op_set(cpu,op);
251: ppc32_update_cr_set_altered_hreg(cpu);
252: }
253:
254: /* EMIT_REQUIRE_FLAGS */
255: static inline void ppc32_op_emit_require_flags(cpu_ppc_t *cpu,int field)
256: {
257: jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_REQUIRE_FLAGS);
258: op->param[0] = field;
259: ppc32_op_set(cpu,op);
260: }
261:
262: /* EMIT_BRANCH_TARGET */
263: static inline void ppc32_op_emit_branch_target(cpu_ppc_t *cpu,
264: ppc32_jit_tcb_t *b,
265: m_uint32_t ia)
266: {
267: cpu_gen_t *c = cpu->gen;
268: jit_op_t *op = jit_op_get(c,0,JIT_OP_BRANCH_TARGET);
269: u_int pos;
270:
271: if ((ia & PPC32_MIN_PAGE_MASK) == b->start_ia) {
272: pos = (ia & PPC32_MIN_PAGE_IMASK) >> 2;
273:
274: /* Insert in head */
275: op->next = c->jit_op_array[pos];
276: c->jit_op_array[pos] = op;
277: }
278: }
279:
280: /* EMIT_SET_HOST_REG_IMM32 */
281: static inline void
282: ppc32_op_emit_set_host_reg_imm32(cpu_ppc_t *cpu,int reg,m_uint32_t val)
283: {
284: jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_SET_HOST_REG_IMM32);
285: op->param[0] = reg;
286: op->param[1] = val;
287: ppc32_op_set(cpu,op);
288: }
289:
290: /* ======================================================================== */
291: /* JIT operations with implementations specific to target CPU */
292: void ppc32_op_insn_output(ppc32_jit_tcb_t *b,jit_op_t *op);
293: void ppc32_op_load_gpr(ppc32_jit_tcb_t *b,jit_op_t *op);
294: void ppc32_op_store_gpr(ppc32_jit_tcb_t *b,jit_op_t *op);
295: void ppc32_op_update_flags(ppc32_jit_tcb_t *b,jit_op_t *op);
296: void ppc32_op_move_host_reg(ppc32_jit_tcb_t *b,jit_op_t *op);
297: void ppc32_op_set_host_reg_imm32(ppc32_jit_tcb_t *b,jit_op_t *op);
298:
299: /* Set the Instruction Address (IA) register */
300: void ppc32_set_ia(u_char **ptr,m_uint32_t new_ia);
301:
302: /* Jump to the next page */
303: void ppc32_set_page_jump(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b);
304:
305: /* Increment the number of executed instructions (performance debugging) */
1.1.1.4 ! root 306: void ppc32_inc_perf_counter(cpu_ppc_t *cpu);
1.1.1.3 root 307:
308: /* ======================================================================== */
309:
1.1.1.2 root 310: /* Virtual Breakpoint */
1.1.1.3 root 311: void ppc32_emit_breakpoint(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b);
1.1.1.2 root 312:
1.1 root 313: /* Initialize instruction lookup table */
314: void ppc32_jit_create_ilt(void);
315:
316: /* Initialize the JIT structure */
317: int ppc32_jit_init(cpu_ppc_t *cpu);
318:
319: /* Flush the JIT */
320: u_int ppc32_jit_flush(cpu_ppc_t *cpu,u_int threshold);
321:
322: /* Shutdown the JIT */
323: void ppc32_jit_shutdown(cpu_ppc_t *cpu);
324:
325: /* Fetch a PowerPC instruction and emit corresponding translated code */
326: struct ppc32_insn_tag *ppc32_jit_fetch_and_emit(cpu_ppc_t *cpu,
327: ppc32_jit_tcb_t *block);
328:
329: /* Record a patch to apply in a compiled block */
1.1.1.3 root 330: int ppc32_jit_tcb_record_patch(ppc32_jit_tcb_t *block,jit_op_t *iop,
331: u_char *jit_ptr,m_uint32_t vaddr);
1.1 root 332:
333: /* Free an instruction block */
334: void ppc32_jit_tcb_free(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block,
335: int list_removal);
336:
337: /* Check if the specified address belongs to the specified block */
338: int ppc32_jit_tcb_local_addr(ppc32_jit_tcb_t *block,m_uint32_t vaddr,
339: u_char **jit_addr);
340:
1.1.1.3 root 341: /* Recompile a page */
342: int ppc32_jit_tcb_recompile(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block);
343:
1.1 root 344: /* Execute compiled PowerPC code */
345: void *ppc32_jit_run_cpu(cpu_gen_t *gen);
346:
1.1.1.3 root 347: /* Start register allocation sequence */
348: void ppc32_jit_start_hreg_seq(cpu_ppc_t *cpu,char *insn);
349:
350: /* Close register allocation sequence */
351: void ppc32_jit_close_hreg_seq(cpu_ppc_t *cpu);
352:
353: /* Insert a reg map as head of list (as MRU element) */
354: void ppc32_jit_insert_hreg_mru(cpu_ppc_t *cpu,struct hreg_map *map);
355:
356: /* Allocate an host register */
357: int ppc32_jit_alloc_hreg(cpu_ppc_t *cpu,int ppc_reg);
358:
359: /* Force allocation of an host register */
360: int ppc32_jit_alloc_hreg_forced(cpu_ppc_t *cpu,int hreg);
361:
362: /* Initialize register mapping */
363: void ppc32_jit_init_hreg_mapping(cpu_ppc_t *cpu);
364:
1.1 root 365: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.