chiark / gitweb /
Merge branch '2.4.x' into 2.5.x
[catacomb] / base / regdump-arm.S
1 /// -*- mode: asm; asm-comment-char: ?/ -*-
2 ///
3 /// Register dump and debugging for 32-bit ARM
4 ///
5 /// (c) 2019 Straylight/Edgeware
6 ///
7
8 ///----- Licensing notice ---------------------------------------------------
9 ///
10 /// This file is part of Catacomb.
11 ///
12 /// Catacomb is free software: you can redistribute it and/or modify it
13 /// under the terms of the GNU Library General Public License as published
14 /// by the Free Software Foundation; either version 2 of the License, or
15 /// (at your option) any later version.
16 ///
17 /// Catacomb is distributed in the hope that it will be useful, but
18 /// WITHOUT ANY WARRANTY; without even the implied warranty of
19 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 /// Library General Public License for more details.
21 ///
22 /// You should have received a copy of the GNU Library General Public
23 /// License along with Catacomb.  If not, write to the Free Software
24 /// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 /// USA.
26
27 ///--------------------------------------------------------------------------
28 /// Preliminaries.
29
30 #include "config.h"
31 #include "asm-common.h"
32 #include "regdump.h"
33
34         .arch   armv7-a
35         .fpu    neon
36
37         .text
38
39 ///--------------------------------------------------------------------------
40 /// Main code.
41
42 FUNC(regdump_gpsave)
43   endprologue
44         // On entry, r13 should point to `REGDUMP_GPSIZE' bytes of
45         // word-aligned storage to be the general-purpose save area, with r12
46         // and r14 already saved.  On exit, the initial registers are saved
47         // in this space, and modified: r4 points to the general-purpose save
48         // area, r6 holds the focus address (possibly already saved), r0
49         // contains the number of bytes required in the extended save area,
50         // and other general-purpose registers are clobbered or used to
51         // communicate with `regdump_xtsave' below.  Doing anything other
52         // than lowering the stack pointer and calling `regdump_xtsave' is
53         // not recommended.
54
55         // Save the easy registers.
56         stmia   r13, {r0-r11}
57         mov     r4, r13
58
59         // Determine the previous stack pointer and save it.
60         add     r0, r4, #REGDUMP_GPSIZE
61         str     r0, [r4, #13*4]
62
63         // Capture the status flags and return address.  If the return
64         // address has its low bit set, then the caller was in Thumb state:
65         // clear the bit from the reconstructed PC, and set the corresponding
66         // CPSR bit.
67         mrs     r0, cpsr
68         tst     r14, #1
69         bic     r1, r14, #1
70         orrne   r0, r0, #0x00000020
71         str     r0, [r13, #4*REGIX_CPSR]
72         str     r1, [r13, #15*4]
73
74         // Load the focus address and save it as r6.
75         ldr     r6, [r4, #4*REGIX_ADDR]
76
77         // Determine the extended save area size.
78         ldgot
79         mov     r0, #8 + 8
80         leaext  r12, regdump__flags
81         ldr     r12, [r12]
82         tst     r12, #REGF_VFP
83         addne   r0, r0, #REGDUMP_FPSIZE_D16
84         tstne   r12, #REGF_D32
85         addne   r0, r0, #REGDUMP_FPSIZE_D32 - REGDUMP_FPSIZE_D16
86
87         // Done.
88         bx      r14
89
90 ENDFUNC
91
92 FUNC(regdump_gprstr)
93   endprologue
94         // On entry, r4 points to a general-purpose save area, established by
95         // `regdump_gpsave'.  On exit, the general-purpose registers (other
96         // than r13 and r14) are restored to their original values.
97
98         // Restore the processor flags.
99         ldr     r0, [r4, #4*REGIX_CPSR]
100         msr     cpsr_fs, r0
101
102         // Load the easy registers.
103         ldmia   r4, {r0-r12}
104
105         // Done.
106         bx      r14
107
108 ENDFUNC
109
110 FUNC(regdump_xtsave)
111   endprologue
112         // On entry, r13 points to an extended save area, of size determined
113         // by `regdump_gpsave' above.  On exit, the save area is filled in
114         // and a handy map placed at its base.
115
116         // Set up the map/extended save area pointer.
117         add     r5, r13, #7
118         bic     r5, r5, #7
119
120         // Start by filling in the easy part of the map.
121         str     r4, [r5, #regmap_gp]
122
123         // Fetch the flags explaining what to do.
124         ldgot
125         leaext  r12, regdump__flags
126         ldr     r12, [r12]
127
128         // Figure out whether there are VFP/NEON registers.
129         tst     r12, #REGF_VFP
130         moveq   r3, #0
131         addne   r3, r5, #regmap_size
132         str     r3, [r5, #regmap_fp]
133         beq     9f
134
135         // Get the FP status register.
136         vmrs    r0, fpscr
137         str     r0, [r3], #8
138
139         // At least the first 16.
140         vstmia  r3!, {d0-d15}
141
142         // Maybe the other 16 too.
143         tst     r12, #REGF_D32
144         vstmiane r3!, {d16-d31}
145
146         // Done.
147 9:      bx      r14
148
149 ENDFUNC
150
151 FUNC(regdump_xtrstr)
152   endprologue
153         // On entry, r5 points to a register-save map.  On exit, the extended
154         // registers are restored from the save area, r4 (pointing to the
155         // general-purpose save area) is preserved, and the other general
156         // registers are clobbered.
157
158         // Fetch the flags explaining what to do.
159         ldgot
160         leaext  r12, regdump__flags
161         ldr     r12, [r12]
162
163         // Figure out if there are VFP/NEON registers.
164         tst     r12, #REGF_VFP
165         beq     9f
166         ldr     r3, [r5, #regmap_fp]
167
168         // Load the FP status register.
169         ldr     r0, [r3], #8
170         vmsr    fpscr, r0
171
172         // Load the first 16 registers.
173         vldmia  r3!, {d0-d15}
174
175         // And maybe the other 16.
176         tst     r12, #REGF_D32
177         vldmiane r3!, {d16-d31}
178
179         // Done.
180 9:      bx      r14
181
182 ENDFUNC
183
184 ///----- That's all, folks --------------------------------------------------