|
|
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) */
! 306: void ppc32_inc_perf_counter(ppc32_jit_tcb_t *b);
! 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.