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 | ||
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 -------------------------------------------------- |