File: mips64_jit.h

package info (click to toggle)
dynamips 0.2.7-0.2.8RC2-2
  • links: PTS
  • area: non-free
  • in suites: lenny
  • size: 3,840 kB
  • ctags: 9,893
  • sloc: ansic: 69,846; makefile: 239; sh: 124; perl: 20
file content (180 lines) | stat: -rw-r--r-- 5,010 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 * Cisco router simulation platform.
 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
 *
 * MIPS64 JIT compiler.
 */

#ifndef __MIPS64_JIT_H__
#define __MIPS64_JIT_H__

#include "utils.h"
#include "sbox.h"

/* Size of executable page area (in Mb) */
#ifndef __CYGWIN__
#define MIPS_EXEC_AREA_SIZE  64
#else
#define MIPS_EXEC_AREA_SIZE  16
#endif

/* Buffer size for JIT code generation */
#define MIPS_JIT_BUFSIZE     32768

/* Maximum number of X86 chunks */
#define MIPS_JIT_MAX_CHUNKS  32

/* Size of hash for PC lookup */
#define MIPS_JIT_PC_HASH_BITS   16
#define MIPS_JIT_PC_HASH_MASK   ((1 << MIPS_JIT_PC_HASH_BITS) - 1)
#define MIPS_JIT_PC_HASH_SIZE   (1 << MIPS_JIT_PC_HASH_BITS)

/* Instruction jump patch */
struct mips64_insn_patch {
   u_char *jit_insn;
   m_uint64_t mips_pc;
};

/* Instruction patch table */
#define MIPS64_INSN_PATCH_TABLE_SIZE  32

struct mips64_jit_patch_table {
   struct mips64_insn_patch patches[MIPS64_INSN_PATCH_TABLE_SIZE];
   u_int cur_patch;
   struct mips64_jit_patch_table *next;
};

/* MIPS64 translated code block */
struct mips64_jit_tcb {
   m_uint64_t start_pc;
   u_char **jit_insn_ptr;
   m_uint64_t acc_count;
   mips_insn_t *mips_code;
   u_int mips_trans_pos;
   u_int jit_chunk_pos;
   u_char *jit_ptr;
   insn_exec_page_t *jit_buffer;
   insn_exec_page_t *jit_chunks[MIPS_JIT_MAX_CHUNKS];
   struct mips64_jit_patch_table *patch_table;
   mips64_jit_tcb_t *prev,*next;
#if DEBUG_BLOCK_TIMESTAMP
   m_uint64_t tm_first_use,tm_last_use;
#endif
};

/* MIPS instruction recognition */
struct mips64_insn_tag {
   int (*emit)(cpu_mips_t *cpu,mips64_jit_tcb_t *,mips_insn_t);
   m_uint32_t mask,value;
   int delay_slot;
};

/* MIPS jump instruction (for block scan) */
struct mips64_insn_jump {
   char *name;
   m_uint32_t mask,value;
   int offset_bits;
   int relative;
};

/* Get the JIT instruction pointer in a translated block */
static forced_inline 
u_char *mips64_jit_tcb_get_host_ptr(mips64_jit_tcb_t *b,m_uint64_t vaddr)
{
   m_uint32_t offset;

   offset = ((m_uint32_t)vaddr & MIPS_MIN_PAGE_IMASK) >> 2;
   return(b->jit_insn_ptr[offset]);
}

/* Check if the specified address belongs to the specified block */
static forced_inline 
int mips64_jit_tcb_local_addr(mips64_jit_tcb_t *block,m_uint64_t vaddr,
                              u_char **jit_addr)
{
   if ((vaddr & MIPS_MIN_PAGE_MASK) == block->start_pc) {
      *jit_addr = mips64_jit_tcb_get_host_ptr(block,vaddr);
      return(1);
   }

   return(0);
}

/* Check if PC register matches the compiled block virtual address */
static forced_inline 
int mips64_jit_tcb_match(cpu_mips_t *cpu,mips64_jit_tcb_t *block)
{
   m_uint64_t vpage;

   vpage = cpu->pc & ~(m_uint64_t)MIPS_MIN_PAGE_IMASK;
   return(block->start_pc == vpage);
}

/* Compute the hash index for the specified PC value */
static forced_inline m_uint32_t mips64_jit_get_pc_hash(m_uint64_t pc)
{
   m_uint32_t page_hash;

   page_hash = sbox_u32(pc >> MIPS_MIN_PAGE_SHIFT);
   return((page_hash ^ (page_hash >> 12)) & MIPS_JIT_PC_HASH_MASK);
}

/* Check if there are pending IRQ */
extern void mips64_check_pending_irq(mips64_jit_tcb_t *b);

/* Initialize instruction lookup table */
void mips64_jit_create_ilt(void);

/* Initialize the JIT structure */
int mips64_jit_init(cpu_mips_t *cpu);

/* Flush the JIT */
u_int mips64_jit_flush(cpu_mips_t *cpu,u_int threshold);

/* Shutdown the JIT */
void mips64_jit_shutdown(cpu_mips_t *cpu);

/* Check if an instruction is in a delay slot or not */
int mips64_jit_is_delay_slot(mips64_jit_tcb_t *b,m_uint64_t pc);

/* Fetch a MIPS instruction and emit corresponding x86 translated code */
struct mips64_insn_tag *mips64_jit_fetch_and_emit(cpu_mips_t *cpu,
                                                  mips64_jit_tcb_t *block,
                                                  int delay_slot);

/* Record a patch to apply in a compiled block */
int mips64_jit_tcb_record_patch(mips64_jit_tcb_t *block,u_char *x86_ptr,
                                m_uint64_t vaddr);

/* Free an instruction block */
void mips64_jit_tcb_free(cpu_mips_t *cpu,mips64_jit_tcb_t *block,
                         int list_removal);

/* Execute compiled MIPS code */
void *mips64_jit_run_cpu(cpu_gen_t *cpu);

/* Set the Pointer Counter (PC) register */
void mips64_set_pc(mips64_jit_tcb_t *b,m_uint64_t new_pc);

/* Set the Return Address (RA) register */
void mips64_set_ra(mips64_jit_tcb_t *b,m_uint64_t ret_pc);

/* Single-step operation */
void mips64_emit_single_step(mips64_jit_tcb_t *b,mips_insn_t insn);

/* Virtual Breakpoint */
void mips64_emit_breakpoint(mips64_jit_tcb_t *b);

/* Emit unhandled instruction code */
int mips64_emit_invalid_delay_slot(mips64_jit_tcb_t *b);

/* 
 * Increment count register and trigger the timer IRQ if value in compare 
 * register is the same.
 */
void mips64_inc_cp0_count_reg(mips64_jit_tcb_t *b);

/* Increment the number of executed instructions (performance debugging) */
void mips64_inc_perf_counter(mips64_jit_tcb_t *b);

#endif