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-2015 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
55IRExpr *guest_mips32_spechelper(const HChar * function_name, IRExpr ** args,
56                                IRStmt ** precedingStmts, Int n_precedingStmts)
57{
58   return NULL;
59}
60
61IRExpr *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 */
69void 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
176void 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*/
290Bool guest_mips32_state_requires_precise_mem_exns (
291        Int minoff, Int maxoff, VexRegisterUpdates pxControl
292     )
293{
294   Int sp_min = offsetof(VexGuestMIPS32State, guest_r29);
295   Int sp_max = sp_min + 4 - 1;
296   Int pc_min = offsetof(VexGuestMIPS32State, guest_PC);
297   Int pc_max = pc_min + 4 - 1;
298
299   if (maxoff < sp_min || minoff > sp_max) {
300      /* no overlap with sp */
301      if (pxControl == VexRegUpdSpAtMemAccess)
302         return False;  /* We only need to check stack pointer. */
303   } else {
304      return True;
305   }
306
307   if (maxoff < pc_min || minoff > pc_max) {
308      /* no overlap with pc */
309   } else {
310      return True;
311   }
312
313   /* We appear to need precise updates of R11 in order to get proper
314      stacktraces from non-optimised code. */
315   Int fp_min = offsetof(VexGuestMIPS32State, guest_r30);
316   Int fp_max = fp_min + 4 - 1;
317
318   if (maxoff < fp_min || minoff > fp_max) {
319      /* no overlap with fp */
320   } else {
321      return True;
322   }
323
324   return False;
325}
326
327Bool guest_mips64_state_requires_precise_mem_exns (
328        Int minoff, Int maxoff, VexRegisterUpdates pxControl
329     )
330{
331   Int sp_min = offsetof(VexGuestMIPS64State, guest_r29);
332   Int sp_max = sp_min + 8 - 1;
333   Int pc_min = offsetof(VexGuestMIPS64State, guest_PC);
334   Int pc_max = pc_min + 8 - 1;
335
336   if ( maxoff < sp_min || minoff > sp_max ) {
337      /* no overlap with sp */
338      if (pxControl == VexRegUpdSpAtMemAccess)
339         return False;  /* We only need to check stack pointer. */
340   } else {
341      return True;
342   }
343
344   if ( maxoff < pc_min || minoff > pc_max ) {
345      /* no overlap with pc */
346   } else {
347      return True;
348   }
349
350   Int fp_min = offsetof(VexGuestMIPS64State, guest_r30);
351   Int fp_max = fp_min + 8 - 1;
352
353   if ( maxoff < fp_min || minoff > fp_max ) {
354      /* no overlap with fp */
355   } else {
356      return True;
357   }
358
359   return False;
360}
361
362VexGuestLayout mips32Guest_layout = {
363   /* Total size of the guest state, in bytes. */
364   .total_sizeB = sizeof(VexGuestMIPS32State),
365   /* Describe the stack pointer. */
366   .offset_SP = offsetof(VexGuestMIPS32State, guest_r29),
367   .sizeof_SP = 4,
368   /* Describe the frame pointer. */
369   .offset_FP = offsetof(VexGuestMIPS32State, guest_r30),
370   .sizeof_FP = 4,
371   /* Describe the instruction pointer. */
372   .offset_IP = offsetof(VexGuestMIPS32State, guest_PC),
373   .sizeof_IP = 4,
374   /* Describe any sections to be regarded by Memcheck as
375      'always-defined'. */
376   .n_alwaysDefd = 8,
377   /* ? :(  */
378   .alwaysDefd = {
379             /* 0 */ ALWAYSDEFD32(guest_r0),
380             /* 1 */ ALWAYSDEFD32(guest_r1),
381             /* 2 */ ALWAYSDEFD32(guest_EMNOTE),
382             /* 3 */ ALWAYSDEFD32(guest_CMSTART),
383             /* 4 */ ALWAYSDEFD32(guest_CMLEN),
384             /* 5 */ ALWAYSDEFD32(guest_r29),
385             /* 6 */ ALWAYSDEFD32(guest_r31),
386             /* 7 */ ALWAYSDEFD32(guest_ULR)
387             }
388};
389
390VexGuestLayout mips64Guest_layout = {
391   /* Total size of the guest state, in bytes. */
392   .total_sizeB = sizeof(VexGuestMIPS64State),
393   /* Describe the stack pointer. */
394   .offset_SP = offsetof(VexGuestMIPS64State, guest_r29),
395   .sizeof_SP = 8,
396   /* Describe the frame pointer. */
397   .offset_FP = offsetof(VexGuestMIPS64State, guest_r30),
398   .sizeof_FP = 8,
399   /* Describe the instruction pointer. */
400   .offset_IP = offsetof(VexGuestMIPS64State, guest_PC),
401   .sizeof_IP = 8,
402   /* Describe any sections to be regarded by Memcheck as
403      'always-defined'. */
404   .n_alwaysDefd = 7,
405   /* ? :(  */
406   .alwaysDefd = {
407                  /* 0 */ ALWAYSDEFD64 (guest_r0),
408                  /* 1 */ ALWAYSDEFD64 (guest_EMNOTE),
409                  /* 2 */ ALWAYSDEFD64 (guest_CMSTART),
410                  /* 3 */ ALWAYSDEFD64 (guest_CMLEN),
411                  /* 4 */ ALWAYSDEFD64 (guest_r29),
412                  /* 5 */ ALWAYSDEFD64 (guest_r31),
413                  /* 6 */ ALWAYSDEFD64 (guest_ULR)
414                  }
415};
416
417#define ASM_VOLATILE_CASE(rd, sel) \
418         case rd: \
419            asm volatile ("mfc0 %0, $" #rd ", "#sel"\n\t" :"=r" (x) ); \
420            break;
421
422UInt mips32_dirtyhelper_mfc0(UInt rd, UInt sel)
423{
424   UInt x = 0;
425#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
426   switch (sel) {
427      case 0:
428         /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
429         switch (rd) {
430            ASM_VOLATILE_CASE(0, 0);
431            ASM_VOLATILE_CASE(1, 0);
432            ASM_VOLATILE_CASE(2, 0);
433            ASM_VOLATILE_CASE(3, 0);
434            ASM_VOLATILE_CASE(4, 0);
435            ASM_VOLATILE_CASE(5, 0);
436            ASM_VOLATILE_CASE(6, 0);
437            ASM_VOLATILE_CASE(7, 0);
438            ASM_VOLATILE_CASE(8, 0);
439            ASM_VOLATILE_CASE(9, 0);
440            ASM_VOLATILE_CASE(10, 0);
441            ASM_VOLATILE_CASE(11, 0);
442            ASM_VOLATILE_CASE(12, 0);
443            ASM_VOLATILE_CASE(13, 0);
444            ASM_VOLATILE_CASE(14, 0);
445            ASM_VOLATILE_CASE(15, 0);
446            ASM_VOLATILE_CASE(16, 0);
447            ASM_VOLATILE_CASE(17, 0);
448            ASM_VOLATILE_CASE(18, 0);
449            ASM_VOLATILE_CASE(19, 0);
450            ASM_VOLATILE_CASE(20, 0);
451            ASM_VOLATILE_CASE(21, 0);
452            ASM_VOLATILE_CASE(22, 0);
453            ASM_VOLATILE_CASE(23, 0);
454            ASM_VOLATILE_CASE(24, 0);
455            ASM_VOLATILE_CASE(25, 0);
456            ASM_VOLATILE_CASE(26, 0);
457            ASM_VOLATILE_CASE(27, 0);
458            ASM_VOLATILE_CASE(28, 0);
459            ASM_VOLATILE_CASE(29, 0);
460            ASM_VOLATILE_CASE(30, 0);
461            ASM_VOLATILE_CASE(31, 0);
462         default:
463            break;
464         }
465         break;
466      case 1:
467         /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
468         switch (rd) {
469            ASM_VOLATILE_CASE(0, 1);
470            ASM_VOLATILE_CASE(1, 1);
471            ASM_VOLATILE_CASE(2, 1);
472            ASM_VOLATILE_CASE(3, 1);
473            ASM_VOLATILE_CASE(4, 1);
474            ASM_VOLATILE_CASE(5, 1);
475            ASM_VOLATILE_CASE(6, 1);
476            ASM_VOLATILE_CASE(7, 1);
477            ASM_VOLATILE_CASE(8, 1);
478            ASM_VOLATILE_CASE(9, 1);
479            ASM_VOLATILE_CASE(10, 1);
480            ASM_VOLATILE_CASE(11, 1);
481            ASM_VOLATILE_CASE(12, 1);
482            ASM_VOLATILE_CASE(13, 1);
483            ASM_VOLATILE_CASE(14, 1);
484            ASM_VOLATILE_CASE(15, 1);
485            ASM_VOLATILE_CASE(16, 1);
486            ASM_VOLATILE_CASE(17, 1);
487            ASM_VOLATILE_CASE(18, 1);
488            ASM_VOLATILE_CASE(19, 1);
489            ASM_VOLATILE_CASE(20, 1);
490            ASM_VOLATILE_CASE(21, 1);
491            ASM_VOLATILE_CASE(22, 1);
492            ASM_VOLATILE_CASE(23, 1);
493            ASM_VOLATILE_CASE(24, 1);
494            ASM_VOLATILE_CASE(25, 1);
495            ASM_VOLATILE_CASE(26, 1);
496            ASM_VOLATILE_CASE(27, 1);
497            ASM_VOLATILE_CASE(28, 1);
498            ASM_VOLATILE_CASE(29, 1);
499            ASM_VOLATILE_CASE(30, 1);
500            ASM_VOLATILE_CASE(31, 1);
501         default:
502            break;
503         }
504         break;
505      case 2:
506         /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
507         switch (rd) {
508            ASM_VOLATILE_CASE(0, 2);
509            ASM_VOLATILE_CASE(1, 2);
510            ASM_VOLATILE_CASE(2, 2);
511            ASM_VOLATILE_CASE(3, 1);
512            ASM_VOLATILE_CASE(4, 2);
513            ASM_VOLATILE_CASE(5, 2);
514            ASM_VOLATILE_CASE(6, 2);
515            ASM_VOLATILE_CASE(7, 2);
516            ASM_VOLATILE_CASE(8, 2);
517            ASM_VOLATILE_CASE(9, 2);
518            ASM_VOLATILE_CASE(10, 2);
519            ASM_VOLATILE_CASE(11, 2);
520            ASM_VOLATILE_CASE(12, 2);
521            ASM_VOLATILE_CASE(13, 2);
522            ASM_VOLATILE_CASE(14, 2);
523            ASM_VOLATILE_CASE(15, 2);
524            ASM_VOLATILE_CASE(16, 2);
525            ASM_VOLATILE_CASE(17, 2);
526            ASM_VOLATILE_CASE(18, 2);
527            ASM_VOLATILE_CASE(19, 2);
528            ASM_VOLATILE_CASE(20, 2);
529            ASM_VOLATILE_CASE(21, 2);
530            ASM_VOLATILE_CASE(22, 2);
531            ASM_VOLATILE_CASE(23, 2);
532            ASM_VOLATILE_CASE(24, 2);
533            ASM_VOLATILE_CASE(25, 2);
534            ASM_VOLATILE_CASE(26, 2);
535            ASM_VOLATILE_CASE(27, 2);
536            ASM_VOLATILE_CASE(28, 2);
537            ASM_VOLATILE_CASE(29, 2);
538            ASM_VOLATILE_CASE(30, 2);
539            ASM_VOLATILE_CASE(31, 2);
540         default:
541            break;
542         }
543         break;
544      case 3:
545         /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
546         switch (rd) {
547            ASM_VOLATILE_CASE(0, 3);
548            ASM_VOLATILE_CASE(1, 3);
549            ASM_VOLATILE_CASE(2, 3);
550            ASM_VOLATILE_CASE(3, 3);
551            ASM_VOLATILE_CASE(4, 3);
552            ASM_VOLATILE_CASE(5, 3);
553            ASM_VOLATILE_CASE(6, 3);
554            ASM_VOLATILE_CASE(7, 3);
555            ASM_VOLATILE_CASE(8, 3);
556            ASM_VOLATILE_CASE(9, 3);
557            ASM_VOLATILE_CASE(10, 3);
558            ASM_VOLATILE_CASE(11, 3);
559            ASM_VOLATILE_CASE(12, 3);
560            ASM_VOLATILE_CASE(13, 3);
561            ASM_VOLATILE_CASE(14, 3);
562            ASM_VOLATILE_CASE(15, 3);
563            ASM_VOLATILE_CASE(16, 3);
564            ASM_VOLATILE_CASE(17, 3);
565            ASM_VOLATILE_CASE(18, 3);
566            ASM_VOLATILE_CASE(19, 3);
567            ASM_VOLATILE_CASE(20, 3);
568            ASM_VOLATILE_CASE(21, 3);
569            ASM_VOLATILE_CASE(22, 3);
570            ASM_VOLATILE_CASE(23, 3);
571            ASM_VOLATILE_CASE(24, 3);
572            ASM_VOLATILE_CASE(25, 3);
573            ASM_VOLATILE_CASE(26, 3);
574            ASM_VOLATILE_CASE(27, 3);
575            ASM_VOLATILE_CASE(28, 3);
576            ASM_VOLATILE_CASE(29, 3);
577            ASM_VOLATILE_CASE(30, 3);
578            ASM_VOLATILE_CASE(31, 3);
579         default:
580            break;
581         }
582         break;
583      case 4:
584         /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
585         switch (rd) {
586            ASM_VOLATILE_CASE(0, 4);
587            ASM_VOLATILE_CASE(1, 4);
588            ASM_VOLATILE_CASE(2, 4);
589            ASM_VOLATILE_CASE(3, 4);
590            ASM_VOLATILE_CASE(4, 4);
591            ASM_VOLATILE_CASE(5, 4);
592            ASM_VOLATILE_CASE(6, 4);
593            ASM_VOLATILE_CASE(7, 4);
594            ASM_VOLATILE_CASE(8, 4);
595            ASM_VOLATILE_CASE(9, 4);
596            ASM_VOLATILE_CASE(10, 4);
597            ASM_VOLATILE_CASE(11, 4);
598            ASM_VOLATILE_CASE(12, 4);
599            ASM_VOLATILE_CASE(13, 4);
600            ASM_VOLATILE_CASE(14, 4);
601            ASM_VOLATILE_CASE(15, 4);
602            ASM_VOLATILE_CASE(16, 4);
603            ASM_VOLATILE_CASE(17, 4);
604            ASM_VOLATILE_CASE(18, 4);
605            ASM_VOLATILE_CASE(19, 4);
606            ASM_VOLATILE_CASE(20, 4);
607            ASM_VOLATILE_CASE(21, 4);
608            ASM_VOLATILE_CASE(22, 4);
609            ASM_VOLATILE_CASE(23, 4);
610            ASM_VOLATILE_CASE(24, 4);
611            ASM_VOLATILE_CASE(25, 4);
612            ASM_VOLATILE_CASE(26, 4);
613            ASM_VOLATILE_CASE(27, 4);
614            ASM_VOLATILE_CASE(28, 4);
615            ASM_VOLATILE_CASE(29, 4);
616            ASM_VOLATILE_CASE(30, 4);
617            ASM_VOLATILE_CASE(31, 4);
618         default:
619            break;
620         }
621         break;
622      case 5:
623         /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
624         switch (rd) {
625            ASM_VOLATILE_CASE(0, 5);
626            ASM_VOLATILE_CASE(1, 5);
627            ASM_VOLATILE_CASE(2, 5);
628            ASM_VOLATILE_CASE(3, 5);
629            ASM_VOLATILE_CASE(4, 5);
630            ASM_VOLATILE_CASE(5, 5);
631            ASM_VOLATILE_CASE(6, 5);
632            ASM_VOLATILE_CASE(7, 5);
633            ASM_VOLATILE_CASE(8, 5);
634            ASM_VOLATILE_CASE(9, 5);
635            ASM_VOLATILE_CASE(10, 5);
636            ASM_VOLATILE_CASE(11, 5);
637            ASM_VOLATILE_CASE(12, 5);
638            ASM_VOLATILE_CASE(13, 5);
639            ASM_VOLATILE_CASE(14, 5);
640            ASM_VOLATILE_CASE(15, 5);
641            ASM_VOLATILE_CASE(16, 5);
642            ASM_VOLATILE_CASE(17, 5);
643            ASM_VOLATILE_CASE(18, 5);
644            ASM_VOLATILE_CASE(19, 5);
645            ASM_VOLATILE_CASE(20, 5);
646            ASM_VOLATILE_CASE(21, 5);
647            ASM_VOLATILE_CASE(22, 5);
648            ASM_VOLATILE_CASE(23, 5);
649            ASM_VOLATILE_CASE(24, 5);
650            ASM_VOLATILE_CASE(25, 5);
651            ASM_VOLATILE_CASE(26, 5);
652            ASM_VOLATILE_CASE(27, 5);
653            ASM_VOLATILE_CASE(28, 5);
654            ASM_VOLATILE_CASE(29, 5);
655            ASM_VOLATILE_CASE(30, 5);
656            ASM_VOLATILE_CASE(31, 5);
657         default:
658            break;
659         }
660         break;
661      case 6:
662         /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
663         switch (rd) {
664            ASM_VOLATILE_CASE(0, 6);
665            ASM_VOLATILE_CASE(1, 6);
666            ASM_VOLATILE_CASE(2, 6);
667            ASM_VOLATILE_CASE(3, 6);
668            ASM_VOLATILE_CASE(4, 6);
669            ASM_VOLATILE_CASE(5, 6);
670            ASM_VOLATILE_CASE(6, 6);
671            ASM_VOLATILE_CASE(7, 6);
672            ASM_VOLATILE_CASE(8, 6);
673            ASM_VOLATILE_CASE(9, 6);
674            ASM_VOLATILE_CASE(10, 6);
675            ASM_VOLATILE_CASE(11, 6);
676            ASM_VOLATILE_CASE(12, 6);
677            ASM_VOLATILE_CASE(13, 6);
678            ASM_VOLATILE_CASE(14, 6);
679            ASM_VOLATILE_CASE(15, 6);
680            ASM_VOLATILE_CASE(16, 6);
681            ASM_VOLATILE_CASE(17, 6);
682            ASM_VOLATILE_CASE(18, 6);
683            ASM_VOLATILE_CASE(19, 6);
684            ASM_VOLATILE_CASE(20, 6);
685            ASM_VOLATILE_CASE(21, 6);
686            ASM_VOLATILE_CASE(22, 6);
687            ASM_VOLATILE_CASE(23, 6);
688            ASM_VOLATILE_CASE(24, 6);
689            ASM_VOLATILE_CASE(25, 6);
690            ASM_VOLATILE_CASE(26, 6);
691            ASM_VOLATILE_CASE(27, 6);
692            ASM_VOLATILE_CASE(28, 6);
693            ASM_VOLATILE_CASE(29, 6);
694            ASM_VOLATILE_CASE(30, 6);
695            ASM_VOLATILE_CASE(31, 6);
696         default:
697            break;
698         }
699         break;
700      case 7:
701         /* __asm__("mfc0 %0, $1, 0" :"=r" (x)); */
702         switch (rd) {
703            ASM_VOLATILE_CASE(0, 7);
704            ASM_VOLATILE_CASE(1, 7);
705            ASM_VOLATILE_CASE(2, 7);
706            ASM_VOLATILE_CASE(3, 7);
707            ASM_VOLATILE_CASE(4, 7);
708            ASM_VOLATILE_CASE(5, 7);
709            ASM_VOLATILE_CASE(6, 7);
710            ASM_VOLATILE_CASE(7, 7);
711            ASM_VOLATILE_CASE(8, 7);
712            ASM_VOLATILE_CASE(9, 7);
713            ASM_VOLATILE_CASE(10, 7);
714            ASM_VOLATILE_CASE(11, 7);
715            ASM_VOLATILE_CASE(12, 7);
716            ASM_VOLATILE_CASE(13, 7);
717            ASM_VOLATILE_CASE(14, 7);
718            ASM_VOLATILE_CASE(15, 7);
719            ASM_VOLATILE_CASE(16, 7);
720            ASM_VOLATILE_CASE(17, 7);
721            ASM_VOLATILE_CASE(18, 7);
722            ASM_VOLATILE_CASE(19, 7);
723            ASM_VOLATILE_CASE(20, 7);
724            ASM_VOLATILE_CASE(21, 7);
725            ASM_VOLATILE_CASE(22, 7);
726            ASM_VOLATILE_CASE(23, 7);
727            ASM_VOLATILE_CASE(24, 7);
728            ASM_VOLATILE_CASE(25, 7);
729            ASM_VOLATILE_CASE(26, 7);
730            ASM_VOLATILE_CASE(27, 7);
731            ASM_VOLATILE_CASE(28, 7);
732            ASM_VOLATILE_CASE(29, 7);
733            ASM_VOLATILE_CASE(30, 7);
734            ASM_VOLATILE_CASE(31, 7);
735         default:
736            break;
737         }
738      break;
739
740   default:
741      break;
742   }
743#endif
744   return x;
745}
746
747#undef ASM_VOLATILE_CASE
748
749#define ASM_VOLATILE_CASE(rd, sel) \
750         case rd: \
751            asm volatile ("dmfc0 %0, $" #rd ", "#sel"\n\t" :"=r" (x) ); \
752            break;
753
754ULong mips64_dirtyhelper_dmfc0 ( UInt rd, UInt sel )
755{
756   ULong x = 0;
757#if defined(VGP_mips64_linux)
758   switch (sel) {
759     case 0:
760        /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
761        switch (rd) {
762           ASM_VOLATILE_CASE (0, 0);
763           ASM_VOLATILE_CASE (1, 0);
764           ASM_VOLATILE_CASE (2, 0);
765           ASM_VOLATILE_CASE (3, 0);
766           ASM_VOLATILE_CASE (4, 0);
767           ASM_VOLATILE_CASE (5, 0);
768           ASM_VOLATILE_CASE (6, 0);
769           ASM_VOLATILE_CASE (7, 0);
770           ASM_VOLATILE_CASE (8, 0);
771           ASM_VOLATILE_CASE (9, 0);
772           ASM_VOLATILE_CASE (10, 0);
773           ASM_VOLATILE_CASE (11, 0);
774           ASM_VOLATILE_CASE (12, 0);
775           ASM_VOLATILE_CASE (13, 0);
776           ASM_VOLATILE_CASE (14, 0);
777           ASM_VOLATILE_CASE (15, 0);
778           ASM_VOLATILE_CASE (16, 0);
779           ASM_VOLATILE_CASE (17, 0);
780           ASM_VOLATILE_CASE (18, 0);
781           ASM_VOLATILE_CASE (19, 0);
782           ASM_VOLATILE_CASE (20, 0);
783           ASM_VOLATILE_CASE (21, 0);
784           ASM_VOLATILE_CASE (22, 0);
785           ASM_VOLATILE_CASE (23, 0);
786           ASM_VOLATILE_CASE (24, 0);
787           ASM_VOLATILE_CASE (25, 0);
788           ASM_VOLATILE_CASE (26, 0);
789           ASM_VOLATILE_CASE (27, 0);
790           ASM_VOLATILE_CASE (28, 0);
791           ASM_VOLATILE_CASE (29, 0);
792           ASM_VOLATILE_CASE (30, 0);
793           ASM_VOLATILE_CASE (31, 0);
794         default:
795           break;
796        }
797        break;
798     case 1:
799        /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
800        switch (rd) {
801           ASM_VOLATILE_CASE (0, 1);
802           ASM_VOLATILE_CASE (1, 1);
803           ASM_VOLATILE_CASE (2, 1);
804           ASM_VOLATILE_CASE (3, 1);
805           ASM_VOLATILE_CASE (4, 1);
806           ASM_VOLATILE_CASE (5, 1);
807           ASM_VOLATILE_CASE (6, 1);
808           ASM_VOLATILE_CASE (7, 1);
809           ASM_VOLATILE_CASE (8, 1);
810           ASM_VOLATILE_CASE (9, 1);
811           ASM_VOLATILE_CASE (10, 1);
812           ASM_VOLATILE_CASE (11, 1);
813           ASM_VOLATILE_CASE (12, 1);
814           ASM_VOLATILE_CASE (13, 1);
815           ASM_VOLATILE_CASE (14, 1);
816           ASM_VOLATILE_CASE (15, 1);
817           ASM_VOLATILE_CASE (16, 1);
818           ASM_VOLATILE_CASE (17, 1);
819           ASM_VOLATILE_CASE (18, 1);
820           ASM_VOLATILE_CASE (19, 1);
821           ASM_VOLATILE_CASE (20, 1);
822           ASM_VOLATILE_CASE (21, 1);
823           ASM_VOLATILE_CASE (22, 1);
824           ASM_VOLATILE_CASE (23, 1);
825           ASM_VOLATILE_CASE (24, 1);
826           ASM_VOLATILE_CASE (25, 1);
827           ASM_VOLATILE_CASE (26, 1);
828           ASM_VOLATILE_CASE (27, 1);
829           ASM_VOLATILE_CASE (28, 1);
830           ASM_VOLATILE_CASE (29, 1);
831           ASM_VOLATILE_CASE (30, 1);
832           ASM_VOLATILE_CASE (31, 1);
833        default:
834           break;
835        }
836        break;
837     case 2:
838        /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
839        switch (rd) {
840           ASM_VOLATILE_CASE (0, 2);
841           ASM_VOLATILE_CASE (1, 2);
842           ASM_VOLATILE_CASE (2, 2);
843           ASM_VOLATILE_CASE (3, 1);
844           ASM_VOLATILE_CASE (4, 2);
845           ASM_VOLATILE_CASE (5, 2);
846           ASM_VOLATILE_CASE (6, 2);
847           ASM_VOLATILE_CASE (7, 2);
848           ASM_VOLATILE_CASE (8, 2);
849           ASM_VOLATILE_CASE (9, 2);
850           ASM_VOLATILE_CASE (10, 2);
851           ASM_VOLATILE_CASE (11, 2);
852           ASM_VOLATILE_CASE (12, 2);
853           ASM_VOLATILE_CASE (13, 2);
854           ASM_VOLATILE_CASE (14, 2);
855           ASM_VOLATILE_CASE (15, 2);
856           ASM_VOLATILE_CASE (16, 2);
857           ASM_VOLATILE_CASE (17, 2);
858           ASM_VOLATILE_CASE (18, 2);
859           ASM_VOLATILE_CASE (19, 2);
860           ASM_VOLATILE_CASE (20, 2);
861           ASM_VOLATILE_CASE (21, 2);
862           ASM_VOLATILE_CASE (22, 2);
863           ASM_VOLATILE_CASE (23, 2);
864           ASM_VOLATILE_CASE (24, 2);
865           ASM_VOLATILE_CASE (25, 2);
866           ASM_VOLATILE_CASE (26, 2);
867           ASM_VOLATILE_CASE (27, 2);
868           ASM_VOLATILE_CASE (28, 2);
869           ASM_VOLATILE_CASE (29, 2);
870           ASM_VOLATILE_CASE (30, 2);
871           ASM_VOLATILE_CASE (31, 2);
872         default:
873           break;
874         }
875         break;
876     case 3:
877        /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
878        switch (rd) {
879           ASM_VOLATILE_CASE (0, 3);
880           ASM_VOLATILE_CASE (1, 3);
881           ASM_VOLATILE_CASE (2, 3);
882           ASM_VOLATILE_CASE (3, 3);
883           ASM_VOLATILE_CASE (4, 3);
884           ASM_VOLATILE_CASE (5, 3);
885           ASM_VOLATILE_CASE (6, 3);
886           ASM_VOLATILE_CASE (7, 3);
887           ASM_VOLATILE_CASE (8, 3);
888           ASM_VOLATILE_CASE (9, 3);
889           ASM_VOLATILE_CASE (10, 3);
890           ASM_VOLATILE_CASE (11, 3);
891           ASM_VOLATILE_CASE (12, 3);
892           ASM_VOLATILE_CASE (13, 3);
893           ASM_VOLATILE_CASE (14, 3);
894           ASM_VOLATILE_CASE (15, 3);
895           ASM_VOLATILE_CASE (16, 3);
896           ASM_VOLATILE_CASE (17, 3);
897           ASM_VOLATILE_CASE (18, 3);
898           ASM_VOLATILE_CASE (19, 3);
899           ASM_VOLATILE_CASE (20, 3);
900           ASM_VOLATILE_CASE (21, 3);
901           ASM_VOLATILE_CASE (22, 3);
902           ASM_VOLATILE_CASE (23, 3);
903           ASM_VOLATILE_CASE (24, 3);
904           ASM_VOLATILE_CASE (25, 3);
905           ASM_VOLATILE_CASE (26, 3);
906           ASM_VOLATILE_CASE (27, 3);
907           ASM_VOLATILE_CASE (28, 3);
908           ASM_VOLATILE_CASE (29, 3);
909           ASM_VOLATILE_CASE (30, 3);
910           ASM_VOLATILE_CASE (31, 3);
911        default:
912           break;
913        }
914        break;
915     case 4:
916        /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
917        switch (rd) {
918           ASM_VOLATILE_CASE (0, 4);
919           ASM_VOLATILE_CASE (1, 4);
920           ASM_VOLATILE_CASE (2, 4);
921           ASM_VOLATILE_CASE (3, 4);
922           ASM_VOLATILE_CASE (4, 4);
923           ASM_VOLATILE_CASE (5, 4);
924           ASM_VOLATILE_CASE (6, 4);
925           ASM_VOLATILE_CASE (7, 4);
926           ASM_VOLATILE_CASE (8, 4);
927           ASM_VOLATILE_CASE (9, 4);
928           ASM_VOLATILE_CASE (10, 4);
929           ASM_VOLATILE_CASE (11, 4);
930           ASM_VOLATILE_CASE (12, 4);
931           ASM_VOLATILE_CASE (13, 4);
932           ASM_VOLATILE_CASE (14, 4);
933           ASM_VOLATILE_CASE (15, 4);
934           ASM_VOLATILE_CASE (16, 4);
935           ASM_VOLATILE_CASE (17, 4);
936           ASM_VOLATILE_CASE (18, 4);
937           ASM_VOLATILE_CASE (19, 4);
938           ASM_VOLATILE_CASE (20, 4);
939           ASM_VOLATILE_CASE (21, 4);
940           ASM_VOLATILE_CASE (22, 4);
941           ASM_VOLATILE_CASE (23, 4);
942           ASM_VOLATILE_CASE (24, 4);
943           ASM_VOLATILE_CASE (25, 4);
944           ASM_VOLATILE_CASE (26, 4);
945           ASM_VOLATILE_CASE (27, 4);
946           ASM_VOLATILE_CASE (28, 4);
947           ASM_VOLATILE_CASE (29, 4);
948           ASM_VOLATILE_CASE (30, 4);
949           ASM_VOLATILE_CASE (31, 4);
950           default:
951              break;
952           }
953        break;
954     case 5:
955        /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
956        switch (rd) {
957           ASM_VOLATILE_CASE (0, 5);
958           ASM_VOLATILE_CASE (1, 5);
959           ASM_VOLATILE_CASE (2, 5);
960           ASM_VOLATILE_CASE (3, 5);
961           ASM_VOLATILE_CASE (4, 5);
962           ASM_VOLATILE_CASE (5, 5);
963           ASM_VOLATILE_CASE (6, 5);
964           ASM_VOLATILE_CASE (7, 5);
965           ASM_VOLATILE_CASE (8, 5);
966           ASM_VOLATILE_CASE (9, 5);
967           ASM_VOLATILE_CASE (10, 5);
968           ASM_VOLATILE_CASE (11, 5);
969           ASM_VOLATILE_CASE (12, 5);
970           ASM_VOLATILE_CASE (13, 5);
971           ASM_VOLATILE_CASE (14, 5);
972           ASM_VOLATILE_CASE (15, 5);
973           ASM_VOLATILE_CASE (16, 5);
974           ASM_VOLATILE_CASE (17, 5);
975           ASM_VOLATILE_CASE (18, 5);
976           ASM_VOLATILE_CASE (19, 5);
977           ASM_VOLATILE_CASE (20, 5);
978           ASM_VOLATILE_CASE (21, 5);
979           ASM_VOLATILE_CASE (22, 5);
980           ASM_VOLATILE_CASE (23, 5);
981           ASM_VOLATILE_CASE (24, 5);
982           ASM_VOLATILE_CASE (25, 5);
983           ASM_VOLATILE_CASE (26, 5);
984           ASM_VOLATILE_CASE (27, 5);
985           ASM_VOLATILE_CASE (28, 5);
986           ASM_VOLATILE_CASE (29, 5);
987           ASM_VOLATILE_CASE (30, 5);
988           ASM_VOLATILE_CASE (31, 5);
989           default:
990              break;
991        }
992        break;
993     case 6:
994        /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
995        switch (rd) {
996           ASM_VOLATILE_CASE (0, 6);
997           ASM_VOLATILE_CASE (1, 6);
998           ASM_VOLATILE_CASE (2, 6);
999           ASM_VOLATILE_CASE (3, 6);
1000           ASM_VOLATILE_CASE (4, 6);
1001           ASM_VOLATILE_CASE (5, 6);
1002           ASM_VOLATILE_CASE (6, 6);
1003           ASM_VOLATILE_CASE (7, 6);
1004           ASM_VOLATILE_CASE (8, 6);
1005           ASM_VOLATILE_CASE (9, 6);
1006           ASM_VOLATILE_CASE (10, 6);
1007           ASM_VOLATILE_CASE (11, 6);
1008           ASM_VOLATILE_CASE (12, 6);
1009           ASM_VOLATILE_CASE (13, 6);
1010           ASM_VOLATILE_CASE (14, 6);
1011           ASM_VOLATILE_CASE (15, 6);
1012           ASM_VOLATILE_CASE (16, 6);
1013           ASM_VOLATILE_CASE (17, 6);
1014           ASM_VOLATILE_CASE (18, 6);
1015           ASM_VOLATILE_CASE (19, 6);
1016           ASM_VOLATILE_CASE (20, 6);
1017           ASM_VOLATILE_CASE (21, 6);
1018           ASM_VOLATILE_CASE (22, 6);
1019           ASM_VOLATILE_CASE (23, 6);
1020           ASM_VOLATILE_CASE (24, 6);
1021           ASM_VOLATILE_CASE (25, 6);
1022           ASM_VOLATILE_CASE (26, 6);
1023           ASM_VOLATILE_CASE (27, 6);
1024           ASM_VOLATILE_CASE (28, 6);
1025           ASM_VOLATILE_CASE (29, 6);
1026           ASM_VOLATILE_CASE (30, 6);
1027           ASM_VOLATILE_CASE (31, 6);
1028        default:
1029           break;
1030        }
1031        break;
1032     case 7:
1033        /* __asm__("dmfc0 %0, $1, 0" :"=r" (x)); */
1034        switch (rd) {
1035           ASM_VOLATILE_CASE (0, 7);
1036           ASM_VOLATILE_CASE (1, 7);
1037           ASM_VOLATILE_CASE (2, 7);
1038           ASM_VOLATILE_CASE (3, 7);
1039           ASM_VOLATILE_CASE (4, 7);
1040           ASM_VOLATILE_CASE (5, 7);
1041           ASM_VOLATILE_CASE (6, 7);
1042           ASM_VOLATILE_CASE (7, 7);
1043           ASM_VOLATILE_CASE (8, 7);
1044           ASM_VOLATILE_CASE (9, 7);
1045           ASM_VOLATILE_CASE (10, 7);
1046           ASM_VOLATILE_CASE (11, 7);
1047           ASM_VOLATILE_CASE (12, 7);
1048           ASM_VOLATILE_CASE (13, 7);
1049           ASM_VOLATILE_CASE (14, 7);
1050           ASM_VOLATILE_CASE (15, 7);
1051           ASM_VOLATILE_CASE (16, 7);
1052           ASM_VOLATILE_CASE (17, 7);
1053           ASM_VOLATILE_CASE (18, 7);
1054           ASM_VOLATILE_CASE (19, 7);
1055           ASM_VOLATILE_CASE (20, 7);
1056           ASM_VOLATILE_CASE (21, 7);
1057           ASM_VOLATILE_CASE (22, 7);
1058           ASM_VOLATILE_CASE (23, 7);
1059           ASM_VOLATILE_CASE (24, 7);
1060           ASM_VOLATILE_CASE (25, 7);
1061           ASM_VOLATILE_CASE (26, 7);
1062           ASM_VOLATILE_CASE (27, 7);
1063           ASM_VOLATILE_CASE (28, 7);
1064           ASM_VOLATILE_CASE (29, 7);
1065           ASM_VOLATILE_CASE (30, 7);
1066           ASM_VOLATILE_CASE (31, 7);
1067         default:
1068           break;
1069         }
1070       break;
1071
1072     default:
1073       break;
1074     }
1075#endif
1076   return x;
1077}
1078
1079#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
1080UInt mips32_dirtyhelper_rdhwr ( UInt rt, UInt rd )
1081{
1082   UInt x = 0;
1083   switch (rd) {
1084      case 1:  /* x = SYNCI_StepSize() */
1085         __asm__ __volatile__("rdhwr %0, $1\n\t" : "=r" (x) );
1086         break;
1087
1088      case 31:  /* x = CVMX_get_cycles() */
1089         __asm__ __volatile__("rdhwr %0, $31\n\t" : "=r" (x) );
1090         break;
1091
1092      default:
1093         vassert(0);
1094         break;
1095   }
1096   return x;
1097}
1098
1099ULong mips64_dirtyhelper_rdhwr ( ULong rt, ULong rd )
1100{
1101   ULong x = 0;
1102   switch (rd) {
1103      case 1:  /* x = SYNCI_StepSize() */
1104         __asm__ __volatile__("rdhwr %0, $1\n\t" : "=r" (x) );
1105         break;
1106
1107      case 31:  /* x = CVMX_get_cycles() */
1108         __asm__ __volatile__("rdhwr %0, $31\n\t" : "=r" (x) );
1109         break;
1110
1111      default:
1112         vassert(0);
1113         break;
1114   }
1115   return x;
1116}
1117#endif
1118
1119#define ASM_VOLATILE_UNARY32(inst)                                  \
1120   __asm__ volatile("cfc1  $t0,  $31"   "\n\t"                      \
1121                    "ctc1  %2,   $31"   "\n\t"                      \
1122                    "mtc1  %1,   $f20"  "\n\t"                      \
1123                    #inst" $f20, $f20"  "\n\t"                      \
1124                    "cfc1  %0,   $31"   "\n\t"                      \
1125                    "ctc1  $t0,  $31"   "\n\t"                      \
1126                    : "=r" (ret)                                    \
1127                    : "r" (loFsVal), "r" (fcsr)                     \
1128                    : "t0", "$f20"                                  \
1129                   );
1130
1131#define ASM_VOLATILE_UNARY32_DOUBLE(inst)                           \
1132   __asm__ volatile("cfc1  $t0,  $31"   "\n\t"                      \
1133                    "ctc1  %3,   $31"   "\n\t"                      \
1134                    "mtc1  %1,   $f20"  "\n\t"                      \
1135                    "mtc1  %2,   $f21"  "\n\t"                      \
1136                    #inst" $f20, $f20"  "\n\t"                      \
1137                    "cfc1  %0,   $31"   "\n\t"                      \
1138                    "ctc1  $t0,  $31"   "\n\t"                      \
1139                    : "=r" (ret)                                    \
1140                    : "r" (loFsVal), "r" (hiFsVal), "r" (fcsr)      \
1141                    : "t0", "$f20", "$f21"                          \
1142                   );
1143
1144#define ASM_VOLATILE_UNARY64(inst)                                  \
1145   __asm__ volatile("cfc1  $t0,  $31"    "\n\t"                     \
1146                    "ctc1  %2,   $31"    "\n\t"                     \
1147                    "ldc1  $f24, 0(%1)"  "\n\t"                     \
1148                    #inst" $f24, $f24"   "\n\t"                     \
1149                    "cfc1  %0,   $31"    "\n\t"                     \
1150                    "ctc1  $t0,  $31"    "\n\t"                     \
1151                    : "=r" (ret)                                    \
1152                    : "r" (&(addr[fs])), "r" (fcsr)                 \
1153                    : "t0", "$f24"                                  \
1154                   );
1155
1156#define ASM_VOLATILE_BINARY32(inst)                                 \
1157   __asm__ volatile("cfc1  $t0,  $31"         "\n\t"                \
1158                    "ctc1  %3,   $31"         "\n\t"                \
1159                    "mtc1  %1,   $f20"        "\n\t"                \
1160                    "mtc1  %2,   $f22"        "\n\t"                \
1161                    #inst" $f20, $f20, $f22"  "\n\t"                \
1162                    "cfc1  %0,   $31"         "\n\t"                \
1163                    "ctc1  $t0,  $31"         "\n\t"                \
1164                    : "=r" (ret)                                    \
1165                    : "r" (loFsVal), "r" (loFtVal), "r" (fcsr)      \
1166                    : "t0", "$f20", "$f22"                          \
1167                   );
1168
1169#define ASM_VOLATILE_BINARY32_DOUBLE(inst)                          \
1170   __asm__ volatile("cfc1  $t0,  $31"         "\n\t"                \
1171                    "ctc1  %5,   $31"         "\n\t"                \
1172                    "mtc1  %1,   $f20"        "\n\t"                \
1173                    "mtc1  %2,   $f21"        "\n\t"                \
1174                    "mtc1  %3,   $f22"        "\n\t"                \
1175                    "mtc1  %4,   $f23"        "\n\t"                \
1176                    #inst" $f20, $f20, $f22"  "\n\t"                \
1177                    "cfc1  %0,   $31"         "\n\t"                \
1178                    "ctc1  $t0,  $31"         "\n\t"                \
1179                    : "=r" (ret)                                    \
1180                    : "r" (loFsVal), "r" (hiFsVal), "r" (loFtVal),  \
1181                      "r" (hiFtVal), "r" (fcsr)                     \
1182                    : "t0", "$f20", "$f21", "$f22", "$f23"          \
1183                   );
1184
1185#define ASM_VOLATILE_BINARY64(inst)                                     \
1186   __asm__ volatile("cfc1  $t0,  $31"         "\n\t"                    \
1187                    "ctc1  %3,   $31"         "\n\t"                    \
1188                    "ldc1  $f24, 0(%1)"       "\n\t"                    \
1189                    "ldc1  $f26, 0(%2)"       "\n\t"                    \
1190                    #inst" $f24, $f24, $f26"  "\n\t"                    \
1191                    "cfc1  %0,   $31"         "\n\t"                    \
1192                    "ctc1  $t0,  $31"         "\n\t"                    \
1193                    : "=r" (ret)                                        \
1194                    : "r" (&(addr[fs])), "r" (&(addr[ft])), "r" (fcsr)  \
1195                    : "t0", "$f24", "$f26"                              \
1196                   );
1197
1198/* TODO: Add cases for all fpu instructions because all fpu instructions are
1199         change the value of FCSR register. */
1200extern UInt mips_dirtyhelper_calculate_FCSR_fp32 ( void* gs, UInt fs, UInt ft,
1201                                                   flt_op inst )
1202{
1203   UInt ret = 0;
1204#if defined(__mips__)
1205   VexGuestMIPS32State* guest_state = (VexGuestMIPS32State*)gs;
1206   UInt loFsVal, hiFsVal, loFtVal, hiFtVal;
1207#if defined (_MIPSEL)
1208   ULong *addr = (ULong *)&guest_state->guest_f0;
1209   loFsVal     = (UInt)addr[fs];
1210   hiFsVal     = (UInt)addr[fs+1];
1211   loFtVal     = (UInt)addr[ft];
1212   hiFtVal     = (UInt)addr[ft+1];
1213#elif defined (_MIPSEB)
1214   UInt *addr = (UInt *)&guest_state->guest_f0;
1215   loFsVal    = (UInt)addr[fs*2];
1216   hiFsVal    = (UInt)addr[fs*2+2];
1217   loFtVal    = (UInt)addr[ft*2];
1218   hiFtVal    = (UInt)addr[ft*2+2];
1219#endif
1220   UInt fcsr     = guest_state->guest_FCSR;
1221   switch (inst) {
1222      case ROUNDWD:
1223         ASM_VOLATILE_UNARY32_DOUBLE(round.w.d)
1224         break;
1225      case FLOORWS:
1226         ASM_VOLATILE_UNARY32(floor.w.s)
1227         break;
1228      case FLOORWD:
1229         ASM_VOLATILE_UNARY32_DOUBLE(floor.w.d)
1230         break;
1231      case TRUNCWS:
1232         ASM_VOLATILE_UNARY32(trunc.w.s)
1233         break;
1234      case TRUNCWD:
1235         ASM_VOLATILE_UNARY32_DOUBLE(trunc.w.d)
1236         break;
1237      case CEILWS:
1238         ASM_VOLATILE_UNARY32(ceil.w.s)
1239         break;
1240      case CEILWD:
1241         ASM_VOLATILE_UNARY32_DOUBLE(ceil.w.d)
1242         break;
1243      case CVTDS:
1244         ASM_VOLATILE_UNARY32(cvt.d.s)
1245         break;
1246      case CVTDW:
1247         ASM_VOLATILE_UNARY32(cvt.d.w)
1248         break;
1249      case CVTSW:
1250         ASM_VOLATILE_UNARY32(cvt.s.w)
1251         break;
1252      case CVTSD:
1253         ASM_VOLATILE_UNARY32_DOUBLE(cvt.s.d)
1254         break;
1255      case CVTWS:
1256         ASM_VOLATILE_UNARY32(cvt.w.s)
1257         break;
1258      case CVTWD:
1259         ASM_VOLATILE_UNARY32_DOUBLE(cvt.w.d)
1260         break;
1261      case ROUNDWS:
1262         ASM_VOLATILE_UNARY32(round.w.s)
1263         break;
1264#if ((__mips == 32) && defined(__mips_isa_rev) && (__mips_isa_rev >= 2)) \
1265    || (__mips == 64)
1266      case CEILLS:
1267         ASM_VOLATILE_UNARY32(ceil.l.s)
1268         break;
1269      case CEILLD:
1270         ASM_VOLATILE_UNARY32_DOUBLE(ceil.l.d)
1271         break;
1272      case CVTDL:
1273         ASM_VOLATILE_UNARY32_DOUBLE(cvt.d.l)
1274         break;
1275      case CVTLS:
1276         ASM_VOLATILE_UNARY32(cvt.l.s)
1277         break;
1278      case CVTLD:
1279         ASM_VOLATILE_UNARY32_DOUBLE(cvt.l.d)
1280         break;
1281      case CVTSL:
1282         ASM_VOLATILE_UNARY32_DOUBLE(cvt.s.l)
1283         break;
1284      case FLOORLS:
1285         ASM_VOLATILE_UNARY32(floor.l.s)
1286         break;
1287      case FLOORLD:
1288         ASM_VOLATILE_UNARY32_DOUBLE(floor.l.d)
1289         break;
1290      case ROUNDLS:
1291         ASM_VOLATILE_UNARY32(round.l.s)
1292         break;
1293      case ROUNDLD:
1294         ASM_VOLATILE_UNARY32_DOUBLE(round.l.d)
1295         break;
1296      case TRUNCLS:
1297         ASM_VOLATILE_UNARY32(trunc.l.s)
1298         break;
1299      case TRUNCLD:
1300         ASM_VOLATILE_UNARY32_DOUBLE(trunc.l.d)
1301         break;
1302#endif
1303      case ADDS:
1304          ASM_VOLATILE_BINARY32(add.s)
1305          break;
1306      case ADDD:
1307          ASM_VOLATILE_BINARY32_DOUBLE(add.d)
1308          break;
1309      case SUBS:
1310          ASM_VOLATILE_BINARY32(sub.s)
1311          break;
1312      case SUBD:
1313          ASM_VOLATILE_BINARY32_DOUBLE(sub.d)
1314          break;
1315      case DIVS:
1316          ASM_VOLATILE_BINARY32(div.s)
1317          break;
1318      default:
1319         vassert(0);
1320         break;
1321   }
1322#endif
1323   return ret;
1324}
1325
1326/* TODO: Add cases for all fpu instructions because all fpu instructions are
1327         change the value of FCSR register. */
1328extern UInt mips_dirtyhelper_calculate_FCSR_fp64 ( void* gs, UInt fs, UInt ft,
1329                                                   flt_op inst )
1330{
1331   UInt ret = 0;
1332#if defined(__mips__)
1333#if defined(VGA_mips32)
1334   VexGuestMIPS32State* guest_state = (VexGuestMIPS32State*)gs;
1335#else
1336   VexGuestMIPS64State* guest_state = (VexGuestMIPS64State*)gs;
1337#endif
1338   ULong *addr = (ULong *)&guest_state->guest_f0;
1339   UInt fcsr   = guest_state->guest_FCSR;
1340   switch (inst) {
1341      case ROUNDWD:
1342         ASM_VOLATILE_UNARY64(round.w.d)
1343         break;
1344      case FLOORWS:
1345         ASM_VOLATILE_UNARY64(floor.w.s)
1346         break;
1347      case FLOORWD:
1348         ASM_VOLATILE_UNARY64(floor.w.d)
1349         break;
1350      case TRUNCWS:
1351         ASM_VOLATILE_UNARY64(trunc.w.s)
1352         break;
1353      case TRUNCWD:
1354         ASM_VOLATILE_UNARY64(trunc.w.d)
1355         break;
1356      case CEILWS:
1357         ASM_VOLATILE_UNARY64(ceil.w.s)
1358         break;
1359      case CEILWD:
1360         ASM_VOLATILE_UNARY64(ceil.w.d)
1361         break;
1362      case CVTDS:
1363         ASM_VOLATILE_UNARY64(cvt.d.s)
1364         break;
1365      case CVTDW:
1366         ASM_VOLATILE_UNARY64(cvt.d.w)
1367         break;
1368      case CVTSW:
1369         ASM_VOLATILE_UNARY64(cvt.s.w)
1370         break;
1371      case CVTSD:
1372         ASM_VOLATILE_UNARY64(cvt.s.d)
1373         break;
1374      case CVTWS:
1375         ASM_VOLATILE_UNARY64(cvt.w.s)
1376         break;
1377      case CVTWD:
1378         ASM_VOLATILE_UNARY64(cvt.w.d)
1379         break;
1380      case ROUNDWS:
1381         ASM_VOLATILE_UNARY64(round.w.s)
1382         break;
1383#if ((__mips == 32) && defined(__mips_isa_rev) && (__mips_isa_rev >= 2)) \
1384    || (__mips == 64)
1385      case CEILLS:
1386         ASM_VOLATILE_UNARY64(ceil.l.s)
1387         break;
1388      case CEILLD:
1389         ASM_VOLATILE_UNARY64(ceil.l.d)
1390         break;
1391      case CVTDL:
1392         ASM_VOLATILE_UNARY64(cvt.d.l)
1393         break;
1394      case CVTLS:
1395         ASM_VOLATILE_UNARY64(cvt.l.s)
1396         break;
1397      case CVTLD:
1398         ASM_VOLATILE_UNARY64(cvt.l.d)
1399         break;
1400      case CVTSL:
1401         ASM_VOLATILE_UNARY64(cvt.s.l)
1402         break;
1403      case FLOORLS:
1404         ASM_VOLATILE_UNARY64(floor.l.s)
1405         break;
1406      case FLOORLD:
1407         ASM_VOLATILE_UNARY64(floor.l.d)
1408         break;
1409      case ROUNDLS:
1410         ASM_VOLATILE_UNARY64(round.l.s)
1411         break;
1412      case ROUNDLD:
1413         ASM_VOLATILE_UNARY64(round.l.d)
1414         break;
1415      case TRUNCLS:
1416         ASM_VOLATILE_UNARY64(trunc.l.s)
1417         break;
1418      case TRUNCLD:
1419         ASM_VOLATILE_UNARY64(trunc.l.d)
1420         break;
1421#endif
1422      case ADDS:
1423          ASM_VOLATILE_BINARY64(add.s)
1424          break;
1425      case ADDD:
1426          ASM_VOLATILE_BINARY64(add.d)
1427          break;
1428      case SUBS:
1429          ASM_VOLATILE_BINARY64(sub.s)
1430          break;
1431      case SUBD:
1432          ASM_VOLATILE_BINARY64(sub.d)
1433          break;
1434      case DIVS:
1435          ASM_VOLATILE_BINARY64(div.s)
1436          break;
1437      default:
1438         vassert(0);
1439         break;
1440   }
1441#endif
1442   return ret;
1443}
1444
1445/*---------------------------------------------------------------*/
1446/*--- end                                guest_mips_helpers.c ---*/
1447/*---------------------------------------------------------------*/
1448