1
2 /*---------------------------------------------------------------*/
3 /*--- begin guest_mips_helpers.c ---*/
4 /*---------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2010-2013 RT-RK
11 mips-valgrind@rt-rk.com
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29 */
30
31 #include "libvex_basictypes.h"
32 #include "libvex_emnote.h"
33 #include "libvex_guest_mips32.h"
34 #include "libvex_guest_mips64.h"
35 #include "libvex_ir.h"
36 #include "libvex.h"
37
38 #include "main_util.h"
39 #include "main_globals.h"
40 #include "guest_generic_bb_to_IR.h"
41 #include "guest_mips_defs.h"
42
43 /* This file contains helper functions for mips guest code. Calls to
44 these functions are generated by the back end.
45 */
46
47 #define ALWAYSDEFD32(field) \
48 { offsetof(VexGuestMIPS32State, field), \
49 (sizeof ((VexGuestMIPS32State*)0)->field) }
50
51 #define ALWAYSDEFD64(field) \
52 { offsetof(VexGuestMIPS64State, field), \
53 (sizeof ((VexGuestMIPS64State*)0)->field) }
54
guest_mips32_spechelper(const HChar * function_name,IRExpr ** args,IRStmt ** precedingStmts,Int n_precedingStmts)55 IRExpr *guest_mips32_spechelper(const HChar * function_name, IRExpr ** args,
56 IRStmt ** precedingStmts, Int n_precedingStmts)
57 {
58 return NULL;
59 }
60
guest_mips64_spechelper(const HChar * function_name,IRExpr ** args,IRStmt ** precedingStmts,Int n_precedingStmts)61 IRExpr *guest_mips64_spechelper ( const HChar * function_name, IRExpr ** args,
62 IRStmt ** precedingStmts,
63 Int n_precedingStmts )
64 {
65 return NULL;
66 }
67
68 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestMIPS32_initialise(VexGuestMIPS32State * vex_state)69 void LibVEX_GuestMIPS32_initialise( /*OUT*/ VexGuestMIPS32State * vex_state)
70 {
71 vex_state->guest_r0 = 0; /* Hardwired to 0 */
72 vex_state->guest_r1 = 0; /* Assembler temporary */
73 vex_state->guest_r2 = 0; /* Values for function returns ... */
74 vex_state->guest_r3 = 0; /* ...and expression evaluation */
75 vex_state->guest_r4 = 0; /* Function arguments */
76 vex_state->guest_r5 = 0;
77 vex_state->guest_r6 = 0;
78 vex_state->guest_r7 = 0;
79 vex_state->guest_r8 = 0; /* Temporaries */
80 vex_state->guest_r9 = 0;
81 vex_state->guest_r10 = 0;
82 vex_state->guest_r11 = 0;
83 vex_state->guest_r12 = 0;
84 vex_state->guest_r13 = 0;
85 vex_state->guest_r14 = 0;
86 vex_state->guest_r15 = 0;
87 vex_state->guest_r16 = 0; /* Saved temporaries */
88 vex_state->guest_r17 = 0;
89 vex_state->guest_r18 = 0;
90 vex_state->guest_r19 = 0;
91 vex_state->guest_r20 = 0;
92 vex_state->guest_r21 = 0;
93 vex_state->guest_r22 = 0;
94 vex_state->guest_r23 = 0;
95 vex_state->guest_r24 = 0; /* Temporaries */
96 vex_state->guest_r25 = 0;
97 vex_state->guest_r26 = 0; /* Reserved for OS kernel */
98 vex_state->guest_r27 = 0;
99 vex_state->guest_r28 = 0; /* Global pointer */
100 vex_state->guest_r29 = 0; /* Stack pointer */
101 vex_state->guest_r30 = 0; /* Frame pointer */
102 vex_state->guest_r31 = 0; /* Return address */
103 vex_state->guest_PC = 0; /* Program counter */
104 vex_state->guest_HI = 0; /* Multiply and divide register higher result */
105 vex_state->guest_LO = 0; /* Multiply and divide register lower result */
106
107 /* FPU Registers */
108 vex_state->guest_f0 = 0x7ff800007ff80000ULL; /* Floting point GP registers */
109 vex_state->guest_f1 = 0x7ff800007ff80000ULL;
110 vex_state->guest_f2 = 0x7ff800007ff80000ULL;
111 vex_state->guest_f3 = 0x7ff800007ff80000ULL;
112 vex_state->guest_f4 = 0x7ff800007ff80000ULL;
113 vex_state->guest_f5 = 0x7ff800007ff80000ULL;
114 vex_state->guest_f6 = 0x7ff800007ff80000ULL;
115 vex_state->guest_f7 = 0x7ff800007ff80000ULL;
116 vex_state->guest_f8 = 0x7ff800007ff80000ULL;
117 vex_state->guest_f9 = 0x7ff800007ff80000ULL;
118 vex_state->guest_f10 = 0x7ff800007ff80000ULL;
119 vex_state->guest_f11 = 0x7ff800007ff80000ULL;
120 vex_state->guest_f12 = 0x7ff800007ff80000ULL;
121 vex_state->guest_f13 = 0x7ff800007ff80000ULL;
122 vex_state->guest_f14 = 0x7ff800007ff80000ULL;
123 vex_state->guest_f15 = 0x7ff800007ff80000ULL;
124 vex_state->guest_f16 = 0x7ff800007ff80000ULL;
125 vex_state->guest_f17 = 0x7ff800007ff80000ULL;
126 vex_state->guest_f18 = 0x7ff800007ff80000ULL;
127 vex_state->guest_f19 = 0x7ff800007ff80000ULL;
128 vex_state->guest_f20 = 0x7ff800007ff80000ULL;
129 vex_state->guest_f21 = 0x7ff800007ff80000ULL;
130 vex_state->guest_f22 = 0x7ff800007ff80000ULL;
131 vex_state->guest_f23 = 0x7ff800007ff80000ULL;
132 vex_state->guest_f24 = 0x7ff800007ff80000ULL;
133 vex_state->guest_f25 = 0x7ff800007ff80000ULL;
134 vex_state->guest_f26 = 0x7ff800007ff80000ULL;
135 vex_state->guest_f27 = 0x7ff800007ff80000ULL;
136 vex_state->guest_f28 = 0x7ff800007ff80000ULL;
137 vex_state->guest_f29 = 0x7ff800007ff80000ULL;
138 vex_state->guest_f30 = 0x7ff800007ff80000ULL;
139 vex_state->guest_f31 = 0x7ff800007ff80000ULL;
140
141 vex_state->guest_FIR = 0; /* FP implementation and revision register */
142 vex_state->guest_FCCR = 0; /* FP condition codes register */
143 vex_state->guest_FEXR = 0; /* FP exceptions register */
144 vex_state->guest_FENR = 0; /* FP enables register */
145 vex_state->guest_FCSR = 0; /* FP control/status register */
146 vex_state->guest_ULR = 0; /* TLS */
147
148 /* Various pseudo-regs mandated by Vex or Valgrind. */
149 /* Emulation notes */
150 vex_state->guest_EMNOTE = 0;
151
152 /* For clflush: record start and length of area to invalidate */
153 vex_state->guest_CMSTART = 0;
154 vex_state->guest_CMLEN = 0;
155 vex_state->host_EvC_COUNTER = 0;
156 vex_state->host_EvC_FAILADDR = 0;
157
158 /* Used to record the unredirected guest address at the start of
159 a translation whose start has been redirected. By reading
160 this pseudo-register shortly afterwards, the translation can
161 find out what the corresponding no-redirection address was.
162 Note, this is only set for wrap-style redirects, not for
163 replace-style ones. */
164 vex_state->guest_NRADDR = 0;
165
166 vex_state->guest_COND = 0;
167
168 /* MIPS32 DSP ASE(r2) specific registers */
169 vex_state->guest_DSPControl = 0; /* DSPControl register */
170 vex_state->guest_ac0 = 0; /* Accumulator 0 */
171 vex_state->guest_ac1 = 0; /* Accumulator 1 */
172 vex_state->guest_ac2 = 0; /* Accumulator 2 */
173 vex_state->guest_ac3 = 0; /* Accumulator 3 */
174 }
175
LibVEX_GuestMIPS64_initialise(VexGuestMIPS64State * vex_state)176 void LibVEX_GuestMIPS64_initialise ( /*OUT*/ VexGuestMIPS64State * vex_state )
177 {
178 vex_state->guest_r0 = 0; /* Hardwired to 0 */
179 vex_state->guest_r1 = 0; /* Assembler temporary */
180 vex_state->guest_r2 = 0; /* Values for function returns ... */
181 vex_state->guest_r3 = 0;
182 vex_state->guest_r4 = 0; /* Function arguments */
183 vex_state->guest_r5 = 0;
184 vex_state->guest_r6 = 0;
185 vex_state->guest_r7 = 0;
186 vex_state->guest_r8 = 0;
187 vex_state->guest_r9 = 0;
188 vex_state->guest_r10 = 0;
189 vex_state->guest_r11 = 0;
190 vex_state->guest_r12 = 0; /* Temporaries */
191 vex_state->guest_r13 = 0;
192 vex_state->guest_r14 = 0;
193 vex_state->guest_r15 = 0;
194 vex_state->guest_r16 = 0; /* Saved temporaries */
195 vex_state->guest_r17 = 0;
196 vex_state->guest_r18 = 0;
197 vex_state->guest_r19 = 0;
198 vex_state->guest_r20 = 0;
199 vex_state->guest_r21 = 0;
200 vex_state->guest_r22 = 0;
201 vex_state->guest_r23 = 0;
202 vex_state->guest_r24 = 0; /* Temporaries */
203 vex_state->guest_r25 = 0;
204 vex_state->guest_r26 = 0; /* Reserved for OS kernel */
205 vex_state->guest_r27 = 0;
206 vex_state->guest_r28 = 0; /* Global pointer */
207 vex_state->guest_r29 = 0; /* Stack pointer */
208 vex_state->guest_r30 = 0; /* Frame pointer */
209 vex_state->guest_r31 = 0; /* Return address */
210 vex_state->guest_PC = 0; /* Program counter */
211 vex_state->guest_HI = 0; /* Multiply and divide register higher result */
212 vex_state->guest_LO = 0; /* Multiply and divide register lower result */
213
214 /* FPU Registers */
215 vex_state->guest_f0 = 0x7ff800007ff80000ULL; /* Floting point registers */
216 vex_state->guest_f1 = 0x7ff800007ff80000ULL;
217 vex_state->guest_f2 = 0x7ff800007ff80000ULL;
218 vex_state->guest_f3 = 0x7ff800007ff80000ULL;
219 vex_state->guest_f4 = 0x7ff800007ff80000ULL;
220 vex_state->guest_f5 = 0x7ff800007ff80000ULL;
221 vex_state->guest_f6 = 0x7ff800007ff80000ULL;
222 vex_state->guest_f7 = 0x7ff800007ff80000ULL;
223 vex_state->guest_f8 = 0x7ff800007ff80000ULL;
224 vex_state->guest_f9 = 0x7ff800007ff80000ULL;
225 vex_state->guest_f10 = 0x7ff800007ff80000ULL;
226 vex_state->guest_f11 = 0x7ff800007ff80000ULL;
227 vex_state->guest_f12 = 0x7ff800007ff80000ULL;
228 vex_state->guest_f13 = 0x7ff800007ff80000ULL;
229 vex_state->guest_f14 = 0x7ff800007ff80000ULL;
230 vex_state->guest_f15 = 0x7ff800007ff80000ULL;
231 vex_state->guest_f16 = 0x7ff800007ff80000ULL;
232 vex_state->guest_f17 = 0x7ff800007ff80000ULL;
233 vex_state->guest_f18 = 0x7ff800007ff80000ULL;
234 vex_state->guest_f19 = 0x7ff800007ff80000ULL;
235 vex_state->guest_f20 = 0x7ff800007ff80000ULL;
236 vex_state->guest_f21 = 0x7ff800007ff80000ULL;
237 vex_state->guest_f22 = 0x7ff800007ff80000ULL;
238 vex_state->guest_f23 = 0x7ff800007ff80000ULL;
239 vex_state->guest_f24 = 0x7ff800007ff80000ULL;
240 vex_state->guest_f25 = 0x7ff800007ff80000ULL;
241 vex_state->guest_f26 = 0x7ff800007ff80000ULL;
242 vex_state->guest_f27 = 0x7ff800007ff80000ULL;
243 vex_state->guest_f28 = 0x7ff800007ff80000ULL;
244 vex_state->guest_f29 = 0x7ff800007ff80000ULL;
245 vex_state->guest_f30 = 0x7ff800007ff80000ULL;
246 vex_state->guest_f31 = 0x7ff800007ff80000ULL;
247
248 vex_state->guest_FIR = 0; /* FP implementation and revision register */
249 vex_state->guest_FCCR = 0; /* FP condition codes register */
250 vex_state->guest_FEXR = 0; /* FP exceptions register */
251 vex_state->guest_FENR = 0; /* FP enables register */
252 vex_state->guest_FCSR = 0; /* FP control/status register */
253
254 vex_state->guest_ULR = 0;
255
256 /* Various pseudo-regs mandated by Vex or Valgrind. */
257 /* Emulation notes */
258 vex_state->guest_EMNOTE = 0;
259
260 /* For clflush: record start and length of area to invalidate */
261 vex_state->guest_CMSTART = 0;
262 vex_state->guest_CMLEN = 0;
263 vex_state->host_EvC_COUNTER = 0;
264 vex_state->host_EvC_FAILADDR = 0;
265
266 /* Used to record the unredirected guest address at the start of
267 a translation whose start has been redirected. By reading
268 this pseudo-register shortly afterwards, the translation can
269 find out what the corresponding no-redirection address was.
270 Note, this is only set for wrap-style redirects, not for
271 replace-style ones. */
272 vex_state->guest_NRADDR = 0;
273
274 vex_state->guest_COND = 0;
275 }
276
277 /*-----------------------------------------------------------*/
278 /*--- Describing the mips guest state, for the benefit ---*/
279 /*--- of iropt and instrumenters. ---*/
280 /*-----------------------------------------------------------*/
281
282 /* Figure out if any part of the guest state contained in minoff
283 .. maxoff requires precise memory exceptions. If in doubt return
284 True (but this generates significantly slower code).
285
286 We enforce precise exns for guest SP, PC.
287
288 Only SP is needed in mode VexRegUpdSpAtMemAccess.
289 */
guest_mips32_state_requires_precise_mem_exns(Int minoff,Int maxoff)290 Bool guest_mips32_state_requires_precise_mem_exns(Int minoff, Int maxoff)
291 {
292 Int sp_min = offsetof(VexGuestMIPS32State, guest_r29);
293 Int sp_max = sp_min + 4 - 1;
294 Int pc_min = offsetof(VexGuestMIPS32State, guest_PC);
295 Int pc_max = pc_min + 4 - 1;
296
297 if (maxoff < sp_min || minoff > sp_max) {
298 /* no overlap with sp */
299 if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
300 return False; /* We only need to check stack pointer. */
301 } else {
302 return True;
303 }
304
305 if (maxoff < pc_min || minoff > pc_max) {
306 /* no overlap with pc */
307 } else {
308 return True;
309 }
310
311 /* We appear to need precise updates of R11 in order to get proper
312 stacktraces from non-optimised code. */
313 Int fp_min = offsetof(VexGuestMIPS32State, guest_r30);
314 Int fp_max = fp_min + 4 - 1;
315
316 if (maxoff < fp_min || minoff > fp_max) {
317 /* no overlap with fp */
318 } else {
319 return True;
320 }
321
322 return False;
323 }
324
guest_mips64_state_requires_precise_mem_exns(Int minoff,Int maxoff)325 Bool guest_mips64_state_requires_precise_mem_exns ( Int minoff, Int maxoff )
326 {
327 Int sp_min = offsetof(VexGuestMIPS64State, guest_r29);
328 Int sp_max = sp_min + 8 - 1;
329 Int pc_min = offsetof(VexGuestMIPS64State, guest_PC);
330 Int pc_max = pc_min + 8 - 1;
331
332 if ( maxoff < sp_min || minoff > sp_max ) {
333 /* no overlap with sp */
334 if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
335 return False; /* We only need to check stack pointer. */
336 } else {
337 return True;
338 }
339
340 if ( maxoff < pc_min || minoff > pc_max ) {
341 /* no overlap with pc */
342 } else {
343 return True;
344 }
345
346 Int fp_min = offsetof(VexGuestMIPS64State, guest_r30);
347 Int fp_max = fp_min + 8 - 1;
348
349 if ( maxoff < fp_min || minoff > fp_max ) {
350 /* no overlap with fp */
351 } else {
352 return True;
353 }
354
355 return False;
356 }
357
358 VexGuestLayout mips32Guest_layout = {
359 /* Total size of the guest state, in bytes. */
360 .total_sizeB = sizeof(VexGuestMIPS32State),
361 /* Describe the stack pointer. */
362 .offset_SP = offsetof(VexGuestMIPS32State, guest_r29),
363 .sizeof_SP = 4,
364 /* Describe the frame pointer. */
365 .offset_FP = offsetof(VexGuestMIPS32State, guest_r30),
366 .sizeof_FP = 4,
367 /* Describe the instruction pointer. */
368 .offset_IP = offsetof(VexGuestMIPS32State, guest_PC),
369 .sizeof_IP = 4,
370 /* Describe any sections to be regarded by Memcheck as
371 'always-defined'. */
372 .n_alwaysDefd = 8,
373 /* ? :( */
374 .alwaysDefd = {
375 /* 0 */ ALWAYSDEFD32(guest_r0),
376 /* 1 */ ALWAYSDEFD32(guest_r1),
377 /* 2 */ ALWAYSDEFD32(guest_EMNOTE),
378 /* 3 */ ALWAYSDEFD32(guest_CMSTART),
379 /* 4 */ ALWAYSDEFD32(guest_CMLEN),
380 /* 5 */ ALWAYSDEFD32(guest_r29),
381 /* 6 */ ALWAYSDEFD32(guest_r31),
382 /* 7 */ ALWAYSDEFD32(guest_ULR)
383 }
384 };
385
386 VexGuestLayout mips64Guest_layout = {
387 /* Total size of the guest state, in bytes. */
388 .total_sizeB = sizeof(VexGuestMIPS64State),
389 /* Describe the stack pointer. */
390 .offset_SP = offsetof(VexGuestMIPS64State, guest_r29),
391 .sizeof_SP = 8,
392 /* Describe the frame pointer. */
393 .offset_FP = offsetof(VexGuestMIPS64State, guest_r30),
394 .sizeof_FP = 8,
395 /* Describe the instruction pointer. */
396 .offset_IP = offsetof(VexGuestMIPS64State, guest_PC),
397 .sizeof_IP = 8,
398 /* Describe any sections to be regarded by Memcheck as
399 'always-defined'. */
400 .n_alwaysDefd = 7,
401 /* ? :( */
402 .alwaysDefd = {
403 /* 0 */ ALWAYSDEFD64 (guest_r0),
404 /* 1 */ ALWAYSDEFD64 (guest_EMNOTE),
405 /* 2 */ ALWAYSDEFD64 (guest_CMSTART),
406 /* 3 */ ALWAYSDEFD64 (guest_CMLEN),
407 /* 4 */ ALWAYSDEFD64 (guest_r29),
408 /* 5 */ ALWAYSDEFD64 (guest_r31),
409 /* 6 */ ALWAYSDEFD64 (guest_ULR)
410 }
411 };
412
413 #define ASM_VOLATILE_CASE(rd, sel) \
414 case rd: \
415 asm volatile ("mfc0 %0, $" #rd ", "#sel"\n\t" :"=r" (x) ); \
416 break;
417
mips32_dirtyhelper_mfc0(UInt rd,UInt sel)418 UInt mips32_dirtyhelper_mfc0(UInt rd, UInt sel)
419 {
420 UInt x = 0;
421 #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
422 switch (sel) {
423 case 0:
424 /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
425 switch (rd) {
426 ASM_VOLATILE_CASE(0, 0);
427 ASM_VOLATILE_CASE(1, 0);
428 ASM_VOLATILE_CASE(2, 0);
429 ASM_VOLATILE_CASE(3, 0);
430 ASM_VOLATILE_CASE(4, 0);
431 ASM_VOLATILE_CASE(5, 0);
432 ASM_VOLATILE_CASE(6, 0);
433 ASM_VOLATILE_CASE(7, 0);
434 ASM_VOLATILE_CASE(8, 0);
435 ASM_VOLATILE_CASE(9, 0);
436 ASM_VOLATILE_CASE(10, 0);
437 ASM_VOLATILE_CASE(11, 0);
438 ASM_VOLATILE_CASE(12, 0);
439 ASM_VOLATILE_CASE(13, 0);
440 ASM_VOLATILE_CASE(14, 0);
441 ASM_VOLATILE_CASE(15, 0);
442 ASM_VOLATILE_CASE(16, 0);
443 ASM_VOLATILE_CASE(17, 0);
444 ASM_VOLATILE_CASE(18, 0);
445 ASM_VOLATILE_CASE(19, 0);
446 ASM_VOLATILE_CASE(20, 0);
447 ASM_VOLATILE_CASE(21, 0);
448 ASM_VOLATILE_CASE(22, 0);
449 ASM_VOLATILE_CASE(23, 0);
450 ASM_VOLATILE_CASE(24, 0);
451 ASM_VOLATILE_CASE(25, 0);
452 ASM_VOLATILE_CASE(26, 0);
453 ASM_VOLATILE_CASE(27, 0);
454 ASM_VOLATILE_CASE(28, 0);
455 ASM_VOLATILE_CASE(29, 0);
456 ASM_VOLATILE_CASE(30, 0);
457 ASM_VOLATILE_CASE(31, 0);
458 default:
459 break;
460 }
461 break;
462 case 1:
463 /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
464 switch (rd) {
465 ASM_VOLATILE_CASE(0, 1);
466 ASM_VOLATILE_CASE(1, 1);
467 ASM_VOLATILE_CASE(2, 1);
468 ASM_VOLATILE_CASE(3, 1);
469 ASM_VOLATILE_CASE(4, 1);
470 ASM_VOLATILE_CASE(5, 1);
471 ASM_VOLATILE_CASE(6, 1);
472 ASM_VOLATILE_CASE(7, 1);
473 ASM_VOLATILE_CASE(8, 1);
474 ASM_VOLATILE_CASE(9, 1);
475 ASM_VOLATILE_CASE(10, 1);
476 ASM_VOLATILE_CASE(11, 1);
477 ASM_VOLATILE_CASE(12, 1);
478 ASM_VOLATILE_CASE(13, 1);
479 ASM_VOLATILE_CASE(14, 1);
480 ASM_VOLATILE_CASE(15, 1);
481 ASM_VOLATILE_CASE(16, 1);
482 ASM_VOLATILE_CASE(17, 1);
483 ASM_VOLATILE_CASE(18, 1);
484 ASM_VOLATILE_CASE(19, 1);
485 ASM_VOLATILE_CASE(20, 1);
486 ASM_VOLATILE_CASE(21, 1);
487 ASM_VOLATILE_CASE(22, 1);
488 ASM_VOLATILE_CASE(23, 1);
489 ASM_VOLATILE_CASE(24, 1);
490 ASM_VOLATILE_CASE(25, 1);
491 ASM_VOLATILE_CASE(26, 1);
492 ASM_VOLATILE_CASE(27, 1);
493 ASM_VOLATILE_CASE(28, 1);
494 ASM_VOLATILE_CASE(29, 1);
495 ASM_VOLATILE_CASE(30, 1);
496 ASM_VOLATILE_CASE(31, 1);
497 default:
498 break;
499 }
500 break;
501 case 2:
502 /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
503 switch (rd) {
504 ASM_VOLATILE_CASE(0, 2);
505 ASM_VOLATILE_CASE(1, 2);
506 ASM_VOLATILE_CASE(2, 2);
507 ASM_VOLATILE_CASE(3, 1);
508 ASM_VOLATILE_CASE(4, 2);
509 ASM_VOLATILE_CASE(5, 2);
510 ASM_VOLATILE_CASE(6, 2);
511 ASM_VOLATILE_CASE(7, 2);
512 ASM_VOLATILE_CASE(8, 2);
513 ASM_VOLATILE_CASE(9, 2);
514 ASM_VOLATILE_CASE(10, 2);
515 ASM_VOLATILE_CASE(11, 2);
516 ASM_VOLATILE_CASE(12, 2);
517 ASM_VOLATILE_CASE(13, 2);
518 ASM_VOLATILE_CASE(14, 2);
519 ASM_VOLATILE_CASE(15, 2);
520 ASM_VOLATILE_CASE(16, 2);
521 ASM_VOLATILE_CASE(17, 2);
522 ASM_VOLATILE_CASE(18, 2);
523 ASM_VOLATILE_CASE(19, 2);
524 ASM_VOLATILE_CASE(20, 2);
525 ASM_VOLATILE_CASE(21, 2);
526 ASM_VOLATILE_CASE(22, 2);
527 ASM_VOLATILE_CASE(23, 2);
528 ASM_VOLATILE_CASE(24, 2);
529 ASM_VOLATILE_CASE(25, 2);
530 ASM_VOLATILE_CASE(26, 2);
531 ASM_VOLATILE_CASE(27, 2);
532 ASM_VOLATILE_CASE(28, 2);
533 ASM_VOLATILE_CASE(29, 2);
534 ASM_VOLATILE_CASE(30, 2);
535 ASM_VOLATILE_CASE(31, 2);
536 default:
537 break;
538 }
539 break;
540 case 3:
541 /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
542 switch (rd) {
543 ASM_VOLATILE_CASE(0, 3);
544 ASM_VOLATILE_CASE(1, 3);
545 ASM_VOLATILE_CASE(2, 3);
546 ASM_VOLATILE_CASE(3, 3);
547 ASM_VOLATILE_CASE(4, 3);
548 ASM_VOLATILE_CASE(5, 3);
549 ASM_VOLATILE_CASE(6, 3);
550 ASM_VOLATILE_CASE(7, 3);
551 ASM_VOLATILE_CASE(8, 3);
552 ASM_VOLATILE_CASE(9, 3);
553 ASM_VOLATILE_CASE(10, 3);
554 ASM_VOLATILE_CASE(11, 3);
555 ASM_VOLATILE_CASE(12, 3);
556 ASM_VOLATILE_CASE(13, 3);
557 ASM_VOLATILE_CASE(14, 3);
558 ASM_VOLATILE_CASE(15, 3);
559 ASM_VOLATILE_CASE(16, 3);
560 ASM_VOLATILE_CASE(17, 3);
561 ASM_VOLATILE_CASE(18, 3);
562 ASM_VOLATILE_CASE(19, 3);
563 ASM_VOLATILE_CASE(20, 3);
564 ASM_VOLATILE_CASE(21, 3);
565 ASM_VOLATILE_CASE(22, 3);
566 ASM_VOLATILE_CASE(23, 3);
567 ASM_VOLATILE_CASE(24, 3);
568 ASM_VOLATILE_CASE(25, 3);
569 ASM_VOLATILE_CASE(26, 3);
570 ASM_VOLATILE_CASE(27, 3);
571 ASM_VOLATILE_CASE(28, 3);
572 ASM_VOLATILE_CASE(29, 3);
573 ASM_VOLATILE_CASE(30, 3);
574 ASM_VOLATILE_CASE(31, 3);
575 default:
576 break;
577 }
578 break;
579 case 4:
580 /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
581 switch (rd) {
582 ASM_VOLATILE_CASE(0, 4);
583 ASM_VOLATILE_CASE(1, 4);
584 ASM_VOLATILE_CASE(2, 4);
585 ASM_VOLATILE_CASE(3, 4);
586 ASM_VOLATILE_CASE(4, 4);
587 ASM_VOLATILE_CASE(5, 4);
588 ASM_VOLATILE_CASE(6, 4);
589 ASM_VOLATILE_CASE(7, 4);
590 ASM_VOLATILE_CASE(8, 4);
591 ASM_VOLATILE_CASE(9, 4);
592 ASM_VOLATILE_CASE(10, 4);
593 ASM_VOLATILE_CASE(11, 4);
594 ASM_VOLATILE_CASE(12, 4);
595 ASM_VOLATILE_CASE(13, 4);
596 ASM_VOLATILE_CASE(14, 4);
597 ASM_VOLATILE_CASE(15, 4);
598 ASM_VOLATILE_CASE(16, 4);
599 ASM_VOLATILE_CASE(17, 4);
600 ASM_VOLATILE_CASE(18, 4);
601 ASM_VOLATILE_CASE(19, 4);
602 ASM_VOLATILE_CASE(20, 4);
603 ASM_VOLATILE_CASE(21, 4);
604 ASM_VOLATILE_CASE(22, 4);
605 ASM_VOLATILE_CASE(23, 4);
606 ASM_VOLATILE_CASE(24, 4);
607 ASM_VOLATILE_CASE(25, 4);
608 ASM_VOLATILE_CASE(26, 4);
609 ASM_VOLATILE_CASE(27, 4);
610 ASM_VOLATILE_CASE(28, 4);
611 ASM_VOLATILE_CASE(29, 4);
612 ASM_VOLATILE_CASE(30, 4);
613 ASM_VOLATILE_CASE(31, 4);
614 default:
615 break;
616 }
617 break;
618 case 5:
619 /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
620 switch (rd) {
621 ASM_VOLATILE_CASE(0, 5);
622 ASM_VOLATILE_CASE(1, 5);
623 ASM_VOLATILE_CASE(2, 5);
624 ASM_VOLATILE_CASE(3, 5);
625 ASM_VOLATILE_CASE(4, 5);
626 ASM_VOLATILE_CASE(5, 5);
627 ASM_VOLATILE_CASE(6, 5);
628 ASM_VOLATILE_CASE(7, 5);
629 ASM_VOLATILE_CASE(8, 5);
630 ASM_VOLATILE_CASE(9, 5);
631 ASM_VOLATILE_CASE(10, 5);
632 ASM_VOLATILE_CASE(11, 5);
633 ASM_VOLATILE_CASE(12, 5);
634 ASM_VOLATILE_CASE(13, 5);
635 ASM_VOLATILE_CASE(14, 5);
636 ASM_VOLATILE_CASE(15, 5);
637 ASM_VOLATILE_CASE(16, 5);
638 ASM_VOLATILE_CASE(17, 5);
639 ASM_VOLATILE_CASE(18, 5);
640 ASM_VOLATILE_CASE(19, 5);
641 ASM_VOLATILE_CASE(20, 5);
642 ASM_VOLATILE_CASE(21, 5);
643 ASM_VOLATILE_CASE(22, 5);
644 ASM_VOLATILE_CASE(23, 5);
645 ASM_VOLATILE_CASE(24, 5);
646 ASM_VOLATILE_CASE(25, 5);
647 ASM_VOLATILE_CASE(26, 5);
648 ASM_VOLATILE_CASE(27, 5);
649 ASM_VOLATILE_CASE(28, 5);
650 ASM_VOLATILE_CASE(29, 5);
651 ASM_VOLATILE_CASE(30, 5);
652 ASM_VOLATILE_CASE(31, 5);
653 default:
654 break;
655 }
656 break;
657 case 6:
658 /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
659 switch (rd) {
660 ASM_VOLATILE_CASE(0, 6);
661 ASM_VOLATILE_CASE(1, 6);
662 ASM_VOLATILE_CASE(2, 6);
663 ASM_VOLATILE_CASE(3, 6);
664 ASM_VOLATILE_CASE(4, 6);
665 ASM_VOLATILE_CASE(5, 6);
666 ASM_VOLATILE_CASE(6, 6);
667 ASM_VOLATILE_CASE(7, 6);
668 ASM_VOLATILE_CASE(8, 6);
669 ASM_VOLATILE_CASE(9, 6);
670 ASM_VOLATILE_CASE(10, 6);
671 ASM_VOLATILE_CASE(11, 6);
672 ASM_VOLATILE_CASE(12, 6);
673 ASM_VOLATILE_CASE(13, 6);
674 ASM_VOLATILE_CASE(14, 6);
675 ASM_VOLATILE_CASE(15, 6);
676 ASM_VOLATILE_CASE(16, 6);
677 ASM_VOLATILE_CASE(17, 6);
678 ASM_VOLATILE_CASE(18, 6);
679 ASM_VOLATILE_CASE(19, 6);
680 ASM_VOLATILE_CASE(20, 6);
681 ASM_VOLATILE_CASE(21, 6);
682 ASM_VOLATILE_CASE(22, 6);
683 ASM_VOLATILE_CASE(23, 6);
684 ASM_VOLATILE_CASE(24, 6);
685 ASM_VOLATILE_CASE(25, 6);
686 ASM_VOLATILE_CASE(26, 6);
687 ASM_VOLATILE_CASE(27, 6);
688 ASM_VOLATILE_CASE(28, 6);
689 ASM_VOLATILE_CASE(29, 6);
690 ASM_VOLATILE_CASE(30, 6);
691 ASM_VOLATILE_CASE(31, 6);
692 default:
693 break;
694 }
695 break;
696 case 7:
697 /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
698 switch (rd) {
699 ASM_VOLATILE_CASE(0, 7);
700 ASM_VOLATILE_CASE(1, 7);
701 ASM_VOLATILE_CASE(2, 7);
702 ASM_VOLATILE_CASE(3, 7);
703 ASM_VOLATILE_CASE(4, 7);
704 ASM_VOLATILE_CASE(5, 7);
705 ASM_VOLATILE_CASE(6, 7);
706 ASM_VOLATILE_CASE(7, 7);
707 ASM_VOLATILE_CASE(8, 7);
708 ASM_VOLATILE_CASE(9, 7);
709 ASM_VOLATILE_CASE(10, 7);
710 ASM_VOLATILE_CASE(11, 7);
711 ASM_VOLATILE_CASE(12, 7);
712 ASM_VOLATILE_CASE(13, 7);
713 ASM_VOLATILE_CASE(14, 7);
714 ASM_VOLATILE_CASE(15, 7);
715 ASM_VOLATILE_CASE(16, 7);
716 ASM_VOLATILE_CASE(17, 7);
717 ASM_VOLATILE_CASE(18, 7);
718 ASM_VOLATILE_CASE(19, 7);
719 ASM_VOLATILE_CASE(20, 7);
720 ASM_VOLATILE_CASE(21, 7);
721 ASM_VOLATILE_CASE(22, 7);
722 ASM_VOLATILE_CASE(23, 7);
723 ASM_VOLATILE_CASE(24, 7);
724 ASM_VOLATILE_CASE(25, 7);
725 ASM_VOLATILE_CASE(26, 7);
726 ASM_VOLATILE_CASE(27, 7);
727 ASM_VOLATILE_CASE(28, 7);
728 ASM_VOLATILE_CASE(29, 7);
729 ASM_VOLATILE_CASE(30, 7);
730 ASM_VOLATILE_CASE(31, 7);
731 default:
732 break;
733 }
734 break;
735
736 default:
737 break;
738 }
739 #endif
740 return x;
741 }
742
743 #undef ASM_VOLATILE_CASE
744
745 #define ASM_VOLATILE_CASE(rd, sel) \
746 case rd: \
747 asm volatile ("dmfc0 %0, $" #rd ", "#sel"\n\t" :"=r" (x) ); \
748 break;
749
mips64_dirtyhelper_dmfc0(UInt rd,UInt sel)750 ULong mips64_dirtyhelper_dmfc0 ( UInt rd, UInt sel )
751 {
752 ULong x = 0;
753 #if defined(VGP_mips64_linux)
754 switch (sel) {
755 case 0:
756 /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
757 switch (rd) {
758 ASM_VOLATILE_CASE (0, 0);
759 ASM_VOLATILE_CASE (1, 0);
760 ASM_VOLATILE_CASE (2, 0);
761 ASM_VOLATILE_CASE (3, 0);
762 ASM_VOLATILE_CASE (4, 0);
763 ASM_VOLATILE_CASE (5, 0);
764 ASM_VOLATILE_CASE (6, 0);
765 ASM_VOLATILE_CASE (7, 0);
766 ASM_VOLATILE_CASE (8, 0);
767 ASM_VOLATILE_CASE (9, 0);
768 ASM_VOLATILE_CASE (10, 0);
769 ASM_VOLATILE_CASE (11, 0);
770 ASM_VOLATILE_CASE (12, 0);
771 ASM_VOLATILE_CASE (13, 0);
772 ASM_VOLATILE_CASE (14, 0);
773 ASM_VOLATILE_CASE (15, 0);
774 ASM_VOLATILE_CASE (16, 0);
775 ASM_VOLATILE_CASE (17, 0);
776 ASM_VOLATILE_CASE (18, 0);
777 ASM_VOLATILE_CASE (19, 0);
778 ASM_VOLATILE_CASE (20, 0);
779 ASM_VOLATILE_CASE (21, 0);
780 ASM_VOLATILE_CASE (22, 0);
781 ASM_VOLATILE_CASE (23, 0);
782 ASM_VOLATILE_CASE (24, 0);
783 ASM_VOLATILE_CASE (25, 0);
784 ASM_VOLATILE_CASE (26, 0);
785 ASM_VOLATILE_CASE (27, 0);
786 ASM_VOLATILE_CASE (28, 0);
787 ASM_VOLATILE_CASE (29, 0);
788 ASM_VOLATILE_CASE (30, 0);
789 ASM_VOLATILE_CASE (31, 0);
790 default:
791 break;
792 }
793 break;
794 case 1:
795 /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
796 switch (rd) {
797 ASM_VOLATILE_CASE (0, 1);
798 ASM_VOLATILE_CASE (1, 1);
799 ASM_VOLATILE_CASE (2, 1);
800 ASM_VOLATILE_CASE (3, 1);
801 ASM_VOLATILE_CASE (4, 1);
802 ASM_VOLATILE_CASE (5, 1);
803 ASM_VOLATILE_CASE (6, 1);
804 ASM_VOLATILE_CASE (7, 1);
805 ASM_VOLATILE_CASE (8, 1);
806 ASM_VOLATILE_CASE (9, 1);
807 ASM_VOLATILE_CASE (10, 1);
808 ASM_VOLATILE_CASE (11, 1);
809 ASM_VOLATILE_CASE (12, 1);
810 ASM_VOLATILE_CASE (13, 1);
811 ASM_VOLATILE_CASE (14, 1);
812 ASM_VOLATILE_CASE (15, 1);
813 ASM_VOLATILE_CASE (16, 1);
814 ASM_VOLATILE_CASE (17, 1);
815 ASM_VOLATILE_CASE (18, 1);
816 ASM_VOLATILE_CASE (19, 1);
817 ASM_VOLATILE_CASE (20, 1);
818 ASM_VOLATILE_CASE (21, 1);
819 ASM_VOLATILE_CASE (22, 1);
820 ASM_VOLATILE_CASE (23, 1);
821 ASM_VOLATILE_CASE (24, 1);
822 ASM_VOLATILE_CASE (25, 1);
823 ASM_VOLATILE_CASE (26, 1);
824 ASM_VOLATILE_CASE (27, 1);
825 ASM_VOLATILE_CASE (28, 1);
826 ASM_VOLATILE_CASE (29, 1);
827 ASM_VOLATILE_CASE (30, 1);
828 ASM_VOLATILE_CASE (31, 1);
829 default:
830 break;
831 }
832 break;
833 case 2:
834 /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
835 switch (rd) {
836 ASM_VOLATILE_CASE (0, 2);
837 ASM_VOLATILE_CASE (1, 2);
838 ASM_VOLATILE_CASE (2, 2);
839 ASM_VOLATILE_CASE (3, 1);
840 ASM_VOLATILE_CASE (4, 2);
841 ASM_VOLATILE_CASE (5, 2);
842 ASM_VOLATILE_CASE (6, 2);
843 ASM_VOLATILE_CASE (7, 2);
844 ASM_VOLATILE_CASE (8, 2);
845 ASM_VOLATILE_CASE (9, 2);
846 ASM_VOLATILE_CASE (10, 2);
847 ASM_VOLATILE_CASE (11, 2);
848 ASM_VOLATILE_CASE (12, 2);
849 ASM_VOLATILE_CASE (13, 2);
850 ASM_VOLATILE_CASE (14, 2);
851 ASM_VOLATILE_CASE (15, 2);
852 ASM_VOLATILE_CASE (16, 2);
853 ASM_VOLATILE_CASE (17, 2);
854 ASM_VOLATILE_CASE (18, 2);
855 ASM_VOLATILE_CASE (19, 2);
856 ASM_VOLATILE_CASE (20, 2);
857 ASM_VOLATILE_CASE (21, 2);
858 ASM_VOLATILE_CASE (22, 2);
859 ASM_VOLATILE_CASE (23, 2);
860 ASM_VOLATILE_CASE (24, 2);
861 ASM_VOLATILE_CASE (25, 2);
862 ASM_VOLATILE_CASE (26, 2);
863 ASM_VOLATILE_CASE (27, 2);
864 ASM_VOLATILE_CASE (28, 2);
865 ASM_VOLATILE_CASE (29, 2);
866 ASM_VOLATILE_CASE (30, 2);
867 ASM_VOLATILE_CASE (31, 2);
868 default:
869 break;
870 }
871 break;
872 case 3:
873 /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
874 switch (rd) {
875 ASM_VOLATILE_CASE (0, 3);
876 ASM_VOLATILE_CASE (1, 3);
877 ASM_VOLATILE_CASE (2, 3);
878 ASM_VOLATILE_CASE (3, 3);
879 ASM_VOLATILE_CASE (4, 3);
880 ASM_VOLATILE_CASE (5, 3);
881 ASM_VOLATILE_CASE (6, 3);
882 ASM_VOLATILE_CASE (7, 3);
883 ASM_VOLATILE_CASE (8, 3);
884 ASM_VOLATILE_CASE (9, 3);
885 ASM_VOLATILE_CASE (10, 3);
886 ASM_VOLATILE_CASE (11, 3);
887 ASM_VOLATILE_CASE (12, 3);
888 ASM_VOLATILE_CASE (13, 3);
889 ASM_VOLATILE_CASE (14, 3);
890 ASM_VOLATILE_CASE (15, 3);
891 ASM_VOLATILE_CASE (16, 3);
892 ASM_VOLATILE_CASE (17, 3);
893 ASM_VOLATILE_CASE (18, 3);
894 ASM_VOLATILE_CASE (19, 3);
895 ASM_VOLATILE_CASE (20, 3);
896 ASM_VOLATILE_CASE (21, 3);
897 ASM_VOLATILE_CASE (22, 3);
898 ASM_VOLATILE_CASE (23, 3);
899 ASM_VOLATILE_CASE (24, 3);
900 ASM_VOLATILE_CASE (25, 3);
901 ASM_VOLATILE_CASE (26, 3);
902 ASM_VOLATILE_CASE (27, 3);
903 ASM_VOLATILE_CASE (28, 3);
904 ASM_VOLATILE_CASE (29, 3);
905 ASM_VOLATILE_CASE (30, 3);
906 ASM_VOLATILE_CASE (31, 3);
907 default:
908 break;
909 }
910 break;
911 case 4:
912 /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
913 switch (rd) {
914 ASM_VOLATILE_CASE (0, 4);
915 ASM_VOLATILE_CASE (1, 4);
916 ASM_VOLATILE_CASE (2, 4);
917 ASM_VOLATILE_CASE (3, 4);
918 ASM_VOLATILE_CASE (4, 4);
919 ASM_VOLATILE_CASE (5, 4);
920 ASM_VOLATILE_CASE (6, 4);
921 ASM_VOLATILE_CASE (7, 4);
922 ASM_VOLATILE_CASE (8, 4);
923 ASM_VOLATILE_CASE (9, 4);
924 ASM_VOLATILE_CASE (10, 4);
925 ASM_VOLATILE_CASE (11, 4);
926 ASM_VOLATILE_CASE (12, 4);
927 ASM_VOLATILE_CASE (13, 4);
928 ASM_VOLATILE_CASE (14, 4);
929 ASM_VOLATILE_CASE (15, 4);
930 ASM_VOLATILE_CASE (16, 4);
931 ASM_VOLATILE_CASE (17, 4);
932 ASM_VOLATILE_CASE (18, 4);
933 ASM_VOLATILE_CASE (19, 4);
934 ASM_VOLATILE_CASE (20, 4);
935 ASM_VOLATILE_CASE (21, 4);
936 ASM_VOLATILE_CASE (22, 4);
937 ASM_VOLATILE_CASE (23, 4);
938 ASM_VOLATILE_CASE (24, 4);
939 ASM_VOLATILE_CASE (25, 4);
940 ASM_VOLATILE_CASE (26, 4);
941 ASM_VOLATILE_CASE (27, 4);
942 ASM_VOLATILE_CASE (28, 4);
943 ASM_VOLATILE_CASE (29, 4);
944 ASM_VOLATILE_CASE (30, 4);
945 ASM_VOLATILE_CASE (31, 4);
946 default:
947 break;
948 }
949 break;
950 case 5:
951 /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
952 switch (rd) {
953 ASM_VOLATILE_CASE (0, 5);
954 ASM_VOLATILE_CASE (1, 5);
955 ASM_VOLATILE_CASE (2, 5);
956 ASM_VOLATILE_CASE (3, 5);
957 ASM_VOLATILE_CASE (4, 5);
958 ASM_VOLATILE_CASE (5, 5);
959 ASM_VOLATILE_CASE (6, 5);
960 ASM_VOLATILE_CASE (7, 5);
961 ASM_VOLATILE_CASE (8, 5);
962 ASM_VOLATILE_CASE (9, 5);
963 ASM_VOLATILE_CASE (10, 5);
964 ASM_VOLATILE_CASE (11, 5);
965 ASM_VOLATILE_CASE (12, 5);
966 ASM_VOLATILE_CASE (13, 5);
967 ASM_VOLATILE_CASE (14, 5);
968 ASM_VOLATILE_CASE (15, 5);
969 ASM_VOLATILE_CASE (16, 5);
970 ASM_VOLATILE_CASE (17, 5);
971 ASM_VOLATILE_CASE (18, 5);
972 ASM_VOLATILE_CASE (19, 5);
973 ASM_VOLATILE_CASE (20, 5);
974 ASM_VOLATILE_CASE (21, 5);
975 ASM_VOLATILE_CASE (22, 5);
976 ASM_VOLATILE_CASE (23, 5);
977 ASM_VOLATILE_CASE (24, 5);
978 ASM_VOLATILE_CASE (25, 5);
979 ASM_VOLATILE_CASE (26, 5);
980 ASM_VOLATILE_CASE (27, 5);
981 ASM_VOLATILE_CASE (28, 5);
982 ASM_VOLATILE_CASE (29, 5);
983 ASM_VOLATILE_CASE (30, 5);
984 ASM_VOLATILE_CASE (31, 5);
985 default:
986 break;
987 }
988 break;
989 case 6:
990 /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
991 switch (rd) {
992 ASM_VOLATILE_CASE (0, 6);
993 ASM_VOLATILE_CASE (1, 6);
994 ASM_VOLATILE_CASE (2, 6);
995 ASM_VOLATILE_CASE (3, 6);
996 ASM_VOLATILE_CASE (4, 6);
997 ASM_VOLATILE_CASE (5, 6);
998 ASM_VOLATILE_CASE (6, 6);
999 ASM_VOLATILE_CASE (7, 6);
1000 ASM_VOLATILE_CASE (8, 6);
1001 ASM_VOLATILE_CASE (9, 6);
1002 ASM_VOLATILE_CASE (10, 6);
1003 ASM_VOLATILE_CASE (11, 6);
1004 ASM_VOLATILE_CASE (12, 6);
1005 ASM_VOLATILE_CASE (13, 6);
1006 ASM_VOLATILE_CASE (14, 6);
1007 ASM_VOLATILE_CASE (15, 6);
1008 ASM_VOLATILE_CASE (16, 6);
1009 ASM_VOLATILE_CASE (17, 6);
1010 ASM_VOLATILE_CASE (18, 6);
1011 ASM_VOLATILE_CASE (19, 6);
1012 ASM_VOLATILE_CASE (20, 6);
1013 ASM_VOLATILE_CASE (21, 6);
1014 ASM_VOLATILE_CASE (22, 6);
1015 ASM_VOLATILE_CASE (23, 6);
1016 ASM_VOLATILE_CASE (24, 6);
1017 ASM_VOLATILE_CASE (25, 6);
1018 ASM_VOLATILE_CASE (26, 6);
1019 ASM_VOLATILE_CASE (27, 6);
1020 ASM_VOLATILE_CASE (28, 6);
1021 ASM_VOLATILE_CASE (29, 6);
1022 ASM_VOLATILE_CASE (30, 6);
1023 ASM_VOLATILE_CASE (31, 6);
1024 default:
1025 break;
1026 }
1027 break;
1028 case 7:
1029 /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
1030 switch (rd) {
1031 ASM_VOLATILE_CASE (0, 7);
1032 ASM_VOLATILE_CASE (1, 7);
1033 ASM_VOLATILE_CASE (2, 7);
1034 ASM_VOLATILE_CASE (3, 7);
1035 ASM_VOLATILE_CASE (4, 7);
1036 ASM_VOLATILE_CASE (5, 7);
1037 ASM_VOLATILE_CASE (6, 7);
1038 ASM_VOLATILE_CASE (7, 7);
1039 ASM_VOLATILE_CASE (8, 7);
1040 ASM_VOLATILE_CASE (9, 7);
1041 ASM_VOLATILE_CASE (10, 7);
1042 ASM_VOLATILE_CASE (11, 7);
1043 ASM_VOLATILE_CASE (12, 7);
1044 ASM_VOLATILE_CASE (13, 7);
1045 ASM_VOLATILE_CASE (14, 7);
1046 ASM_VOLATILE_CASE (15, 7);
1047 ASM_VOLATILE_CASE (16, 7);
1048 ASM_VOLATILE_CASE (17, 7);
1049 ASM_VOLATILE_CASE (18, 7);
1050 ASM_VOLATILE_CASE (19, 7);
1051 ASM_VOLATILE_CASE (20, 7);
1052 ASM_VOLATILE_CASE (21, 7);
1053 ASM_VOLATILE_CASE (22, 7);
1054 ASM_VOLATILE_CASE (23, 7);
1055 ASM_VOLATILE_CASE (24, 7);
1056 ASM_VOLATILE_CASE (25, 7);
1057 ASM_VOLATILE_CASE (26, 7);
1058 ASM_VOLATILE_CASE (27, 7);
1059 ASM_VOLATILE_CASE (28, 7);
1060 ASM_VOLATILE_CASE (29, 7);
1061 ASM_VOLATILE_CASE (30, 7);
1062 ASM_VOLATILE_CASE (31, 7);
1063 default:
1064 break;
1065 }
1066 break;
1067
1068 default:
1069 break;
1070 }
1071 #endif
1072 return x;
1073 }
1074
1075 #define ASM_VOLATILE_CASE(rd, sel) \
1076 case rd: asm volatile ("dmfc0 %0, $" #rd ", "#sel"\n\t" :"=r" (x) ); break;
1077
1078 #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
mips32_dirtyhelper_rdhwr(UInt rt,UInt rd)1079 UInt mips32_dirtyhelper_rdhwr ( UInt rt, UInt rd )
1080 {
1081 UInt x = 0;
1082 switch (rd) {
1083 case 1: /* x = SYNCI_StepSize() */
1084 __asm__ __volatile__("rdhwr %0, $1\n\t" : "=r" (x) );
1085 break;
1086
1087 default:
1088 vassert(0);
1089 break;
1090 }
1091 return x;
1092 }
1093
mips64_dirtyhelper_rdhwr(ULong rt,ULong rd)1094 ULong mips64_dirtyhelper_rdhwr ( ULong rt, ULong rd )
1095 {
1096 ULong x = 0;
1097 switch (rd) {
1098 case 1: /* x = SYNCI_StepSize() */
1099 __asm__ __volatile__("rdhwr %0, $1\n\t" : "=r" (x) );
1100 break;
1101
1102 default:
1103 vassert(0);
1104 break;
1105 }
1106 return x;
1107 }
1108 #endif
1109
1110 #define ASM_VOLATILE_UNARY32(inst) \
1111 __asm__ volatile("cfc1 $t0, $31" "\n\t" \
1112 "ctc1 %2, $31" "\n\t" \
1113 "mtc1 %1, $f20" "\n\t" \
1114 #inst" $f20, $f20" "\n\t" \
1115 "cfc1 %0, $31" "\n\t" \
1116 "ctc1 $t0, $31" "\n\t" \
1117 : "=r" (ret) \
1118 : "r" (loFsVal), "r" (fcsr) \
1119 : "t0", "$f20" \
1120 );
1121
1122 #define ASM_VOLATILE_UNARY32_DOUBLE(inst) \
1123 __asm__ volatile("cfc1 $t0, $31" "\n\t" \
1124 "ctc1 %3, $31" "\n\t" \
1125 "mtc1 %1, $f20" "\n\t" \
1126 "mtc1 %2, $f21" "\n\t" \
1127 #inst" $f20, $f20" "\n\t" \
1128 "cfc1 %0, $31" "\n\t" \
1129 "ctc1 $t0, $31" "\n\t" \
1130 : "=r" (ret) \
1131 : "r" (loFsVal), "r" (hiFsVal), "r" (fcsr) \
1132 : "t0", "$f20", "$f21" \
1133 );
1134
1135 #define ASM_VOLATILE_UNARY64(inst) \
1136 __asm__ volatile("cfc1 $t0, $31" "\n\t" \
1137 "ctc1 %2, $31" "\n\t" \
1138 "ldc1 $f24, 0(%1)" "\n\t" \
1139 #inst" $f24, $f24" "\n\t" \
1140 "cfc1 %0, $31" "\n\t" \
1141 "ctc1 $t0, $31" "\n\t" \
1142 : "=r" (ret) \
1143 : "r" (&(addr[fs])), "r" (fcsr) \
1144 : "t0", "$f24" \
1145 );
1146
1147 #define ASM_VOLATILE_BINARY32(inst) \
1148 __asm__ volatile("cfc1 $t0, $31" "\n\t" \
1149 "ctc1 %3, $31" "\n\t" \
1150 "mtc1 %1, $f20" "\n\t" \
1151 "mtc1 %2, $f22" "\n\t" \
1152 #inst" $f20, $f20, $f22" "\n\t" \
1153 "cfc1 %0, $31" "\n\t" \
1154 "ctc1 $t0, $31" "\n\t" \
1155 : "=r" (ret) \
1156 : "r" (loFsVal), "r" (loFtVal), "r" (fcsr) \
1157 : "t0", "$f20", "$f22" \
1158 );
1159
1160 #define ASM_VOLATILE_BINARY32_DOUBLE(inst) \
1161 __asm__ volatile("cfc1 $t0, $31" "\n\t" \
1162 "ctc1 %5, $31" "\n\t" \
1163 "mtc1 %1, $f20" "\n\t" \
1164 "mtc1 %2, $f21" "\n\t" \
1165 "mtc1 %3, $f22" "\n\t" \
1166 "mtc1 %4, $f23" "\n\t" \
1167 #inst" $f20, $f20, $f22" "\n\t" \
1168 "cfc1 %0, $31" "\n\t" \
1169 "ctc1 $t0, $31" "\n\t" \
1170 : "=r" (ret) \
1171 : "r" (loFsVal), "r" (hiFsVal), "r" (loFtVal), \
1172 "r" (hiFtVal), "r" (fcsr) \
1173 : "t0", "$f20", "$f21", "$f22", "$f23" \
1174 );
1175
1176 #define ASM_VOLATILE_BINARY64(inst) \
1177 __asm__ volatile("cfc1 $t0, $31" "\n\t" \
1178 "ctc1 %3, $31" "\n\t" \
1179 "ldc1 $f24, 0(%1)" "\n\t" \
1180 "ldc1 $f26, 0(%2)" "\n\t" \
1181 #inst" $f24, $f24, $f26" "\n\t" \
1182 "cfc1 %0, $31" "\n\t" \
1183 "ctc1 $t0, $31" "\n\t" \
1184 : "=r" (ret) \
1185 : "r" (&(addr[fs])), "r" (&(addr[ft])), "r" (fcsr) \
1186 : "t0", "$f24", "$f26" \
1187 );
1188
1189 /* TODO: Add cases for all fpu instructions because all fpu instructions are
1190 change the value of FCSR register. */
mips_dirtyhelper_calculate_FCSR_fp32(void * gs,UInt fs,UInt ft,flt_op inst)1191 extern UInt mips_dirtyhelper_calculate_FCSR_fp32 ( void* gs, UInt fs, UInt ft,
1192 flt_op inst )
1193 {
1194 UInt ret = 0;
1195 #if defined(__mips__)
1196 VexGuestMIPS32State* guest_state = (VexGuestMIPS32State*)gs;
1197 UInt loFsVal, hiFsVal, loFtVal, hiFtVal;
1198 #if defined (_MIPSEL)
1199 ULong *addr = (ULong *)&guest_state->guest_f0;
1200 loFsVal = (UInt)addr[fs];
1201 hiFsVal = (UInt)addr[fs+1];
1202 loFtVal = (UInt)addr[ft];
1203 hiFtVal = (UInt)addr[ft+1];
1204 #elif defined (_MIPSEB)
1205 UInt *addr = (UInt *)&guest_state->guest_f0;
1206 loFsVal = (UInt)addr[fs*2];
1207 hiFsVal = (UInt)addr[fs*2+2];
1208 loFtVal = (UInt)addr[ft*2];
1209 hiFtVal = (UInt)addr[ft*2+2];
1210 #endif
1211 UInt fcsr = guest_state->guest_FCSR;
1212 switch (inst) {
1213 case ROUNDWD:
1214 ASM_VOLATILE_UNARY32_DOUBLE(round.w.d)
1215 break;
1216 case FLOORWS:
1217 ASM_VOLATILE_UNARY32(floor.w.s)
1218 break;
1219 case FLOORWD:
1220 ASM_VOLATILE_UNARY32_DOUBLE(floor.w.d)
1221 break;
1222 case TRUNCWS:
1223 ASM_VOLATILE_UNARY32(trunc.w.s)
1224 break;
1225 case TRUNCWD:
1226 ASM_VOLATILE_UNARY32_DOUBLE(trunc.w.d)
1227 break;
1228 case CEILWS:
1229 ASM_VOLATILE_UNARY32(ceil.w.s)
1230 break;
1231 case CEILWD:
1232 ASM_VOLATILE_UNARY32_DOUBLE(ceil.w.d)
1233 break;
1234 case CVTDS:
1235 ASM_VOLATILE_UNARY32(cvt.d.s)
1236 break;
1237 case CVTDW:
1238 ASM_VOLATILE_UNARY32(cvt.d.w)
1239 break;
1240 case CVTSW:
1241 ASM_VOLATILE_UNARY32(cvt.s.w)
1242 break;
1243 case CVTSD:
1244 ASM_VOLATILE_UNARY32_DOUBLE(cvt.s.d)
1245 break;
1246 case CVTWS:
1247 ASM_VOLATILE_UNARY32(cvt.w.s)
1248 break;
1249 case CVTWD:
1250 ASM_VOLATILE_UNARY32_DOUBLE(cvt.w.d)
1251 break;
1252 case ROUNDWS:
1253 ASM_VOLATILE_UNARY32(round.w.s)
1254 break;
1255 #if ((__mips == 32) && defined(__mips_isa_rev) && (__mips_isa_rev >= 2)) \
1256 || (__mips == 64)
1257 case CEILLS:
1258 ASM_VOLATILE_UNARY32(ceil.l.s)
1259 break;
1260 case CEILLD:
1261 ASM_VOLATILE_UNARY32_DOUBLE(ceil.l.d)
1262 break;
1263 case CVTDL:
1264 ASM_VOLATILE_UNARY32_DOUBLE(cvt.d.l)
1265 break;
1266 case CVTLS:
1267 ASM_VOLATILE_UNARY32(cvt.l.s)
1268 break;
1269 case CVTLD:
1270 ASM_VOLATILE_UNARY32_DOUBLE(cvt.l.d)
1271 break;
1272 case CVTSL:
1273 ASM_VOLATILE_UNARY32_DOUBLE(cvt.s.l)
1274 break;
1275 case FLOORLS:
1276 ASM_VOLATILE_UNARY32(floor.l.s)
1277 break;
1278 case FLOORLD:
1279 ASM_VOLATILE_UNARY32_DOUBLE(floor.l.d)
1280 break;
1281 case ROUNDLS:
1282 ASM_VOLATILE_UNARY32(round.l.s)
1283 break;
1284 case ROUNDLD:
1285 ASM_VOLATILE_UNARY32_DOUBLE(round.l.d)
1286 break;
1287 case TRUNCLS:
1288 ASM_VOLATILE_UNARY32(trunc.l.s)
1289 break;
1290 case TRUNCLD:
1291 ASM_VOLATILE_UNARY32_DOUBLE(trunc.l.d)
1292 break;
1293 #endif
1294 case ADDS:
1295 ASM_VOLATILE_BINARY32(add.s)
1296 break;
1297 case ADDD:
1298 ASM_VOLATILE_BINARY32_DOUBLE(add.d)
1299 break;
1300 case SUBS:
1301 ASM_VOLATILE_BINARY32(sub.s)
1302 break;
1303 case SUBD:
1304 ASM_VOLATILE_BINARY32_DOUBLE(sub.d)
1305 break;
1306 case DIVS:
1307 ASM_VOLATILE_BINARY32(div.s)
1308 break;
1309 default:
1310 vassert(0);
1311 break;
1312 }
1313 #endif
1314 return ret;
1315 }
1316
1317 /* TODO: Add cases for all fpu instructions because all fpu instructions are
1318 change the value of FCSR register. */
mips_dirtyhelper_calculate_FCSR_fp64(void * gs,UInt fs,UInt ft,flt_op inst)1319 extern UInt mips_dirtyhelper_calculate_FCSR_fp64 ( void* gs, UInt fs, UInt ft,
1320 flt_op inst )
1321 {
1322 UInt ret = 0;
1323 #if defined(__mips__)
1324 #if defined(VGA_mips32)
1325 VexGuestMIPS32State* guest_state = (VexGuestMIPS32State*)gs;
1326 #else
1327 VexGuestMIPS64State* guest_state = (VexGuestMIPS64State*)gs;
1328 #endif
1329 ULong *addr = (ULong *)&guest_state->guest_f0;
1330 UInt fcsr = guest_state->guest_FCSR;
1331 switch (inst) {
1332 case ROUNDWD:
1333 ASM_VOLATILE_UNARY64(round.w.d)
1334 break;
1335 case FLOORWS:
1336 ASM_VOLATILE_UNARY64(floor.w.s)
1337 break;
1338 case FLOORWD:
1339 ASM_VOLATILE_UNARY64(floor.w.d)
1340 break;
1341 case TRUNCWS:
1342 ASM_VOLATILE_UNARY64(trunc.w.s)
1343 break;
1344 case TRUNCWD:
1345 ASM_VOLATILE_UNARY64(trunc.w.d)
1346 break;
1347 case CEILWS:
1348 ASM_VOLATILE_UNARY64(ceil.w.s)
1349 break;
1350 case CEILWD:
1351 ASM_VOLATILE_UNARY64(ceil.w.d)
1352 break;
1353 case CVTDS:
1354 ASM_VOLATILE_UNARY64(cvt.d.s)
1355 break;
1356 case CVTDW:
1357 ASM_VOLATILE_UNARY64(cvt.d.w)
1358 break;
1359 case CVTSW:
1360 ASM_VOLATILE_UNARY64(cvt.s.w)
1361 break;
1362 case CVTSD:
1363 ASM_VOLATILE_UNARY64(cvt.s.d)
1364 break;
1365 case CVTWS:
1366 ASM_VOLATILE_UNARY64(cvt.w.s)
1367 break;
1368 case CVTWD:
1369 ASM_VOLATILE_UNARY64(cvt.w.d)
1370 break;
1371 case ROUNDWS:
1372 ASM_VOLATILE_UNARY64(round.w.s)
1373 break;
1374 #if ((__mips == 32) && defined(__mips_isa_rev) && (__mips_isa_rev >= 2)) \
1375 || (__mips == 64)
1376 case CEILLS:
1377 ASM_VOLATILE_UNARY64(ceil.l.s)
1378 break;
1379 case CEILLD:
1380 ASM_VOLATILE_UNARY64(ceil.l.d)
1381 break;
1382 case CVTDL:
1383 ASM_VOLATILE_UNARY64(cvt.d.l)
1384 break;
1385 case CVTLS:
1386 ASM_VOLATILE_UNARY64(cvt.l.s)
1387 break;
1388 case CVTLD:
1389 ASM_VOLATILE_UNARY64(cvt.l.d)
1390 break;
1391 case CVTSL:
1392 ASM_VOLATILE_UNARY64(cvt.s.l)
1393 break;
1394 case FLOORLS:
1395 ASM_VOLATILE_UNARY64(floor.l.s)
1396 break;
1397 case FLOORLD:
1398 ASM_VOLATILE_UNARY64(floor.l.d)
1399 break;
1400 case ROUNDLS:
1401 ASM_VOLATILE_UNARY64(round.l.s)
1402 break;
1403 case ROUNDLD:
1404 ASM_VOLATILE_UNARY64(round.l.d)
1405 break;
1406 case TRUNCLS:
1407 ASM_VOLATILE_UNARY64(trunc.l.s)
1408 break;
1409 case TRUNCLD:
1410 ASM_VOLATILE_UNARY64(trunc.l.d)
1411 break;
1412 #endif
1413 case ADDS:
1414 ASM_VOLATILE_BINARY64(add.s)
1415 break;
1416 case ADDD:
1417 ASM_VOLATILE_BINARY64(add.d)
1418 break;
1419 case SUBS:
1420 ASM_VOLATILE_BINARY64(sub.s)
1421 break;
1422 case SUBD:
1423 ASM_VOLATILE_BINARY64(sub.d)
1424 break;
1425 case DIVS:
1426 ASM_VOLATILE_BINARY64(div.s)
1427 break;
1428 default:
1429 vassert(0);
1430 break;
1431 }
1432 #endif
1433 return ret;
1434 }
1435
1436 /*---------------------------------------------------------------*/
1437 /*--- end guest_mips_helpers.c ---*/
1438 /*---------------------------------------------------------------*/
1439