translator.h
14.5 KB
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
/*
* Copyright (C) 1996-1998 by the Board of Trustees
* of Leland Stanford Junior University.
*
* This file is part of the SimOS distribution.
* See LICENSE file for terms of the license.
*
*/
#ifndef TRANSLATOR_H
#define TRANSLATOR_H
#include "tc.h"
/* TRANSLATOR POLICY */
/* Barrier every basic block */
/*#define CHAIN_BAR_SYNC*/
/* Defining this has the dispatch loop print the current pc to stdout. With NO_CHAINING*/
/* This prints the beginning of every basic block */
/* Presently it skips the slave loop (who wants to see that?) */
/*#define PRINT_PC*/
/* Enables recording of translations */
/*#define RECORD_TRANSLATIONS*/
/* END TRANSLATOR POLICY */
/* All offsets are relative to the one above it */
/* This offset gets put in the pc_tc_lookup hash table. It is the */
/* most conservative. It checks virtual and physical address match */
/* (and so would be used by a jr) */
#ifdef OLDCODE
/* XXX ack! this doesn't work on vcode -BL */
#define SPECULATIVE_ENTRY ((embra.emode == EMBRA_PAGE)?5:4)
/* This is an offset relative to SPECULATIVE_ENTRY. It assumes that */
/* the virtual address is correct, it just checks that the physical */
/* page we want is mapped (and so would be used by branches or jumps */
/* that span a page */
#define CHECK_MAPPING_ENTRY (3)
/* This is also an offset relative to CHECK_MAPPING_ENTRY. It assumes */
/* that we know what virtual address we chained to, and it assumes */
/* that the physical page we are chaining to is mapped. It is */
/* therefore appropriate for branches and jumps within a page */
#define SAME_PAGE_ENTRY (embra.MPinUP?7:5)
#endif
/* This is used by CP0 instructions that can except, and that have no */
/* special parameters (like the move to/from ) */
#ifdef OLDCODE
#define DO_CALLOUT_LEN (6)
#else
#define DO_CALLOUT_LEN (6)
#endif
#ifndef _LANGUAGE_ASSEMBLY
void Translator_Init(void);
/* Both are called from continue_run */
C_LINK TCA Translate( int cpuNum, VA current_pc, int* has_flushed );
C_LINK TCA ChainBasicBlock(TCA jump_addr,VA new_pc);
C_LINK void CountFP(void);
extern TCA Get_TCA_No_Icache_Check( int cpuNum, VA vAddr );
/* ***************************************************************
* Code emission macros
* ***************************************************************/
/* vcode versions of code emission macros */
/* shifts */
#define ECsh(funct, _rd, _rt, shamt) prev_store.real=0; \
VC_ ## funct(VREGS[_rd], VREGS[_rt], \
shamt)
#define VC_srl_op_(_rd, _rt, shamt) v_rshui(_rd, _rt, shamt)
#define VC_sra_op_(_rd, _rt, shamt) v_rshii(_rd, _rt, shamt)
#define VC_sll_op_(_rd, _rt, shamt) v_lshui(_rd, _rt, shamt)
/* arithmetic functions */
#define ECs(funct, _rd, _rs, _rt) prev_store.real=0; \
VC_ ## funct(VREGS[_rd],VREGS[_rs], \
VREGS[_rt])
#define VC_add_op_(_rd, _rs, _rt) v_addi(_rd, _rs, _rt)
#define VC_addi_op_(_rd, _rs, _immed) v_addii(_rd, _rs, _immed)
#define VC_addu_op_(_rd, _rs, _rt) v_addu(_rd, _rs, _rt)
#define VC_and_op_(_rd, _rs, _rt) v_andu(_rd, _rs, _rt)
#define VC_andi_op_(_rd, _rs, _immed) v_andusi(_rd, _rs, (unsigned short) _immed)
#define VC_jr_op_(_rd, _rs, _rt) v_jp(_rs)
/* XXX this is cheesoid; should be more elegant... */
#if defined(SIM_MIPS32)
#define VC_mult_op_(_rd, _rs, _rt) { v_mulhii(_rd, _rs, _rt); \
v_stui(_rd, VREGS[VSS_BASE], HI_OFF); \
v_muli(_rd, _rs, _rt); \
v_stui(_rd, VREGS[VSS_BASE], LO_OFF); }
#define VC_multu_op_(_rd, _rs, _rt) { v_mulhiu(_rd, _rs, _rt); \
v_stui(_rd, VREGS[VSS_BASE], HI_OFF); \
v_mulu(_rd, _rs, _rt); \
v_stui(_rd, VREGS[VSS_BASE], LO_OFF); }
#define VC_div_op_(_rd, _rs, _rt) { v_modi(_rd, _rs, _rt); \
v_stui(_rd, VREGS[VSS_BASE], HI_OFF); \
v_divi(_rd, _rs, _rt); \
v_stui(_rd, VREGS[VSS_BASE], LO_OFF); }
#define VC_divu_op_(_rd, _rs, _rt) { v_modu(_rd, _rs, _rt); \
v_stui(_rd, VREGS[VSS_BASE], HI_OFF); \
v_divu(_rd, _rs, _rt); \
v_stui(_rd, VREGS[VSS_BASE], LO_OFF); }
#else
#define VC_mult_op_(_rd, _rs, _rt) { v_mulhii(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], HI_OFF); \
v_muli(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], LO_OFF); }
#define VC_multu_op_(_rd, _rs, _rt) { v_mulhiu(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], HI_OFF); \
v_mulu(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], LO_OFF); }
#define VC_div_op_(_rd, _rs, _rt) { v_modi(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], HI_OFF); \
v_divi(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], LO_OFF); }
#define VC_divu_op_(_rd, _rs, _rt) { v_modu(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], HI_OFF); \
v_divu(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], LO_OFF); }
#define VC_dmult_op_(_rd, _rs, _rt) { v_mulhil(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], HI_OFF); \
v_mull(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], LO_OFF); }
#define VC_dmultu_op_(_rd, _rs, _rt) { v_mulhiul(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], HI_OFF); \
v_mulul(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], LO_OFF); }
#define VC_ddiv_op_(_rd, _rs, _rt) { v_modl(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], HI_OFF); \
v_divul(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], LO_OFF); }
#define VC_ddivu_op_(_rd, _rs, _rt) { v_modul(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], HI_OFF); \
v_divul(_rd, _rs, _rt); \
v_stli(_rd, VREGS[VSS_BASE], LO_OFF); }
#endif
#define VC_nor_op_(_rd, _rs, _rt) v_noru(_rd, _rs, _rt)
#define VC_or_op_(_rd, _rs, _rt) v_oru(_rd, _rs, _rt)
#define VC_sllv_op_(_rd, _rs, _rt) v_lshu(_rd, _rt, _rs)
#define VC_slt_op_(_rd, _rs, _rt) v_lti(_rd, _rs, _rt)
#define VC_slti_op_(_rd, _rs, _immed) v_ltii(_rd, _rs, _immed)
#define VC_sltiu_op_(_rd, _rs, _immed) v_ltui(_rd, _rs, _immed)
#define VC_sltu_op_(_rd, _rs, _rt) v_ltu(_rd, _rs, _rt)
#define VC_srav_op_(_rd, _rs, _rt) v_rshi(_rd, _rt, _rs)
#define VC_srlv_op_(_rd, _rs, _rt) v_rshu(_rd, _rt, _rs)
#define VC_sub_op_(_rd, _rs, _rt) v_subi(_rd, _rs, _rt)
#define VC_subu_op_(_rd, _rs, _rt) v_subu(_rd, _rs, _rt)
#define VC_xor_op_(_rd, _rs, _rt) v_xoru(_rd, _rs, _rt)
#define VC_xori_op_(_rd, _rs, _immed) v_xorusi(_rd, _rs, \
(unsigned short) _immed)
/* branches - note we only support one label deep!!
* note also that you MUST follow a branch with a
* VCTARGET (i.e. v_label(label)) at the appropriate point in the instruction
* stream!!
*/
#define ECb(funct, _rs, offset) {prev_store.real=0;label = v_genlabel(); \
VC_ ## funct(_rs, offset);}
#define VC_bltz_op_(_rs, offset) v_bltii(VREGS[_rs], 0, label)
#define VCTARGET v_label(label)
#define SET_LABEL(_lab) {labels._lab = v_genlabel(); v_label(labels._lab); \
labels._lab##_addr = v_ip;}
/* This says, subtract the two TC addresses and subtract 1 for the */
/* instruction I am in */
#define USE_LABEL(_lab) _lab
#define USE_LABEL_VALUE(_lab) _lab
/* immediate-mode instructions */
#define ECi(opcode, _rt, _rs, _immed) {prev_store.real=0; \
VC_ ## opcode(VREGS[_rt], VREGS[_rs], \
_immed);}
#define ECilab(opcode, _rt, _rs, _label) {prev_store.real=0; \
VCL_ ## opcode(VREGS[_rt], \
VREGS[_rs], _label);}
#define EC1i(opcode, _rt, _rs, _immed) {prev_store.real=0; \
VC_ ## opcode(FVREGS[_rt],VREGS[_rs], \
_immed);}
#define VC_andiu_op_(_rt, _rs, _immed) v_andusi(_rt, _rs, (unsigned short) _immed)
#define VC_addiu_op_(_rt, _rs, _immed) v_addui(_rt, _rs, _immed)
#define VCL_addiu_op_(_rt, _rs, _label) v_addui(_rt, _rs, \
((unsigned long) (v_ip - (labels. ## _label ## _addr))))
#define VC_bne_op_(_rt, _rs, _immed) {label = v_genlabel(); \
v_bnei(_rs, _rt, label);}
#define VCL_bne_op_(_rt, _rs, _label) v_bnei(_rs, _rt, labels. ## _label)
#define VC_beq_op_(_rt, _rs, _immed) {label = v_genlabel(); \
v_beqi(_rs, _rt, label);}
#define VC_blez_op_(_rt, _rs, _immed) {label = v_genlabel(); \
v_bleii(_rs, 0, label);}
#define VCL_blez_op_(_rt, _rs, _label) v_bleii(_rs, 0, (labels. ## _label))
#define VC_bgez_op_(_rs, _immed) {label = v_genlabel(); \
v_bgeii(VREGS[_rs], 0, label);}
#define VC_bgtz_op_(_rt, _rs, _immed) {label = v_genlabel();\
v_bgtii(_rs, 0, label);}
#define VC_ori_op_(_rt, _rs, _immed) v_orusi(_rt, _rs, (unsigned short) (_immed))
#define VC_lw_op_(_rt, _rs, _immed) v_ldui(_rt, _rs, _immed)
#define VC_lwc1_op_(_rt, _rs, _immed) v_ldfi(_rt, _rs, _immed)
#ifdef SIM_MIPS64
/* XXX THIS STILL WON'T WORK -BL */
#define VC_ldc1_op_(_rt, _rs, _immed) dldc1((_rt).reg,(_rs).reg, _immed)
#else
#define VC_ldc1_op_(_rt, _rs, _immed) v_lddi(_rt, _rs, _immed)
#endif
/** this is inefficient; probably can make one of these a NOP -BL */
/* #define VC_lwl_op_(_rt, _rs, _immed) v_uldui(_rt, _rs, _immed) */
/* #define VC_lwr_op_(_rt, _rs, _immed) v_uldui(_rt, _rs, _immed) */
#define VC_lwl_op_(_rt, _rs, _immed) lwl((_rt).reg, (_rs).reg, _immed)
#define VC_lwr_op_(_rt, _rs, _immed) lwr((_rt).reg, (_rs).reg, _immed)
#define VC_ldl_op_(_rt, _rs, _immed) ldl((_rt).reg, (_rs).reg, _immed)
#define VC_ldr_op_(_rt, _rs, _immed) ldr((_rt).reg, (_rs).reg, _immed)
/** ugh!! we're hosed on these operations. Need to fix this!!! */
/* #define VC_swl_op_(_rt, _rs, _immed) v_ustui(_rt, _rs, _immed)
#define VC_swr_op_(_rt, _rs, _immed) v_ustui(_rt, _rs, _immed)
right now, an ugly hack.... XXX -BL
*/
#define VC_swl_op_(_rt, _rs, _immed) swl((_rt).reg, (_rs).reg, _immed)
#define VC_swr_op_(_rt, _rs, _immed) swr((_rt).reg, (_rs).reg, _immed)
#define VC_sdl_op_(_rt, _rs, _immed) sdl((_rt).reg, (_rs).reg, _immed)
#define VC_sdr_op_(_rt, _rs, _immed) sdr((_rt).reg, (_rs).reg, _immed)
#define VC_lui_op_(_rt, _rs, _immed) v_seti(_rt,((_immed)<<16 & 0xffff0000))
#define VC_sw_op_(_rt, _rs, _immed) v_stui(_rt, _rs, _immed)
#define VC_swc1_op_(_rt, _rs, _immed) v_stfi(_rt, _rs, _immed)
#ifdef SIM_MIPS64
/* XXX THIS STILL WON'T WORK -BL */
#define VC_sdc1_op_(_rt, _rs, _immed) dsdc1((_rt).reg, (_rs).reg, _immed)
#else
#define VC_sdc1_op_(_rt, _rs, _immed) v_stdi(_rt, _rs, _immed)
#endif
#define VC_lb_op_(_rt, _rs, _immed) v_ldci(_rt, _rs, _immed)
#define VC_sb_op_(_rt, _rs, _immed) v_stci(_rt, _rs, _immed)
#define VC_lbu_op_(_rt, _rs, _immed) v_lduci(_rt, _rs, _immed)
#define VC_lh_op_(_rt, _rs, _immed) v_ldsi(_rt, _rs, _immed)
#define VC_sh_op_(_rt, _rs, _immed) v_stsi(_rt, _rs, _immed)
#define VC_lhu_op_(_rt, _rs, _immed) v_ldusi(_rt, _rs, _immed)
/** XXX another ugly hack for now; need to implement in vcode -BL */
#define VC_lwu_op_(_rt, _rs, _immed) { v_ldui(_rt, _rs, _immed); \
dsll32((_rt).reg, (_rt).reg, 0); \
dsrl32((_rt).reg, (_rt).reg, 0); \
}
/* note we only support one label deep */
/* jumps */
#define ECj(opcode, target) prev_store.real=0; VC_ ## opcode(target)
/* XXX this is a disgusting hack to make vcode generate a plain old
* jal using r31; need a better way to do this -BL
* should be: v_jalpi(_ra,target), if we had ra
* this WILL NOT WORK on sparc, etc. - need to fix
*/
#define VC_jal_op_(target) {prev_store.real=0; jal((unsigned)target);v_nop();}
#define VC_j_op_(target) {prev_store.real = 0; v_jpi(target);}
/* nop */
#define ECnop {prev_store.real = 0; } /* was v_nop(); */
/* more immediates */
#define ECImmed(_op1, _op2, _rs, _immed) prev_store.real=0; \
VC_ ## _op1 ## _op2(_rs, _immed)
/* Coprocessor instructions */
/* cop1move: move between integer register and fp data/control registers */
#define ECCop1Move(_inst, _rt, _fs) VC_ ## _inst(_rt, _fs)
/* RPB -- I changed these to be analogous to mtc/mfc below */
#define VC_ctc_op_(_rt, _fs) { prev_store.real=0; ctc1(_fs, _rt); }
#define VC_cfc_op_(_rt, _fs) { prev_store.real=0; cfc1(_rt, _fs); }
/* XXX right now, this is efficient but non-portable; for SPARC add
* new vcode operation?? or just go through memory?
*/
#define VC_mtc_op_(_rt, _fs) { prev_store.real=0; movi2f(_fs, _rt); }
#define VC_mfc_op_(_rt, _fs) { prev_store.real=0; movf2i(_rt, _fs); }
#define VC_dmtc_op_(_rt, _fs) { prev_store.real=0; dmtc1(_fs, _rt); }
#define VC_dmfc_op_(_rt, _fs) { prev_store.real=0; dmfc1(_rt, _fs); }
/* Generate MIPS instructions - CHEESOID!! Yes, we have to
* do this, at least right now!! -BL
*/
#define VC_ComposeBCOND(rs,funct,offset) (prev_store.real = 0, (int)\
(bcond_op << 26 | (rs) << 21 | (funct) << 16 | ((offset) & 0xffff ) ) )
#define VC_ComposeImmed(opCode,rs,rt,immed) (prev_store.real = 0, (int)\
((opCode) << 26 | (rs) << 21 | (rt) << 16 | ((uint)(immed) & 0xffff ) ) )
/* temporary hack to test whether chaining is totally hosed */
#define ComposeJump(opCode,target) (prev_store.real = 0, (int)\
((opCode) << 26 |((uint)(target) & 0x3ffffff ) ) )
#if defined(SIM_MIPS64)
/* 64-bit instructions */
#define VC_dsll_op_(_rd, _rs, _rt) v_lshli(_rd, _rs, _rt)
#define VC_dsll32_op_(_rd, _rs, _imm) dsll32(_rd.reg, _rs.reg, _imm)
#define VC_dsrl_op_(_rd, _rs, _imm) v_rshuli(_rd, _rs, _imm)
#define VC_dsra_op_(_rd, _rs, _imm) v_rshli(_rd, _rs, _imm)
#define VC_dsra32_op_(_rd, _rs, _imm) dsra32(_rd.reg, _rs.reg, _imm)
#define VC_dsrl32_op_(_rd, _rs, _imm) dsrl32(_rd.reg, _rs.reg, _imm)
#define VC_dadd_op_(_rd, _rs, _rt) v_addl(_rd, _rs, _rt)
#define VC_daddu_op_(_rd, _rs, _rt) v_addul(_rd, _rs, _rt)
#define VC_dsllv_op_(_rd, _rs, _rt) v_lshl(_rd, _rs, _rt)
#define VC_dsrlv_op_(_rd, _rs, _rt) v_rshul(_rd, _rs, _rt)
#define VC_dsrav_op_(_rd, _rs, _rt) v_rshl(_rd, _rs, _rt)
#define VC_dsub_op_(_rd, _rs, _rt) v_subl(_rd, _rs, _rt)
#define VC_dsubu_op_(_rd, _rs, _rt) v_subul(_rd, _rs, _rt)
#define VC_daddi_op_(_rd, _rs, _rt) v_addli(_rd, _rs, _rt)
#define VC_daddiu_op_(_rd, _rs, _rt) v_adduli(_rd, _rs, _rt)
#define VC_ld_op_(_rt, _rs, _immed) v_ldli(_rt, _rs, _immed)
#define VC_sd_op_(_rt, _rs, _immed) v_stli(_rt, _rs, _immed)
#endif
/* allow vcode to do this for us */
#define VCL_lw_op_(_reg, _addr) {Load_32_Bit_Immed (_reg, _addr); \
v_ldui(VREGS[_reg], VREGS[_reg], 0);}
#define VCL_ld_op_(_reg, _addr) {Load_32_Bit_Immed (_reg, _addr); \
v_ldli(VREGS[_reg], VREGS[_reg], 0);}
#define VCL_lb_op_(_reg, _addr) {Load_32_Bit_Immed(_reg, _addr); \
v_ldci(VREGS[_reg], VREGS[_reg], 0);}
/* Convenience Functions (glorified macros) */
#define Load_32_Bit_Immed(_reg, _immed){prev_store.real=0; \
v_seti(VREGS[_reg],(_immed) & 0xffff0000); \
v_orii(VREGS[_reg], VREGS[_reg], \
(_immed) & 0xffff);}
/* #define Load_64_Bit_Immed(_reg, _immed){prev_store.real=0; \
v_setl(VREGS[_reg],(_immed));} */
#if defined(SIM_MIPS32)
#define Load_Reg_Immed Load_32_Bit_Immed
#endif
#endif /*_LANGUAGE_ASSEMBLY */
#endif /* TRANSLATOR_H */