1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The core dispatch loop, for jumping to a code address.       ---*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                         dispatch-arm-linux.S ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  Copyright (C) 2008-2011 Evan Geller
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     gaze@bea.ms
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  02111-1307, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_arm_linux)
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	.fpu vfp
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics_asm.h"
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_dispatch_asm.h"
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_transtab_asm.h"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "libvex_guest_offsets.h"	/* for OFFSET_arm_R* */
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The dispatch loop.  VG_(run_innerloop) is used to    ---*/
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- run all translations except no-redir ones.           ---*/
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Preamble (set everything up)                 ---*/
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* signature:
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.text
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.globl VG_(run_innerloop)
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(run_innerloop):
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	push {r0, r1, r4, r5, r6, r7, r8, r9, fp, lr}
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* set FPSCR to vex-required default value */
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mov  r4, #0
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fmxr fpscr, r4
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* r0 (hence also [sp,#0]) holds guest_state */
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* r1 holds do_profiling */
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	mov r8, r0
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ldr r0, [r8, #OFFSET_arm_R15T]
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       	/* fall into main loop (the right one) */
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cmp r1, #0      /* do_profiling */
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	beq VG_(run_innerloop__dispatch_unprofiled)
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	b   VG_(run_innerloop__dispatch_profiled)
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- NO-PROFILING (standard) dispatcher           ---*/
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Pairing of insns below is my guesstimate of how dual dispatch would
79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   work on an A8.  JRS, 2011-May-28 */
80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.global	VG_(run_innerloop__dispatch_unprofiled)
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(run_innerloop__dispatch_unprofiled):
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* AT ENTRY: r0 is next guest addr, r8 is possibly
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        modified guest state ptr */
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Has the guest state pointer been messed with?  If yes, exit. */
88b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movw r3, #:lower16:VG_(dispatch_ctr)
89b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        tst  r8, #1
90b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movt r3, #:upper16:VG_(dispatch_ctr)
92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	bne  gsp_changed
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* save the jump address in the guest state */
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str  r0, [r8, #OFFSET_arm_R15T]
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Are we out of timeslice?  If yes, defer to scheduler. */
99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        ldr  r2, [r3]
100b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        subs r2, r2, #1
102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        str  r2, [r3]
104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        beq  counter_is_zero
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* try a fast lookup in the translation cache */
108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // r0 = next guest, r1,r2,r3,r4 scratch
109b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movw r1, #VG_TT_FAST_MASK       // r1 = VG_TT_FAST_MASK
110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movw r4, #:lower16:VG_(tt_fast)
111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	and  r2, r1, r0, LSR #1         // r2 = entry #
113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movt r4, #:upper16:VG_(tt_fast) // r4 = &VG_(tt_fast)
114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	add  r1, r4, r2, LSL #3         // r1 = &tt_fast[entry#]
116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
117b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        ldrd r4, r5, [r1, #0]           // r4 = .guest, r5 = .host
118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	cmp  r4, r0
120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	bne  fast_lookup_failed
122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // r5: next-host    r8: live, gsp
123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // r4: next-guest
124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // r2: entry #
125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // LIVE: r5, r8; all others dead
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Found a match.  Jump to .host. */
128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	blx  r5
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	b    VG_(run_innerloop__dispatch_unprofiled)
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.ltorg
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/*NOTREACHED*/
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- PROFILING dispatcher (can be much slower)    ---*/
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.global	VG_(run_innerloop__dispatch_profiled)
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(run_innerloop__dispatch_profiled):
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* AT ENTRY: r0 is next guest addr, r8 is possibly
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        modified guest state ptr */
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Has the guest state pointer been messed with?  If yes, exit. */
144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movw r3, #:lower16:VG_(dispatch_ctr)
145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	tst  r8, #1
146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movt r3, #:upper16:VG_(dispatch_ctr)
148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	bne  gsp_changed
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* save the jump address in the guest state */
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str  r0, [r8, #OFFSET_arm_R15T]
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Are we out of timeslice?  If yes, defer to scheduler. */
155b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        ldr  r2, [r3]
156b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        subs r2, r2, #1
158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
159b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        str  r2, [r3]
160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        beq  counter_is_zero
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* try a fast lookup in the translation cache */
164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // r0 = next guest, r1,r2,r3,r4 scratch
165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movw r1, #VG_TT_FAST_MASK       // r1 = VG_TT_FAST_MASK
166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movw r4, #:lower16:VG_(tt_fast)
167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	and  r2, r1, r0, LSR #1         // r2 = entry #
169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movt r4, #:upper16:VG_(tt_fast) // r4 = &VG_(tt_fast)
170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	add  r1, r4, r2, LSL #3         // r1 = &tt_fast[entry#]
172b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
173b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        ldrd r4, r5, [r1, #0]           // r4 = .guest, r5 = .host
174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	cmp  r4, r0
176b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	bne  fast_lookup_failed
178b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // r5: next-host    r8: live, gsp
179b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // r4: next-guest
180b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // r2: entry #
181b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        // LIVE: r5, r8; all others dead
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* increment bb profile counter */
184b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movw r0, #:lower16:VG_(tt_fastN)
185b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        movt r0, #:upper16:VG_(tt_fastN) // r0 = &tt_fastN[0]
186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        ldr  r0, [r0, r2, LSL #2]        // r0 = tt_fast[entry #]
187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov        ldr  r3, [r0]                    // *r0 ++
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        add  r3, r3, #1
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str  r3, [r0]
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Found a match.  Jump to .host. */
192b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov	blx  r5
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	b    VG_(run_innerloop__dispatch_profiled)
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/*NOTREACHED*/
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- exit points                                  ---*/
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*----------------------------------------------------*/
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browngsp_changed:
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        // r0 = next guest addr (R15T), r8 = modified gsp
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Someone messed with the gsp.  Have to
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           defer to scheduler to resolve this.  dispatch ctr
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           is not yet decremented, so no need to increment. */
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* R15T is NOT up to date here.  First, need to write
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           r0 back to R15T, but without trashing r8 since
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           that holds the value we want to return to the scheduler.
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           Hence use r1 transiently for the guest state pointer. */
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ldr r1, [sp, #0]
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	str r0, [r1, #OFFSET_arm_R15T]
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	mov r0, r8      // "return modified gsp"
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	b run_innerloop_exit
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /*NOTREACHED*/
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browncounter_is_zero:
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* R15T is up to date here */
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Back out increment of the dispatch ctr */
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ldr  r1, =VG_(dispatch_ctr)
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ldr  r2, [r1]
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        add  r2, r2, #1
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str  r2, [r1]
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mov  r0, #VG_TRC_INNER_COUNTERZERO
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        b    run_innerloop_exit
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /*NOTREACHED*/
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownfast_lookup_failed:
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* R15T is up to date here */
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* Back out increment of the dispatch ctr */
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ldr  r1, =VG_(dispatch_ctr)
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ldr  r2, [r1]
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        add  r2, r2, #1
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        str  r2, [r1]
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	mov  r0, #VG_TRC_INNER_FASTMISS
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	b    run_innerloop_exit
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /*NOTREACHED*/
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* All exits from the dispatcher go through here.  %r0 holds
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the return value.
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownrun_innerloop_exit:
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* We're leaving.  Check that nobody messed with
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           FPSCR in ways we don't expect. */
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fmrx r4, fpscr
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bic  r4, #0xF8000000 /* mask out NZCV and QC */
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bic  r4, #0x0000009F /* mask out IDC,IXC,UFC,OFC,DZC,IOC */
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        cmp  r4, #0
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        bne  invariant_violation
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        b    run_innerloop_exit_REALLY
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninvariant_violation:
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        mov  r0, #VG_TRC_INVARIANT_FAILED
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        b    run_innerloop_exit_REALLY
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownrun_innerloop_exit_REALLY:
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	add sp, sp, #8
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pop {r4, r5, r6, r7, r8, r9, fp, pc}
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.size VG_(run_innerloop), .-VG_(run_innerloop)
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- A special dispatcher, for running no-redir           ---*/
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- translations.  Just runs the given translation once. ---*/
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                      ---*/
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* signature:
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(run_a_noredir_translation) ( UWord* argblock );
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Run a no-redir translation.  argblock points to 4 UWords, 2 to carry args
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   and 2 to carry results:
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      0: input:  ptr to translation
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      1: input:  ptr to guest state
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      2: output: next guest PC
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      3: output: guest state pointer afterwards (== thread return code)
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.global VG_(run_a_noredir_translation)
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_(run_a_noredir_translation):
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	push {r0,r1 /* EABI compliance */, r4-r12, lr}
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ldr r8, [r0, #4]
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	mov lr, pc
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ldr pc, [r0, #0]
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pop {r1}
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	str r0, [r1, #8]
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	str r8, [r1, #12]
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pop {r1/*EABI compliance*/,r4-r12, pc}
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.size VG_(run_a_noredir_translation), .-VG_(run_a_noredir_translation)
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Let the linker know we don't need an executable stack */
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown.section .note.GNU-stack,"",%progbits
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGP_arm_linux)
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                     dispatch-arm-linux.S ---*/
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
301