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-2012 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_emwarn.h"
33 #include "libvex_guest_mips32.h"
34 #include "libvex_ir.h"
35 #include "libvex.h"
36
37 #include "main_util.h"
38 #include "guest_generic_bb_to_IR.h"
39 #include "guest_mips_defs.h"
40
41 /* This file contains helper functions for mips guest code. Calls to
42 these functions are generated by the back end.
43 */
44
45 #define ALWAYSDEFD32(field) \
46 { offsetof(VexGuestMIPS32State, field), \
47 (sizeof ((VexGuestMIPS32State*)0)->field) }
48
guest_mips32_spechelper(HChar * function_name,IRExpr ** args,IRStmt ** precedingStmts,Int n_precedingStmts)49 IRExpr *guest_mips32_spechelper(HChar * function_name, IRExpr ** args,
50 IRStmt ** precedingStmts, Int n_precedingStmts)
51 {
52 return NULL;
53 }
54
55 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestMIPS32_initialise(VexGuestMIPS32State * vex_state)56 void LibVEX_GuestMIPS32_initialise( /*OUT*/ VexGuestMIPS32State * vex_state)
57 {
58 vex_state->guest_r0 = 0; /* Hardwired to 0 */
59 vex_state->guest_r1 = 0; /* Assembler temporary */
60 vex_state->guest_r2 = 0; /* Values for function returns ... */
61 vex_state->guest_r3 = 0; /* ...and expression evaluation */
62 vex_state->guest_r4 = 0; /* Function arguments */
63 vex_state->guest_r5 = 0;
64 vex_state->guest_r6 = 0;
65 vex_state->guest_r7 = 0;
66 vex_state->guest_r8 = 0; /* Temporaries */
67 vex_state->guest_r9 = 0;
68 vex_state->guest_r10 = 0;
69 vex_state->guest_r11 = 0;
70 vex_state->guest_r12 = 0;
71 vex_state->guest_r13 = 0;
72 vex_state->guest_r14 = 0;
73 vex_state->guest_r15 = 0;
74 vex_state->guest_r16 = 0; /* Saved temporaries */
75 vex_state->guest_r17 = 0;
76 vex_state->guest_r18 = 0;
77 vex_state->guest_r19 = 0;
78 vex_state->guest_r20 = 0;
79 vex_state->guest_r21 = 0;
80 vex_state->guest_r22 = 0;
81 vex_state->guest_r23 = 0;
82 vex_state->guest_r24 = 0; /* Temporaries */
83 vex_state->guest_r25 = 0;
84 vex_state->guest_r26 = 0; /* Reserved for OS kernel */
85 vex_state->guest_r27 = 0;
86 vex_state->guest_r28 = 0; /* Global pointer */
87 vex_state->guest_r29 = 0; /* Stack pointer */
88 vex_state->guest_r30 = 0; /* Frame pointer */
89 vex_state->guest_r31 = 0; /* Return address */
90 vex_state->guest_PC = 0; /* Program counter */
91 vex_state->guest_HI = 0; /* Multiply and divide register higher result */
92 vex_state->guest_LO = 0; /* Multiply and divide register lower result */
93
94 /* FPU Registers */
95 vex_state->guest_f0 = 0x7ff80000; /* Floting point general purpose registers */
96 vex_state->guest_f1 = 0x7ff80000;
97 vex_state->guest_f2 = 0x7ff80000;
98 vex_state->guest_f3 = 0x7ff80000;
99 vex_state->guest_f4 = 0x7ff80000;
100 vex_state->guest_f5 = 0x7ff80000;
101 vex_state->guest_f6 = 0x7ff80000;
102 vex_state->guest_f7 = 0x7ff80000;
103 vex_state->guest_f8 = 0x7ff80000;
104 vex_state->guest_f9 = 0x7ff80000;
105 vex_state->guest_f10 = 0x7ff80000;
106 vex_state->guest_f11 = 0x7ff80000;
107 vex_state->guest_f12 = 0x7ff80000;
108 vex_state->guest_f13 = 0x7ff80000;
109 vex_state->guest_f14 = 0x7ff80000;
110 vex_state->guest_f15 = 0x7ff80000;
111 vex_state->guest_f16 = 0x7ff80000;
112 vex_state->guest_f17 = 0x7ff80000;
113 vex_state->guest_f18 = 0x7ff80000;
114 vex_state->guest_f19 = 0x7ff80000;
115 vex_state->guest_f20 = 0x7ff80000;
116 vex_state->guest_f21 = 0x7ff80000;
117 vex_state->guest_f22 = 0x7ff80000;
118 vex_state->guest_f23 = 0x7ff80000;
119 vex_state->guest_f24 = 0x7ff80000;
120 vex_state->guest_f25 = 0x7ff80000;
121 vex_state->guest_f26 = 0x7ff80000;
122 vex_state->guest_f27 = 0x7ff80000;
123 vex_state->guest_f28 = 0x7ff80000;
124 vex_state->guest_f29 = 0x7ff80000;
125 vex_state->guest_f30 = 0x7ff80000;
126 vex_state->guest_f31 = 0x7ff80000;
127
128 vex_state->guest_FIR = 0; /* FP implementation and revision register */
129 vex_state->guest_FCCR = 0; /* FP condition codes register */
130 vex_state->guest_FEXR = 0; /* FP exceptions register */
131 vex_state->guest_FENR = 0; /* FP enables register */
132 vex_state->guest_FCSR = 0; /* FP control/status register */
133 vex_state->guest_ULR = 0; /* TLS */
134
135 /* Various pseudo-regs mandated by Vex or Valgrind. */
136 /* Emulation warnings */
137 vex_state->guest_EMWARN = 0;
138
139 /* For clflush: record start and length of area to invalidate */
140 vex_state->guest_TISTART = 0;
141 vex_state->guest_TILEN = 0;
142 vex_state->host_EvC_COUNTER = 0;
143 vex_state->host_EvC_FAILADDR = 0;
144
145 /* Used to record the unredirected guest address at the start of
146 a translation whose start has been redirected. By reading
147 this pseudo-register shortly afterwards, the translation can
148 find out what the corresponding no-redirection address was.
149 Note, this is only set for wrap-style redirects, not for
150 replace-style ones. */
151 vex_state->guest_NRADDR = 0;
152
153 vex_state->guest_COND = 0;
154 }
155
156 /*-----------------------------------------------------------*/
157 /*--- Describing the mips guest state, for the benefit ---*/
158 /*--- of iropt and instrumenters. ---*/
159 /*-----------------------------------------------------------*/
160
161 /* Figure out if any part of the guest state contained in minoff
162 .. maxoff requires precise memory exceptions. If in doubt return
163 True (but this is generates significantly slower code).
164
165 We enforce precise exns for guest SP, PC.
166 */
guest_mips32_state_requires_precise_mem_exns(Int minoff,Int maxoff)167 Bool guest_mips32_state_requires_precise_mem_exns(Int minoff, Int maxoff)
168 {
169 Int sp_min = offsetof(VexGuestMIPS32State, guest_r29);
170 Int sp_max = sp_min + 4 - 1;
171 Int pc_min = offsetof(VexGuestMIPS32State, guest_PC);
172 Int pc_max = pc_min + 4 - 1;
173
174 if (maxoff < sp_min || minoff > sp_max) {
175 /* no overlap with sp */
176 } else {
177 return True;
178 }
179
180 if (maxoff < pc_min || minoff > pc_max) {
181 /* no overlap with pc */
182 } else {
183 return True;
184 }
185
186 /* We appear to need precise updates of R11 in order to get proper
187 stacktraces from non-optimised code. */
188 Int fp_min = offsetof(VexGuestMIPS32State, guest_r30);
189 Int fp_max = fp_min + 4 - 1;
190
191 if (maxoff < fp_min || minoff > fp_max) {
192 /* no overlap with fp */
193 } else {
194 return True;
195 }
196
197 return False;
198 }
199
200 VexGuestLayout mips32Guest_layout = {
201 /* Total size of the guest state, in bytes. */
202 .total_sizeB = sizeof(VexGuestMIPS32State),
203 /* Describe the stack pointer. */
204 .offset_SP = offsetof(VexGuestMIPS32State, guest_r29),
205 .sizeof_SP = 4,
206 /* Describe the frame pointer. */
207 .offset_FP = offsetof(VexGuestMIPS32State, guest_r30),
208 .sizeof_FP = 4,
209 /* Describe the instruction pointer. */
210 .offset_IP = offsetof(VexGuestMIPS32State, guest_PC),
211 .sizeof_IP = 4,
212 /* Describe any sections to be regarded by Memcheck as
213 'always-defined'. */
214 .n_alwaysDefd = 8,
215 /* ? :( */
216 .alwaysDefd = {
217 /* 0 */ ALWAYSDEFD32(guest_r0),
218 /* 1 */ ALWAYSDEFD32(guest_r1),
219 /* 2 */ ALWAYSDEFD32(guest_EMWARN),
220 /* 3 */ ALWAYSDEFD32(guest_TISTART),
221 /* 4 */ ALWAYSDEFD32(guest_TILEN),
222 /* 5 */ ALWAYSDEFD32(guest_r29),
223 /* 6 */ ALWAYSDEFD32(guest_r31),
224 /* 7 */ ALWAYSDEFD32(guest_ULR)
225 }
226 };
227
228 #define ASM_VOLATILE_CASE(rd, sel) \
229 case rd: asm volatile ("mfc0 %0, $" #rd ", "#sel"\n\t" :"=r" (x) ); break;
230
mips32_dirtyhelper_mfc0(UInt rd,UInt sel)231 UInt mips32_dirtyhelper_mfc0(UInt rd, UInt sel)
232 {
233 UInt x = 0;
234 #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
235 switch (sel) {
236 case 0:
237 //__asm__("mfc0 %0, $1, 0" :"=r" (x));
238 switch (rd) {
239 ASM_VOLATILE_CASE(0, 0);
240 ASM_VOLATILE_CASE(1, 0);
241 ASM_VOLATILE_CASE(2, 0);
242 ASM_VOLATILE_CASE(3, 0);
243 ASM_VOLATILE_CASE(4, 0);
244 ASM_VOLATILE_CASE(5, 0);
245 ASM_VOLATILE_CASE(6, 0);
246 ASM_VOLATILE_CASE(7, 0);
247 ASM_VOLATILE_CASE(8, 0);
248 ASM_VOLATILE_CASE(9, 0);
249 ASM_VOLATILE_CASE(10, 0);
250 ASM_VOLATILE_CASE(11, 0);
251 ASM_VOLATILE_CASE(12, 0);
252 ASM_VOLATILE_CASE(13, 0);
253 ASM_VOLATILE_CASE(14, 0);
254 ASM_VOLATILE_CASE(15, 0);
255 ASM_VOLATILE_CASE(16, 0);
256 ASM_VOLATILE_CASE(17, 0);
257 ASM_VOLATILE_CASE(18, 0);
258 ASM_VOLATILE_CASE(19, 0);
259 ASM_VOLATILE_CASE(20, 0);
260 ASM_VOLATILE_CASE(21, 0);
261 ASM_VOLATILE_CASE(22, 0);
262 ASM_VOLATILE_CASE(23, 0);
263 ASM_VOLATILE_CASE(24, 0);
264 ASM_VOLATILE_CASE(25, 0);
265 ASM_VOLATILE_CASE(26, 0);
266 ASM_VOLATILE_CASE(27, 0);
267 ASM_VOLATILE_CASE(28, 0);
268 ASM_VOLATILE_CASE(29, 0);
269 ASM_VOLATILE_CASE(30, 0);
270 ASM_VOLATILE_CASE(31, 0);
271 default:
272 break;
273 }
274 break;
275 case 1:
276 //__asm__("mfc0 %0, $1, 0" :"=r" (x));
277 switch (rd) {
278 ASM_VOLATILE_CASE(0, 1);
279 ASM_VOLATILE_CASE(1, 1);
280 ASM_VOLATILE_CASE(2, 1);
281 ASM_VOLATILE_CASE(3, 1);
282 ASM_VOLATILE_CASE(4, 1);
283 ASM_VOLATILE_CASE(5, 1);
284 ASM_VOLATILE_CASE(6, 1);
285 ASM_VOLATILE_CASE(7, 1);
286 ASM_VOLATILE_CASE(8, 1);
287 ASM_VOLATILE_CASE(9, 1);
288 ASM_VOLATILE_CASE(10, 1);
289 ASM_VOLATILE_CASE(11, 1);
290 ASM_VOLATILE_CASE(12, 1);
291 ASM_VOLATILE_CASE(13, 1);
292 ASM_VOLATILE_CASE(14, 1);
293 ASM_VOLATILE_CASE(15, 1);
294 ASM_VOLATILE_CASE(16, 1);
295 ASM_VOLATILE_CASE(17, 1);
296 ASM_VOLATILE_CASE(18, 1);
297 ASM_VOLATILE_CASE(19, 1);
298 ASM_VOLATILE_CASE(20, 1);
299 ASM_VOLATILE_CASE(21, 1);
300 ASM_VOLATILE_CASE(22, 1);
301 ASM_VOLATILE_CASE(23, 1);
302 ASM_VOLATILE_CASE(24, 1);
303 ASM_VOLATILE_CASE(25, 1);
304 ASM_VOLATILE_CASE(26, 1);
305 ASM_VOLATILE_CASE(27, 1);
306 ASM_VOLATILE_CASE(28, 1);
307 ASM_VOLATILE_CASE(29, 1);
308 ASM_VOLATILE_CASE(30, 1);
309 ASM_VOLATILE_CASE(31, 1);
310 default:
311 break;
312 }
313 break;
314 case 2:
315 //__asm__("mfc0 %0, $1, 0" :"=r" (x));
316 switch (rd) {
317 ASM_VOLATILE_CASE(0, 2);
318 ASM_VOLATILE_CASE(1, 2);
319 ASM_VOLATILE_CASE(2, 2);
320 ASM_VOLATILE_CASE(3, 1);
321 ASM_VOLATILE_CASE(4, 2);
322 ASM_VOLATILE_CASE(5, 2);
323 ASM_VOLATILE_CASE(6, 2);
324 ASM_VOLATILE_CASE(7, 2);
325 ASM_VOLATILE_CASE(8, 2);
326 ASM_VOLATILE_CASE(9, 2);
327 ASM_VOLATILE_CASE(10, 2);
328 ASM_VOLATILE_CASE(11, 2);
329 ASM_VOLATILE_CASE(12, 2);
330 ASM_VOLATILE_CASE(13, 2);
331 ASM_VOLATILE_CASE(14, 2);
332 ASM_VOLATILE_CASE(15, 2);
333 ASM_VOLATILE_CASE(16, 2);
334 ASM_VOLATILE_CASE(17, 2);
335 ASM_VOLATILE_CASE(18, 2);
336 ASM_VOLATILE_CASE(19, 2);
337 ASM_VOLATILE_CASE(20, 2);
338 ASM_VOLATILE_CASE(21, 2);
339 ASM_VOLATILE_CASE(22, 2);
340 ASM_VOLATILE_CASE(23, 2);
341 ASM_VOLATILE_CASE(24, 2);
342 ASM_VOLATILE_CASE(25, 2);
343 ASM_VOLATILE_CASE(26, 2);
344 ASM_VOLATILE_CASE(27, 2);
345 ASM_VOLATILE_CASE(28, 2);
346 ASM_VOLATILE_CASE(29, 2);
347 ASM_VOLATILE_CASE(30, 2);
348 ASM_VOLATILE_CASE(31, 2);
349 default:
350 break;
351 }
352 break;
353 case 3:
354 //__asm__("mfc0 %0, $1, 0" :"=r" (x));
355 switch (rd) {
356 ASM_VOLATILE_CASE(0, 3);
357 ASM_VOLATILE_CASE(1, 3);
358 ASM_VOLATILE_CASE(2, 3);
359 ASM_VOLATILE_CASE(3, 3);
360 ASM_VOLATILE_CASE(4, 3);
361 ASM_VOLATILE_CASE(5, 3);
362 ASM_VOLATILE_CASE(6, 3);
363 ASM_VOLATILE_CASE(7, 3);
364 ASM_VOLATILE_CASE(8, 3);
365 ASM_VOLATILE_CASE(9, 3);
366 ASM_VOLATILE_CASE(10, 3);
367 ASM_VOLATILE_CASE(11, 3);
368 ASM_VOLATILE_CASE(12, 3);
369 ASM_VOLATILE_CASE(13, 3);
370 ASM_VOLATILE_CASE(14, 3);
371 ASM_VOLATILE_CASE(15, 3);
372 ASM_VOLATILE_CASE(16, 3);
373 ASM_VOLATILE_CASE(17, 3);
374 ASM_VOLATILE_CASE(18, 3);
375 ASM_VOLATILE_CASE(19, 3);
376 ASM_VOLATILE_CASE(20, 3);
377 ASM_VOLATILE_CASE(21, 3);
378 ASM_VOLATILE_CASE(22, 3);
379 ASM_VOLATILE_CASE(23, 3);
380 ASM_VOLATILE_CASE(24, 3);
381 ASM_VOLATILE_CASE(25, 3);
382 ASM_VOLATILE_CASE(26, 3);
383 ASM_VOLATILE_CASE(27, 3);
384 ASM_VOLATILE_CASE(28, 3);
385 ASM_VOLATILE_CASE(29, 3);
386 ASM_VOLATILE_CASE(30, 3);
387 ASM_VOLATILE_CASE(31, 3);
388 default:
389 break;
390 }
391 break;
392 case 4:
393 //__asm__("mfc0 %0, $1, 0" :"=r" (x));
394 switch (rd) {
395 ASM_VOLATILE_CASE(0, 4);
396 ASM_VOLATILE_CASE(1, 4);
397 ASM_VOLATILE_CASE(2, 4);
398 ASM_VOLATILE_CASE(3, 4);
399 ASM_VOLATILE_CASE(4, 4);
400 ASM_VOLATILE_CASE(5, 4);
401 ASM_VOLATILE_CASE(6, 4);
402 ASM_VOLATILE_CASE(7, 4);
403 ASM_VOLATILE_CASE(8, 4);
404 ASM_VOLATILE_CASE(9, 4);
405 ASM_VOLATILE_CASE(10, 4);
406 ASM_VOLATILE_CASE(11, 4);
407 ASM_VOLATILE_CASE(12, 4);
408 ASM_VOLATILE_CASE(13, 4);
409 ASM_VOLATILE_CASE(14, 4);
410 ASM_VOLATILE_CASE(15, 4);
411 ASM_VOLATILE_CASE(16, 4);
412 ASM_VOLATILE_CASE(17, 4);
413 ASM_VOLATILE_CASE(18, 4);
414 ASM_VOLATILE_CASE(19, 4);
415 ASM_VOLATILE_CASE(20, 4);
416 ASM_VOLATILE_CASE(21, 4);
417 ASM_VOLATILE_CASE(22, 4);
418 ASM_VOLATILE_CASE(23, 4);
419 ASM_VOLATILE_CASE(24, 4);
420 ASM_VOLATILE_CASE(25, 4);
421 ASM_VOLATILE_CASE(26, 4);
422 ASM_VOLATILE_CASE(27, 4);
423 ASM_VOLATILE_CASE(28, 4);
424 ASM_VOLATILE_CASE(29, 4);
425 ASM_VOLATILE_CASE(30, 4);
426 ASM_VOLATILE_CASE(31, 4);
427 default:
428 break;
429 }
430 break;
431 case 5:
432 //__asm__("mfc0 %0, $1, 0" :"=r" (x));
433 switch (rd) {
434 ASM_VOLATILE_CASE(0, 5);
435 ASM_VOLATILE_CASE(1, 5);
436 ASM_VOLATILE_CASE(2, 5);
437 ASM_VOLATILE_CASE(3, 5);
438 ASM_VOLATILE_CASE(4, 5);
439 ASM_VOLATILE_CASE(5, 5);
440 ASM_VOLATILE_CASE(6, 5);
441 ASM_VOLATILE_CASE(7, 5);
442 ASM_VOLATILE_CASE(8, 5);
443 ASM_VOLATILE_CASE(9, 5);
444 ASM_VOLATILE_CASE(10, 5);
445 ASM_VOLATILE_CASE(11, 5);
446 ASM_VOLATILE_CASE(12, 5);
447 ASM_VOLATILE_CASE(13, 5);
448 ASM_VOLATILE_CASE(14, 5);
449 ASM_VOLATILE_CASE(15, 5);
450 ASM_VOLATILE_CASE(16, 5);
451 ASM_VOLATILE_CASE(17, 5);
452 ASM_VOLATILE_CASE(18, 5);
453 ASM_VOLATILE_CASE(19, 5);
454 ASM_VOLATILE_CASE(20, 5);
455 ASM_VOLATILE_CASE(21, 5);
456 ASM_VOLATILE_CASE(22, 5);
457 ASM_VOLATILE_CASE(23, 5);
458 ASM_VOLATILE_CASE(24, 5);
459 ASM_VOLATILE_CASE(25, 5);
460 ASM_VOLATILE_CASE(26, 5);
461 ASM_VOLATILE_CASE(27, 5);
462 ASM_VOLATILE_CASE(28, 5);
463 ASM_VOLATILE_CASE(29, 5);
464 ASM_VOLATILE_CASE(30, 5);
465 ASM_VOLATILE_CASE(31, 5);
466 default:
467 break;
468 }
469 break;
470 case 6:
471 //__asm__("mfc0 %0, $1, 0" :"=r" (x));
472 switch (rd) {
473 ASM_VOLATILE_CASE(0, 6);
474 ASM_VOLATILE_CASE(1, 6);
475 ASM_VOLATILE_CASE(2, 6);
476 ASM_VOLATILE_CASE(3, 6);
477 ASM_VOLATILE_CASE(4, 6);
478 ASM_VOLATILE_CASE(5, 6);
479 ASM_VOLATILE_CASE(6, 6);
480 ASM_VOLATILE_CASE(7, 6);
481 ASM_VOLATILE_CASE(8, 6);
482 ASM_VOLATILE_CASE(9, 6);
483 ASM_VOLATILE_CASE(10, 6);
484 ASM_VOLATILE_CASE(11, 6);
485 ASM_VOLATILE_CASE(12, 6);
486 ASM_VOLATILE_CASE(13, 6);
487 ASM_VOLATILE_CASE(14, 6);
488 ASM_VOLATILE_CASE(15, 6);
489 ASM_VOLATILE_CASE(16, 6);
490 ASM_VOLATILE_CASE(17, 6);
491 ASM_VOLATILE_CASE(18, 6);
492 ASM_VOLATILE_CASE(19, 6);
493 ASM_VOLATILE_CASE(20, 6);
494 ASM_VOLATILE_CASE(21, 6);
495 ASM_VOLATILE_CASE(22, 6);
496 ASM_VOLATILE_CASE(23, 6);
497 ASM_VOLATILE_CASE(24, 6);
498 ASM_VOLATILE_CASE(25, 6);
499 ASM_VOLATILE_CASE(26, 6);
500 ASM_VOLATILE_CASE(27, 6);
501 ASM_VOLATILE_CASE(28, 6);
502 ASM_VOLATILE_CASE(29, 6);
503 ASM_VOLATILE_CASE(30, 6);
504 ASM_VOLATILE_CASE(31, 6);
505 default:
506 break;
507 }
508 break;
509 case 7:
510 //__asm__("mfc0 %0, $1, 0" :"=r" (x));
511 switch (rd) {
512 ASM_VOLATILE_CASE(0, 7);
513 ASM_VOLATILE_CASE(1, 7);
514 ASM_VOLATILE_CASE(2, 7);
515 ASM_VOLATILE_CASE(3, 7);
516 ASM_VOLATILE_CASE(4, 7);
517 ASM_VOLATILE_CASE(5, 7);
518 ASM_VOLATILE_CASE(6, 7);
519 ASM_VOLATILE_CASE(7, 7);
520 ASM_VOLATILE_CASE(8, 7);
521 ASM_VOLATILE_CASE(9, 7);
522 ASM_VOLATILE_CASE(10, 7);
523 ASM_VOLATILE_CASE(11, 7);
524 ASM_VOLATILE_CASE(12, 7);
525 ASM_VOLATILE_CASE(13, 7);
526 ASM_VOLATILE_CASE(14, 7);
527 ASM_VOLATILE_CASE(15, 7);
528 ASM_VOLATILE_CASE(16, 7);
529 ASM_VOLATILE_CASE(17, 7);
530 ASM_VOLATILE_CASE(18, 7);
531 ASM_VOLATILE_CASE(19, 7);
532 ASM_VOLATILE_CASE(20, 7);
533 ASM_VOLATILE_CASE(21, 7);
534 ASM_VOLATILE_CASE(22, 7);
535 ASM_VOLATILE_CASE(23, 7);
536 ASM_VOLATILE_CASE(24, 7);
537 ASM_VOLATILE_CASE(25, 7);
538 ASM_VOLATILE_CASE(26, 7);
539 ASM_VOLATILE_CASE(27, 7);
540 ASM_VOLATILE_CASE(28, 7);
541 ASM_VOLATILE_CASE(29, 7);
542 ASM_VOLATILE_CASE(30, 7);
543 ASM_VOLATILE_CASE(31, 7);
544 default:
545 break;
546 }
547 break;
548
549 default:
550 break;
551 }
552 #endif
553 return x;
554 }
555
556 #undef ASM_VOLATILE_CASE
557
558 #define ASM_VOLATILE_CASE(rd, sel) \
559 case rd: asm volatile ("dmfc0 %0, $" #rd ", "#sel"\n\t" :"=r" (x) ); break;
560
561 #define ASM_VOLATILE_SYNC(stype) \
562 asm volatile ("sync \n\t");
563
mips32_dirtyhelper_sync(UInt stype)564 void mips32_dirtyhelper_sync(UInt stype)
565 {
566 #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
567 ASM_VOLATILE_SYNC(0);
568 #endif
569 }
570
571 /*---------------------------------------------------------------*/
572 /*--- end guest_mips_helpers.c ---*/
573 /*---------------------------------------------------------------*/
574