1
2/*--------------------------------------------------------------------*/
3/*--- The core dispatch loop, for jumping to a code address.       ---*/
4/*---                                        dispatch-mips-linux.S ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8  This file is part of Valgrind, a dynamic binary instrumentation
9  framework.
10
11  Copyright (C) 2000-2012 RT-RK
12     mips-valgrind@rt-rk.com
13
14  This program is free software; you can redistribute it and/or
15  modify it under the terms of the GNU General Public License as
16  published by the Free Software Foundation; either version 2 of the
17  License, or (at your option) any later version.
18
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, write to the Free Software
26   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27   02111-1307, USA.
28
29  The GNU General Public License is contained in the file COPYING.
30*/
31
32
33#if defined(VGP_mips32_linux)
34
35#include "pub_core_basics_asm.h"
36#include "pub_core_dispatch_asm.h"
37#include "pub_core_transtab_asm.h"
38#include "libvex_guest_offsets.h"	/* for OFFSET_mips_PC */
39
40
41/*------------------------------------------------------------*/
42/*---                                                      ---*/
43/*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
44/*--- used to run all translations,                        ---*/
45/*--- including no-redir ones.                             ---*/
46/*---                                                      ---*/
47/*------------------------------------------------------------*/
48
49/*----------------------------------------------------*/
50/*--- Entry and preamble (set everything up)       ---*/
51/*----------------------------------------------------*/
52
53/* signature:
54void VG_(disp_run_translations)( UWord* two_words,
55                                 void*  guest_state,
56                                 Addr   host_addr );
57*/
58
59.text
60.globl VG_(disp_run_translations)
61VG_(disp_run_translations):
62    /* a0 ($4) holds two_words   */
63    /* a1 ($5) holds guest_state */
64    /* a2 ($6) holds host_addr   */
65
66    /* New stack frame.  Stack must remain 8 aligned (at least) */
67    addiu $29, -56
68
69    /* Save ra */
70    sw  $31, 0($29)
71
72    /* ... and orig guest state*/
73    sw $5, 4($29)
74
75    /* ... and s0 - s7 */
76    sw $16, 8($29)
77    sw $17, 12($29)
78    sw $18, 16($29)
79    sw $19, 20($29)
80    sw $20, 24($29)
81    sw $21, 28($29)
82    sw $22, 32($29)
83    sw $23, 36($29)
84
85    /* ... and gp, fp/s8 */
86    sw $28, 40($29)
87    sw $30, 44($29)
88
89    /* Save a0 ($4) on stack. In postamble it will be restored such that the
90       return values can be written */
91    sw $4, 48($29)
92
93    /* Load address of guest state into guest state register (r10) */
94    move $10, $5
95
96    /* and jump into the code cache.  Chained translations in
97           the code cache run, until for whatever reason, they can't
98           continue.  When that happens, the translation in question
99           will jump (or call) to one of the continuation points
100           VG_(cp_...) below. */
101    jr $6
102    /*NOTREACHED*/
103
104/*----------------------------------------------------*/
105/*--- Postamble and exit.                          ---*/
106/*----------------------------------------------------*/
107
108postamble:
109        /* At this point, r2 and r3 contain two
110           words to be returned to the caller.  r2
111           holds a TRC value, and r3 optionally may
112           hold another word (for CHAIN_ME exits, the
113           address of the place to patch.) */
114
115    /* Restore $4 from stack; holds address of two_words */
116    lw $4, 48($29)
117    sw  $2, 0($4)         /* Store $2 to two_words[0] */
118    sw  $3, 4($4)         /* Store $3 to two_words[1] */
119
120    /* Restore callee-saved registers... */
121
122    /* Restore ra */
123    lw $31, 0($29)
124
125    /* ... and s0 - s7 */
126    lw $16, 8($29)
127    lw $17, 12($29)
128    lw $18, 16($29)
129    lw $19, 20($29)
130    lw $20, 24($29)
131    lw $21, 28($29)
132    lw $22, 32($29)
133    lw $23, 36($29)
134
135    /* ... and gp, fp/s8 */
136    lw $28, 40($29)
137    lw $30, 44($29)
138
139
140    addiu $29, 56   /* stack_size */
141    jr $31
142    nop
143
144/*----------------------------------------------------*/
145/*--- Continuation points                          ---*/
146/*----------------------------------------------------*/
147
148/* ------ Chain me to slow entry point ------ */
149.global VG_(disp_cp_chain_me_to_slowEP)
150VG_(disp_cp_chain_me_to_slowEP):
151        /* We got called.  The return address indicates
152           where the patching needs to happen.  Collect
153           the return address and, exit back to C land,
154           handing the caller the pair (Chain_me_S, RA) */
155        li $2, VG_TRC_CHAIN_ME_TO_SLOW_EP
156        move $3, $31
157        /* 8 = mkLoadImm_EXACTLY2or5
158           4 = jalr $9
159           4 = nop */
160        addiu  $3, $3, -16
161        b    postamble
162
163/* ------ Chain me to slow entry point ------ */
164.global VG_(disp_cp_chain_me_to_fastEP)
165VG_(disp_cp_chain_me_to_fastEP):
166        /* We got called.  The return address indicates
167           where the patching needs to happen.  Collect
168           the return address and, exit back to C land,
169           handing the caller the pair (Chain_me_S, RA) */
170        li $2, VG_TRC_CHAIN_ME_TO_FAST_EP
171        move $3, $31
172        /* 8 = mkLoadImm_EXACTLY2or5
173           4 = jalr $9
174           4 = nop */
175        addiu  $3, $3, -16
176        b    postamble
177
178/* ------ Indirect but boring jump ------ */
179.global VG_(disp_cp_xindir)
180VG_(disp_cp_xindir):
181        /* Where are we going? */
182        lw  $11, OFFSET_mips32_PC($10)
183
184        lw $13, vgPlain_stats__n_xindirs_32
185        addiu $13, $13, 0x1
186        sw $13, vgPlain_stats__n_xindirs_32
187
188        /* try a fast lookup in the translation cache */
189        /* t1 = VG_TT_FAST_HASH(addr) * sizeof(ULong*)
190                = (t8 >> 2 & VG_TT_FAST_MASK)  << 3 */
191
192        move $14, $11
193        li $12, VG_TT_FAST_MASK
194        srl $14, $14, 2
195        and $14, $14, $12
196        sll $14, $14, 3
197
198        /* t2 = (addr of VG_(tt_fast)) + t1 */
199        la $13, VG_(tt_fast)
200        addu $13, $13, $14
201
202        lw $12, 0($13) /* t3 = VG_(tt_fast)[hash] :: ULong* */
203        addi $13, $13, 4
204        lw $25, 0($13) /* little-endian, so comparing 1st 32bit word */
205        nop
206
207check:
208        bne $12, $11, fast_lookup_failed
209        /* run the translation */
210        jr $25
211        .long   0x0   /* persuade insn decoders not to speculate past here */
212
213fast_lookup_failed:
214        /* %PC is up to date */
215        /* back out decrement of the dispatch counter */
216        /* hold dispatch_ctr in t0 (r8) */
217        lw $13, vgPlain_stats__n_xindirs_32
218        addiu $13, $13, 0x1
219        sw $13, vgPlain_stats__n_xindirs_32
220        li $2, VG_TRC_INNER_FASTMISS
221        li $3, 0
222        b       postamble
223
224/* ------ Assisted jump ------ */
225        .global VG_(disp_cp_xassisted)
226VG_(disp_cp_xassisted):
227        /* guest-state-pointer contains the TRC. Put the value into the
228           return register */
229        move    $2, $10
230        move    $3, $0
231        b       postamble
232
233/* ------ Event check failed ------ */
234        .global VG_(disp_cp_evcheck_fail)
235VG_(disp_cp_evcheck_fail):
236        li      $2, VG_TRC_INNER_COUNTERZERO
237        move    $3, $0
238        b       postamble
239
240.size VG_(disp_run_translations), .-VG_(disp_run_translations)
241
242
243/* Let the linker know we do not need an executable stack */
244.section .note.GNU-stack,"",@progbits
245
246#endif // defined(VGP_mips32_linux)
247/*--------------------------------------------------------------------*/
248/*--- end                                                          ---*/
249/*--------------------------------------------------------------------*/
250