arm.c revision 1.1.1.3 1 1.1 christos /* Common target dependent code for GDB on ARM systems.
2 1.1 christos
3 1.1.1.3 christos Copyright (C) 1988-2019 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of GDB.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 1.1 christos
20 1.1.1.3 christos #include "common/common-defs.h"
21 1.1.1.3 christos #include "common/common-regcache.h"
22 1.1 christos #include "arm.h"
23 1.1 christos
24 1.1 christos /* See arm.h. */
25 1.1 christos
26 1.1 christos int
27 1.1 christos thumb_insn_size (unsigned short inst1)
28 1.1 christos {
29 1.1 christos if ((inst1 & 0xe000) == 0xe000 && (inst1 & 0x1800) != 0)
30 1.1 christos return 4;
31 1.1 christos else
32 1.1 christos return 2;
33 1.1 christos }
34 1.1 christos
35 1.1 christos /* See arm.h. */
36 1.1 christos
37 1.1 christos int
38 1.1 christos bitcount (unsigned long val)
39 1.1 christos {
40 1.1 christos int nbits;
41 1.1 christos for (nbits = 0; val != 0; nbits++)
42 1.1 christos val &= val - 1; /* Delete rightmost 1-bit in val. */
43 1.1 christos return nbits;
44 1.1 christos }
45 1.1 christos
46 1.1 christos /* See arm.h. */
47 1.1 christos
48 1.1 christos int
49 1.1 christos condition_true (unsigned long cond, unsigned long status_reg)
50 1.1 christos {
51 1.1 christos if (cond == INST_AL || cond == INST_NV)
52 1.1 christos return 1;
53 1.1 christos
54 1.1 christos switch (cond)
55 1.1 christos {
56 1.1 christos case INST_EQ:
57 1.1 christos return ((status_reg & FLAG_Z) != 0);
58 1.1 christos case INST_NE:
59 1.1 christos return ((status_reg & FLAG_Z) == 0);
60 1.1 christos case INST_CS:
61 1.1 christos return ((status_reg & FLAG_C) != 0);
62 1.1 christos case INST_CC:
63 1.1 christos return ((status_reg & FLAG_C) == 0);
64 1.1 christos case INST_MI:
65 1.1 christos return ((status_reg & FLAG_N) != 0);
66 1.1 christos case INST_PL:
67 1.1 christos return ((status_reg & FLAG_N) == 0);
68 1.1 christos case INST_VS:
69 1.1 christos return ((status_reg & FLAG_V) != 0);
70 1.1 christos case INST_VC:
71 1.1 christos return ((status_reg & FLAG_V) == 0);
72 1.1 christos case INST_HI:
73 1.1 christos return ((status_reg & (FLAG_C | FLAG_Z)) == FLAG_C);
74 1.1 christos case INST_LS:
75 1.1 christos return ((status_reg & (FLAG_C | FLAG_Z)) != FLAG_C);
76 1.1 christos case INST_GE:
77 1.1 christos return (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0));
78 1.1 christos case INST_LT:
79 1.1 christos return (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0));
80 1.1 christos case INST_GT:
81 1.1 christos return (((status_reg & FLAG_Z) == 0)
82 1.1 christos && (((status_reg & FLAG_N) == 0)
83 1.1 christos == ((status_reg & FLAG_V) == 0)));
84 1.1 christos case INST_LE:
85 1.1 christos return (((status_reg & FLAG_Z) != 0)
86 1.1 christos || (((status_reg & FLAG_N) == 0)
87 1.1 christos != ((status_reg & FLAG_V) == 0)));
88 1.1 christos }
89 1.1 christos return 1;
90 1.1 christos }
91 1.1 christos
92 1.1 christos
93 1.1 christos /* See arm.h. */
94 1.1 christos
95 1.1 christos int
96 1.1 christos thumb_advance_itstate (unsigned int itstate)
97 1.1 christos {
98 1.1 christos /* Preserve IT[7:5], the first three bits of the condition. Shift
99 1.1 christos the upcoming condition flags left by one bit. */
100 1.1 christos itstate = (itstate & 0xe0) | ((itstate << 1) & 0x1f);
101 1.1 christos
102 1.1 christos /* If we have finished the IT block, clear the state. */
103 1.1 christos if ((itstate & 0x0f) == 0)
104 1.1 christos itstate = 0;
105 1.1 christos
106 1.1 christos return itstate;
107 1.1 christos }
108 1.1 christos
109 1.1 christos /* See arm.h. */
110 1.1 christos
111 1.1 christos int
112 1.1 christos arm_instruction_changes_pc (uint32_t this_instr)
113 1.1 christos {
114 1.1 christos if (bits (this_instr, 28, 31) == INST_NV)
115 1.1 christos /* Unconditional instructions. */
116 1.1 christos switch (bits (this_instr, 24, 27))
117 1.1 christos {
118 1.1 christos case 0xa:
119 1.1 christos case 0xb:
120 1.1 christos /* Branch with Link and change to Thumb. */
121 1.1 christos return 1;
122 1.1 christos case 0xc:
123 1.1 christos case 0xd:
124 1.1 christos case 0xe:
125 1.1 christos /* Coprocessor register transfer. */
126 1.1 christos if (bits (this_instr, 12, 15) == 15)
127 1.1 christos error (_("Invalid update to pc in instruction"));
128 1.1 christos return 0;
129 1.1 christos default:
130 1.1 christos return 0;
131 1.1 christos }
132 1.1 christos else
133 1.1 christos switch (bits (this_instr, 25, 27))
134 1.1 christos {
135 1.1 christos case 0x0:
136 1.1 christos if (bits (this_instr, 23, 24) == 2 && bit (this_instr, 20) == 0)
137 1.1 christos {
138 1.1 christos /* Multiplies and extra load/stores. */
139 1.1 christos if (bit (this_instr, 4) == 1 && bit (this_instr, 7) == 1)
140 1.1 christos /* Neither multiplies nor extension load/stores are allowed
141 1.1 christos to modify PC. */
142 1.1 christos return 0;
143 1.1 christos
144 1.1 christos /* Otherwise, miscellaneous instructions. */
145 1.1 christos
146 1.1 christos /* BX <reg>, BXJ <reg>, BLX <reg> */
147 1.1 christos if (bits (this_instr, 4, 27) == 0x12fff1
148 1.1 christos || bits (this_instr, 4, 27) == 0x12fff2
149 1.1 christos || bits (this_instr, 4, 27) == 0x12fff3)
150 1.1 christos return 1;
151 1.1 christos
152 1.1 christos /* Other miscellaneous instructions are unpredictable if they
153 1.1 christos modify PC. */
154 1.1 christos return 0;
155 1.1 christos }
156 1.1.1.3 christos /* Data processing instruction. */
157 1.1.1.3 christos /* Fall through. */
158 1.1 christos
159 1.1 christos case 0x1:
160 1.1 christos if (bits (this_instr, 12, 15) == 15)
161 1.1 christos return 1;
162 1.1 christos else
163 1.1 christos return 0;
164 1.1 christos
165 1.1 christos case 0x2:
166 1.1 christos case 0x3:
167 1.1 christos /* Media instructions and architecturally undefined instructions. */
168 1.1 christos if (bits (this_instr, 25, 27) == 3 && bit (this_instr, 4) == 1)
169 1.1 christos return 0;
170 1.1 christos
171 1.1 christos /* Stores. */
172 1.1 christos if (bit (this_instr, 20) == 0)
173 1.1 christos return 0;
174 1.1 christos
175 1.1 christos /* Loads. */
176 1.1 christos if (bits (this_instr, 12, 15) == ARM_PC_REGNUM)
177 1.1 christos return 1;
178 1.1 christos else
179 1.1 christos return 0;
180 1.1 christos
181 1.1 christos case 0x4:
182 1.1 christos /* Load/store multiple. */
183 1.1 christos if (bit (this_instr, 20) == 1 && bit (this_instr, 15) == 1)
184 1.1 christos return 1;
185 1.1 christos else
186 1.1 christos return 0;
187 1.1 christos
188 1.1 christos case 0x5:
189 1.1 christos /* Branch and branch with link. */
190 1.1 christos return 1;
191 1.1 christos
192 1.1 christos case 0x6:
193 1.1 christos case 0x7:
194 1.1 christos /* Coprocessor transfers or SWIs can not affect PC. */
195 1.1 christos return 0;
196 1.1 christos
197 1.1 christos default:
198 1.1 christos internal_error (__FILE__, __LINE__, _("bad value in switch"));
199 1.1 christos }
200 1.1 christos }
201 1.1 christos
202 1.1 christos /* See arm.h. */
203 1.1 christos
204 1.1 christos int
205 1.1 christos thumb_instruction_changes_pc (unsigned short inst)
206 1.1 christos {
207 1.1 christos if ((inst & 0xff00) == 0xbd00) /* pop {rlist, pc} */
208 1.1 christos return 1;
209 1.1 christos
210 1.1 christos if ((inst & 0xf000) == 0xd000) /* conditional branch */
211 1.1 christos return 1;
212 1.1 christos
213 1.1 christos if ((inst & 0xf800) == 0xe000) /* unconditional branch */
214 1.1 christos return 1;
215 1.1 christos
216 1.1 christos if ((inst & 0xff00) == 0x4700) /* bx REG, blx REG */
217 1.1 christos return 1;
218 1.1 christos
219 1.1 christos if ((inst & 0xff87) == 0x4687) /* mov pc, REG */
220 1.1 christos return 1;
221 1.1 christos
222 1.1 christos if ((inst & 0xf500) == 0xb100) /* CBNZ or CBZ. */
223 1.1 christos return 1;
224 1.1 christos
225 1.1 christos return 0;
226 1.1 christos }
227 1.1 christos
228 1.1 christos
229 1.1 christos /* See arm.h. */
230 1.1 christos
231 1.1 christos int
232 1.1 christos thumb2_instruction_changes_pc (unsigned short inst1, unsigned short inst2)
233 1.1 christos {
234 1.1 christos if ((inst1 & 0xf800) == 0xf000 && (inst2 & 0x8000) == 0x8000)
235 1.1 christos {
236 1.1 christos /* Branches and miscellaneous control instructions. */
237 1.1 christos
238 1.1 christos if ((inst2 & 0x1000) != 0 || (inst2 & 0xd001) == 0xc000)
239 1.1 christos {
240 1.1 christos /* B, BL, BLX. */
241 1.1 christos return 1;
242 1.1 christos }
243 1.1 christos else if (inst1 == 0xf3de && (inst2 & 0xff00) == 0x3f00)
244 1.1 christos {
245 1.1 christos /* SUBS PC, LR, #imm8. */
246 1.1 christos return 1;
247 1.1 christos }
248 1.1 christos else if ((inst2 & 0xd000) == 0x8000 && (inst1 & 0x0380) != 0x0380)
249 1.1 christos {
250 1.1 christos /* Conditional branch. */
251 1.1 christos return 1;
252 1.1 christos }
253 1.1 christos
254 1.1 christos return 0;
255 1.1 christos }
256 1.1 christos
257 1.1 christos if ((inst1 & 0xfe50) == 0xe810)
258 1.1 christos {
259 1.1 christos /* Load multiple or RFE. */
260 1.1 christos
261 1.1 christos if (bit (inst1, 7) && !bit (inst1, 8))
262 1.1 christos {
263 1.1 christos /* LDMIA or POP */
264 1.1 christos if (bit (inst2, 15))
265 1.1 christos return 1;
266 1.1 christos }
267 1.1 christos else if (!bit (inst1, 7) && bit (inst1, 8))
268 1.1 christos {
269 1.1 christos /* LDMDB */
270 1.1 christos if (bit (inst2, 15))
271 1.1 christos return 1;
272 1.1 christos }
273 1.1 christos else if (bit (inst1, 7) && bit (inst1, 8))
274 1.1 christos {
275 1.1 christos /* RFEIA */
276 1.1 christos return 1;
277 1.1 christos }
278 1.1 christos else if (!bit (inst1, 7) && !bit (inst1, 8))
279 1.1 christos {
280 1.1 christos /* RFEDB */
281 1.1 christos return 1;
282 1.1 christos }
283 1.1 christos
284 1.1 christos return 0;
285 1.1 christos }
286 1.1 christos
287 1.1 christos if ((inst1 & 0xffef) == 0xea4f && (inst2 & 0xfff0) == 0x0f00)
288 1.1 christos {
289 1.1 christos /* MOV PC or MOVS PC. */
290 1.1 christos return 1;
291 1.1 christos }
292 1.1 christos
293 1.1 christos if ((inst1 & 0xff70) == 0xf850 && (inst2 & 0xf000) == 0xf000)
294 1.1 christos {
295 1.1 christos /* LDR PC. */
296 1.1 christos if (bits (inst1, 0, 3) == 15)
297 1.1 christos return 1;
298 1.1 christos if (bit (inst1, 7))
299 1.1 christos return 1;
300 1.1 christos if (bit (inst2, 11))
301 1.1 christos return 1;
302 1.1 christos if ((inst2 & 0x0fc0) == 0x0000)
303 1.1 christos return 1;
304 1.1 christos
305 1.1 christos return 0;
306 1.1 christos }
307 1.1 christos
308 1.1 christos if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf000)
309 1.1 christos {
310 1.1 christos /* TBB. */
311 1.1 christos return 1;
312 1.1 christos }
313 1.1 christos
314 1.1 christos if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf010)
315 1.1 christos {
316 1.1 christos /* TBH. */
317 1.1 christos return 1;
318 1.1 christos }
319 1.1 christos
320 1.1 christos return 0;
321 1.1 christos }
322 1.1 christos
323 1.1 christos /* See arm.h. */
324 1.1 christos
325 1.1 christos unsigned long
326 1.1 christos shifted_reg_val (struct regcache *regcache, unsigned long inst,
327 1.1 christos int carry, unsigned long pc_val, unsigned long status_reg)
328 1.1 christos {
329 1.1 christos unsigned long res, shift;
330 1.1 christos int rm = bits (inst, 0, 3);
331 1.1 christos unsigned long shifttype = bits (inst, 5, 6);
332 1.1 christos
333 1.1 christos if (bit (inst, 4))
334 1.1 christos {
335 1.1 christos int rs = bits (inst, 8, 11);
336 1.1 christos shift = (rs == 15
337 1.1 christos ? pc_val + 8
338 1.1 christos : regcache_raw_get_unsigned (regcache, rs)) & 0xFF;
339 1.1 christos }
340 1.1 christos else
341 1.1 christos shift = bits (inst, 7, 11);
342 1.1 christos
343 1.1 christos res = (rm == ARM_PC_REGNUM
344 1.1 christos ? (pc_val + (bit (inst, 4) ? 12 : 8))
345 1.1 christos : regcache_raw_get_unsigned (regcache, rm));
346 1.1 christos
347 1.1 christos switch (shifttype)
348 1.1 christos {
349 1.1 christos case 0: /* LSL */
350 1.1 christos res = shift >= 32 ? 0 : res << shift;
351 1.1 christos break;
352 1.1 christos
353 1.1 christos case 1: /* LSR */
354 1.1 christos res = shift >= 32 ? 0 : res >> shift;
355 1.1 christos break;
356 1.1 christos
357 1.1 christos case 2: /* ASR */
358 1.1 christos if (shift >= 32)
359 1.1 christos shift = 31;
360 1.1 christos res = ((res & 0x80000000L)
361 1.1 christos ? ~((~res) >> shift) : res >> shift);
362 1.1 christos break;
363 1.1 christos
364 1.1 christos case 3: /* ROR/RRX */
365 1.1 christos shift &= 31;
366 1.1 christos if (shift == 0)
367 1.1 christos res = (res >> 1) | (carry ? 0x80000000L : 0);
368 1.1 christos else
369 1.1 christos res = (res >> shift) | (res << (32 - shift));
370 1.1 christos break;
371 1.1 christos }
372 1.1 christos
373 1.1 christos return res & 0xffffffff;
374 1.1 christos }
375