Commit | Line | Data |
---|---|---|
4bc8424a MW |
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 | ||
6a3d653c | 63 | // Clear the magic Thumb-state bit from the return address. |
4bc8424a | 64 | bic r1, r14, #1 |
4bc8424a MW |
65 | str r1, [r13, #15*4] |
66 | ||
67 | // Load the focus address and save it as r6. | |
68 | ldr r6, [r4, #4*REGIX_ADDR] | |
69 | ||
70 | // Determine the extended save area size. | |
71 | ldgot | |
72 | mov r0, #8 + 8 | |
73 | leaext r12, regdump__flags | |
74 | ldr r12, [r12] | |
75 | tst r12, #REGF_VFP | |
76 | addne r0, r0, #REGDUMP_FPSIZE_D16 | |
77 | tstne r12, #REGF_D32 | |
78 | addne r0, r0, #REGDUMP_FPSIZE_D32 - REGDUMP_FPSIZE_D16 | |
79 | ||
80 | // Done. | |
81 | bx r14 | |
82 | ||
83 | ENDFUNC | |
84 | ||
85 | FUNC(regdump_gprstr) | |
86 | endprologue | |
87 | // On entry, r4 points to a general-purpose save area, established by | |
88 | // `regdump_gpsave'. On exit, the general-purpose registers (other | |
89 | // than r13 and r14) are restored to their original values. | |
90 | ||
91 | // Restore the processor flags. | |
92 | ldr r0, [r4, #4*REGIX_CPSR] | |
93 | msr cpsr_fs, r0 | |
94 | ||
95 | // Load the easy registers. | |
96 | ldmia r4, {r0-r12} | |
97 | ||
98 | // Done. | |
99 | bx r14 | |
100 | ||
101 | ENDFUNC | |
102 | ||
103 | FUNC(regdump_xtsave) | |
104 | endprologue | |
105 | // On entry, r13 points to an extended save area, of size determined | |
106 | // by `regdump_gpsave' above. On exit, the save area is filled in | |
107 | // and a handy map placed at its base. | |
108 | ||
109 | // Set up the map/extended save area pointer. | |
110 | add r5, r13, #7 | |
111 | bic r5, r5, #7 | |
112 | ||
113 | // Start by filling in the easy part of the map. | |
114 | str r4, [r5, #regmap_gp] | |
115 | ||
116 | // Fetch the flags explaining what to do. | |
117 | ldgot | |
118 | leaext r12, regdump__flags | |
119 | ldr r12, [r12] | |
120 | ||
121 | // Figure out whether there are VFP/NEON registers. | |
122 | tst r12, #REGF_VFP | |
123 | moveq r3, #0 | |
124 | addne r3, r5, #regmap_size | |
125 | str r3, [r5, #regmap_fp] | |
126 | beq 9f | |
127 | ||
128 | // Get the FP status register. | |
129 | vmrs r0, fpscr | |
130 | str r0, [r3], #8 | |
131 | ||
132 | // At least the first 16. | |
133 | vstmia r3!, {d0-d15} | |
134 | ||
135 | // Maybe the other 16 too. | |
136 | tst r12, #REGF_D32 | |
137 | vstmiane r3!, {d16-d31} | |
138 | ||
139 | // Done. | |
140 | 9: bx r14 | |
141 | ||
142 | ENDFUNC | |
143 | ||
144 | FUNC(regdump_xtrstr) | |
145 | endprologue | |
146 | // On entry, r5 points to a register-save map. On exit, the extended | |
147 | // registers are restored from the save area, r4 (pointing to the | |
148 | // general-purpose save area) is preserved, and the other general | |
149 | // registers are clobbered. | |
150 | ||
151 | // Fetch the flags explaining what to do. | |
152 | ldgot | |
153 | leaext r12, regdump__flags | |
154 | ldr r12, [r12] | |
155 | ||
156 | // Figure out if there are VFP/NEON registers. | |
157 | tst r12, #REGF_VFP | |
158 | beq 9f | |
159 | ldr r3, [r5, #regmap_fp] | |
160 | ||
161 | // Load the FP status register. | |
162 | ldr r0, [r3], #8 | |
163 | vmsr fpscr, r0 | |
164 | ||
165 | // Load the first 16 registers. | |
166 | vldmia r3!, {d0-d15} | |
167 | ||
168 | // And maybe the other 16. | |
169 | tst r12, #REGF_D32 | |
170 | vldmiane r3!, {d16-d31} | |
171 | ||
172 | // Done. | |
173 | 9: bx r14 | |
174 | ||
175 | ENDFUNC | |
176 | ||
177 | ///----- That's all, folks -------------------------------------------------- |