arm.c revision 1.1.1.4 1 1.1 christos /* Common target dependent code for GDB on ARM systems.
2 1.1 christos
3 1.1.1.4 christos Copyright (C) 1988-2020 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.4 christos #include "gdbsupport/common-defs.h"
21 1.1.1.4 christos #include "gdbsupport/common-regcache.h"
22 1.1 christos #include "arm.h"
23 1.1 christos
24 1.1.1.4 christos #include "../features/arm/arm-core.c"
25 1.1.1.4 christos #include "../features/arm/arm-vfpv2.c"
26 1.1.1.4 christos #include "../features/arm/arm-vfpv3.c"
27 1.1.1.4 christos #include "../features/arm/xscale-iwmmxt.c"
28 1.1.1.4 christos #include "../features/arm/arm-m-profile.c"
29 1.1.1.4 christos #include "../features/arm/arm-m-profile-with-fpa.c"
30 1.1.1.4 christos
31 1.1 christos /* See arm.h. */
32 1.1 christos
33 1.1 christos int
34 1.1 christos thumb_insn_size (unsigned short inst1)
35 1.1 christos {
36 1.1 christos if ((inst1 & 0xe000) == 0xe000 && (inst1 & 0x1800) != 0)
37 1.1 christos return 4;
38 1.1 christos else
39 1.1 christos return 2;
40 1.1 christos }
41 1.1 christos
42 1.1 christos /* See arm.h. */
43 1.1 christos
44 1.1 christos int
45 1.1 christos condition_true (unsigned long cond, unsigned long status_reg)
46 1.1 christos {
47 1.1 christos if (cond == INST_AL || cond == INST_NV)
48 1.1 christos return 1;
49 1.1 christos
50 1.1 christos switch (cond)
51 1.1 christos {
52 1.1 christos case INST_EQ:
53 1.1 christos return ((status_reg & FLAG_Z) != 0);
54 1.1 christos case INST_NE:
55 1.1 christos return ((status_reg & FLAG_Z) == 0);
56 1.1 christos case INST_CS:
57 1.1 christos return ((status_reg & FLAG_C) != 0);
58 1.1 christos case INST_CC:
59 1.1 christos return ((status_reg & FLAG_C) == 0);
60 1.1 christos case INST_MI:
61 1.1 christos return ((status_reg & FLAG_N) != 0);
62 1.1 christos case INST_PL:
63 1.1 christos return ((status_reg & FLAG_N) == 0);
64 1.1 christos case INST_VS:
65 1.1 christos return ((status_reg & FLAG_V) != 0);
66 1.1 christos case INST_VC:
67 1.1 christos return ((status_reg & FLAG_V) == 0);
68 1.1 christos case INST_HI:
69 1.1 christos return ((status_reg & (FLAG_C | FLAG_Z)) == FLAG_C);
70 1.1 christos case INST_LS:
71 1.1 christos return ((status_reg & (FLAG_C | FLAG_Z)) != FLAG_C);
72 1.1 christos case INST_GE:
73 1.1 christos return (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0));
74 1.1 christos case INST_LT:
75 1.1 christos return (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0));
76 1.1 christos case INST_GT:
77 1.1 christos return (((status_reg & FLAG_Z) == 0)
78 1.1 christos && (((status_reg & FLAG_N) == 0)
79 1.1 christos == ((status_reg & FLAG_V) == 0)));
80 1.1 christos case INST_LE:
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 }
85 1.1 christos return 1;
86 1.1 christos }
87 1.1 christos
88 1.1 christos
89 1.1 christos /* See arm.h. */
90 1.1 christos
91 1.1 christos int
92 1.1 christos thumb_advance_itstate (unsigned int itstate)
93 1.1 christos {
94 1.1 christos /* Preserve IT[7:5], the first three bits of the condition. Shift
95 1.1 christos the upcoming condition flags left by one bit. */
96 1.1 christos itstate = (itstate & 0xe0) | ((itstate << 1) & 0x1f);
97 1.1 christos
98 1.1 christos /* If we have finished the IT block, clear the state. */
99 1.1 christos if ((itstate & 0x0f) == 0)
100 1.1 christos itstate = 0;
101 1.1 christos
102 1.1 christos return itstate;
103 1.1 christos }
104 1.1 christos
105 1.1 christos /* See arm.h. */
106 1.1 christos
107 1.1 christos int
108 1.1 christos arm_instruction_changes_pc (uint32_t this_instr)
109 1.1 christos {
110 1.1 christos if (bits (this_instr, 28, 31) == INST_NV)
111 1.1 christos /* Unconditional instructions. */
112 1.1 christos switch (bits (this_instr, 24, 27))
113 1.1 christos {
114 1.1 christos case 0xa:
115 1.1 christos case 0xb:
116 1.1 christos /* Branch with Link and change to Thumb. */
117 1.1 christos return 1;
118 1.1 christos case 0xc:
119 1.1 christos case 0xd:
120 1.1 christos case 0xe:
121 1.1 christos /* Coprocessor register transfer. */
122 1.1 christos if (bits (this_instr, 12, 15) == 15)
123 1.1 christos error (_("Invalid update to pc in instruction"));
124 1.1 christos return 0;
125 1.1 christos default:
126 1.1 christos return 0;
127 1.1 christos }
128 1.1 christos else
129 1.1 christos switch (bits (this_instr, 25, 27))
130 1.1 christos {
131 1.1 christos case 0x0:
132 1.1 christos if (bits (this_instr, 23, 24) == 2 && bit (this_instr, 20) == 0)
133 1.1 christos {
134 1.1 christos /* Multiplies and extra load/stores. */
135 1.1 christos if (bit (this_instr, 4) == 1 && bit (this_instr, 7) == 1)
136 1.1 christos /* Neither multiplies nor extension load/stores are allowed
137 1.1 christos to modify PC. */
138 1.1 christos return 0;
139 1.1 christos
140 1.1 christos /* Otherwise, miscellaneous instructions. */
141 1.1 christos
142 1.1 christos /* BX <reg>, BXJ <reg>, BLX <reg> */
143 1.1 christos if (bits (this_instr, 4, 27) == 0x12fff1
144 1.1 christos || bits (this_instr, 4, 27) == 0x12fff2
145 1.1 christos || bits (this_instr, 4, 27) == 0x12fff3)
146 1.1 christos return 1;
147 1.1 christos
148 1.1 christos /* Other miscellaneous instructions are unpredictable if they
149 1.1 christos modify PC. */
150 1.1 christos return 0;
151 1.1 christos }
152 1.1.1.3 christos /* Data processing instruction. */
153 1.1.1.3 christos /* Fall through. */
154 1.1 christos
155 1.1 christos case 0x1:
156 1.1 christos if (bits (this_instr, 12, 15) == 15)
157 1.1 christos return 1;
158 1.1 christos else
159 1.1 christos return 0;
160 1.1 christos
161 1.1 christos case 0x2:
162 1.1 christos case 0x3:
163 1.1 christos /* Media instructions and architecturally undefined instructions. */
164 1.1 christos if (bits (this_instr, 25, 27) == 3 && bit (this_instr, 4) == 1)
165 1.1 christos return 0;
166 1.1 christos
167 1.1 christos /* Stores. */
168 1.1 christos if (bit (this_instr, 20) == 0)
169 1.1 christos return 0;
170 1.1 christos
171 1.1 christos /* Loads. */
172 1.1 christos if (bits (this_instr, 12, 15) == ARM_PC_REGNUM)
173 1.1 christos return 1;
174 1.1 christos else
175 1.1 christos return 0;
176 1.1 christos
177 1.1 christos case 0x4:
178 1.1 christos /* Load/store multiple. */
179 1.1 christos if (bit (this_instr, 20) == 1 && bit (this_instr, 15) == 1)
180 1.1 christos return 1;
181 1.1 christos else
182 1.1 christos return 0;
183 1.1 christos
184 1.1 christos case 0x5:
185 1.1 christos /* Branch and branch with link. */
186 1.1 christos return 1;
187 1.1 christos
188 1.1 christos case 0x6:
189 1.1 christos case 0x7:
190 1.1 christos /* Coprocessor transfers or SWIs can not affect PC. */
191 1.1 christos return 0;
192 1.1 christos
193 1.1 christos default:
194 1.1 christos internal_error (__FILE__, __LINE__, _("bad value in switch"));
195 1.1 christos }
196 1.1 christos }
197 1.1 christos
198 1.1 christos /* See arm.h. */
199 1.1 christos
200 1.1 christos int
201 1.1 christos thumb_instruction_changes_pc (unsigned short inst)
202 1.1 christos {
203 1.1 christos if ((inst & 0xff00) == 0xbd00) /* pop {rlist, pc} */
204 1.1 christos return 1;
205 1.1 christos
206 1.1 christos if ((inst & 0xf000) == 0xd000) /* conditional branch */
207 1.1 christos return 1;
208 1.1 christos
209 1.1 christos if ((inst & 0xf800) == 0xe000) /* unconditional branch */
210 1.1 christos return 1;
211 1.1 christos
212 1.1 christos if ((inst & 0xff00) == 0x4700) /* bx REG, blx REG */
213 1.1 christos return 1;
214 1.1 christos
215 1.1 christos if ((inst & 0xff87) == 0x4687) /* mov pc, REG */
216 1.1 christos return 1;
217 1.1 christos
218 1.1 christos if ((inst & 0xf500) == 0xb100) /* CBNZ or CBZ. */
219 1.1 christos return 1;
220 1.1 christos
221 1.1 christos return 0;
222 1.1 christos }
223 1.1 christos
224 1.1 christos
225 1.1 christos /* See arm.h. */
226 1.1 christos
227 1.1 christos int
228 1.1 christos thumb2_instruction_changes_pc (unsigned short inst1, unsigned short inst2)
229 1.1 christos {
230 1.1 christos if ((inst1 & 0xf800) == 0xf000 && (inst2 & 0x8000) == 0x8000)
231 1.1 christos {
232 1.1 christos /* Branches and miscellaneous control instructions. */
233 1.1 christos
234 1.1 christos if ((inst2 & 0x1000) != 0 || (inst2 & 0xd001) == 0xc000)
235 1.1 christos {
236 1.1 christos /* B, BL, BLX. */
237 1.1 christos return 1;
238 1.1 christos }
239 1.1 christos else if (inst1 == 0xf3de && (inst2 & 0xff00) == 0x3f00)
240 1.1 christos {
241 1.1 christos /* SUBS PC, LR, #imm8. */
242 1.1 christos return 1;
243 1.1 christos }
244 1.1 christos else if ((inst2 & 0xd000) == 0x8000 && (inst1 & 0x0380) != 0x0380)
245 1.1 christos {
246 1.1 christos /* Conditional branch. */
247 1.1 christos return 1;
248 1.1 christos }
249 1.1 christos
250 1.1 christos return 0;
251 1.1 christos }
252 1.1 christos
253 1.1 christos if ((inst1 & 0xfe50) == 0xe810)
254 1.1 christos {
255 1.1 christos /* Load multiple or RFE. */
256 1.1 christos
257 1.1 christos if (bit (inst1, 7) && !bit (inst1, 8))
258 1.1 christos {
259 1.1 christos /* LDMIA or POP */
260 1.1 christos if (bit (inst2, 15))
261 1.1 christos return 1;
262 1.1 christos }
263 1.1 christos else if (!bit (inst1, 7) && bit (inst1, 8))
264 1.1 christos {
265 1.1 christos /* LDMDB */
266 1.1 christos if (bit (inst2, 15))
267 1.1 christos return 1;
268 1.1 christos }
269 1.1 christos else if (bit (inst1, 7) && bit (inst1, 8))
270 1.1 christos {
271 1.1 christos /* RFEIA */
272 1.1 christos return 1;
273 1.1 christos }
274 1.1 christos else if (!bit (inst1, 7) && !bit (inst1, 8))
275 1.1 christos {
276 1.1 christos /* RFEDB */
277 1.1 christos return 1;
278 1.1 christos }
279 1.1 christos
280 1.1 christos return 0;
281 1.1 christos }
282 1.1 christos
283 1.1 christos if ((inst1 & 0xffef) == 0xea4f && (inst2 & 0xfff0) == 0x0f00)
284 1.1 christos {
285 1.1 christos /* MOV PC or MOVS PC. */
286 1.1 christos return 1;
287 1.1 christos }
288 1.1 christos
289 1.1 christos if ((inst1 & 0xff70) == 0xf850 && (inst2 & 0xf000) == 0xf000)
290 1.1 christos {
291 1.1 christos /* LDR PC. */
292 1.1 christos if (bits (inst1, 0, 3) == 15)
293 1.1 christos return 1;
294 1.1 christos if (bit (inst1, 7))
295 1.1 christos return 1;
296 1.1 christos if (bit (inst2, 11))
297 1.1 christos return 1;
298 1.1 christos if ((inst2 & 0x0fc0) == 0x0000)
299 1.1 christos return 1;
300 1.1 christos
301 1.1 christos return 0;
302 1.1 christos }
303 1.1 christos
304 1.1 christos if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf000)
305 1.1 christos {
306 1.1 christos /* TBB. */
307 1.1 christos return 1;
308 1.1 christos }
309 1.1 christos
310 1.1 christos if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf010)
311 1.1 christos {
312 1.1 christos /* TBH. */
313 1.1 christos return 1;
314 1.1 christos }
315 1.1 christos
316 1.1 christos return 0;
317 1.1 christos }
318 1.1 christos
319 1.1 christos /* See arm.h. */
320 1.1 christos
321 1.1 christos unsigned long
322 1.1 christos shifted_reg_val (struct regcache *regcache, unsigned long inst,
323 1.1 christos int carry, unsigned long pc_val, unsigned long status_reg)
324 1.1 christos {
325 1.1 christos unsigned long res, shift;
326 1.1 christos int rm = bits (inst, 0, 3);
327 1.1 christos unsigned long shifttype = bits (inst, 5, 6);
328 1.1 christos
329 1.1 christos if (bit (inst, 4))
330 1.1 christos {
331 1.1 christos int rs = bits (inst, 8, 11);
332 1.1 christos shift = (rs == 15
333 1.1 christos ? pc_val + 8
334 1.1 christos : regcache_raw_get_unsigned (regcache, rs)) & 0xFF;
335 1.1 christos }
336 1.1 christos else
337 1.1 christos shift = bits (inst, 7, 11);
338 1.1 christos
339 1.1 christos res = (rm == ARM_PC_REGNUM
340 1.1 christos ? (pc_val + (bit (inst, 4) ? 12 : 8))
341 1.1 christos : regcache_raw_get_unsigned (regcache, rm));
342 1.1 christos
343 1.1 christos switch (shifttype)
344 1.1 christos {
345 1.1 christos case 0: /* LSL */
346 1.1 christos res = shift >= 32 ? 0 : res << shift;
347 1.1 christos break;
348 1.1 christos
349 1.1 christos case 1: /* LSR */
350 1.1 christos res = shift >= 32 ? 0 : res >> shift;
351 1.1 christos break;
352 1.1 christos
353 1.1 christos case 2: /* ASR */
354 1.1 christos if (shift >= 32)
355 1.1 christos shift = 31;
356 1.1 christos res = ((res & 0x80000000L)
357 1.1 christos ? ~((~res) >> shift) : res >> shift);
358 1.1 christos break;
359 1.1 christos
360 1.1 christos case 3: /* ROR/RRX */
361 1.1 christos shift &= 31;
362 1.1 christos if (shift == 0)
363 1.1 christos res = (res >> 1) | (carry ? 0x80000000L : 0);
364 1.1 christos else
365 1.1 christos res = (res >> shift) | (res << (32 - shift));
366 1.1 christos break;
367 1.1 christos }
368 1.1 christos
369 1.1 christos return res & 0xffffffff;
370 1.1 christos }
371 1.1.1.4 christos
372 1.1.1.4 christos /* See arch/arm.h. */
373 1.1.1.4 christos
374 1.1.1.4 christos target_desc *
375 1.1.1.4 christos arm_create_target_description (arm_fp_type fp_type)
376 1.1.1.4 christos {
377 1.1.1.4 christos target_desc *tdesc = allocate_target_description ();
378 1.1.1.4 christos
379 1.1.1.4 christos #ifndef IN_PROCESS_AGENT
380 1.1.1.4 christos if (fp_type == ARM_FP_TYPE_IWMMXT)
381 1.1.1.4 christos set_tdesc_architecture (tdesc, "iwmmxt");
382 1.1.1.4 christos else
383 1.1.1.4 christos set_tdesc_architecture (tdesc, "arm");
384 1.1.1.4 christos #endif
385 1.1.1.4 christos
386 1.1.1.4 christos long regnum = 0;
387 1.1.1.4 christos
388 1.1.1.4 christos regnum = create_feature_arm_arm_core (tdesc, regnum);
389 1.1.1.4 christos
390 1.1.1.4 christos switch (fp_type)
391 1.1.1.4 christos {
392 1.1.1.4 christos case ARM_FP_TYPE_NONE:
393 1.1.1.4 christos break;
394 1.1.1.4 christos
395 1.1.1.4 christos case ARM_FP_TYPE_VFPV2:
396 1.1.1.4 christos regnum = create_feature_arm_arm_vfpv2 (tdesc, regnum);
397 1.1.1.4 christos break;
398 1.1.1.4 christos
399 1.1.1.4 christos case ARM_FP_TYPE_VFPV3:
400 1.1.1.4 christos regnum = create_feature_arm_arm_vfpv3 (tdesc, regnum);
401 1.1.1.4 christos break;
402 1.1.1.4 christos
403 1.1.1.4 christos case ARM_FP_TYPE_IWMMXT:
404 1.1.1.4 christos regnum = create_feature_arm_xscale_iwmmxt (tdesc, regnum);
405 1.1.1.4 christos break;
406 1.1.1.4 christos
407 1.1.1.4 christos default:
408 1.1.1.4 christos error (_("Invalid Arm FP type: %d"), fp_type);
409 1.1.1.4 christos }
410 1.1.1.4 christos
411 1.1.1.4 christos return tdesc;
412 1.1.1.4 christos }
413 1.1.1.4 christos
414 1.1.1.4 christos /* See arch/arm.h. */
415 1.1.1.4 christos
416 1.1.1.4 christos target_desc *
417 1.1.1.4 christos arm_create_mprofile_target_description (arm_m_profile_type m_type)
418 1.1.1.4 christos {
419 1.1.1.4 christos target_desc *tdesc = allocate_target_description ();
420 1.1.1.4 christos
421 1.1.1.4 christos #ifndef IN_PROCESS_AGENT
422 1.1.1.4 christos set_tdesc_architecture (tdesc, "arm");
423 1.1.1.4 christos #endif
424 1.1.1.4 christos
425 1.1.1.4 christos long regnum = 0;
426 1.1.1.4 christos
427 1.1.1.4 christos switch (m_type)
428 1.1.1.4 christos {
429 1.1.1.4 christos case ARM_M_TYPE_M_PROFILE:
430 1.1.1.4 christos regnum = create_feature_arm_arm_m_profile (tdesc, regnum);
431 1.1.1.4 christos break;
432 1.1.1.4 christos
433 1.1.1.4 christos case ARM_M_TYPE_VFP_D16:
434 1.1.1.4 christos regnum = create_feature_arm_arm_m_profile (tdesc, regnum);
435 1.1.1.4 christos regnum = create_feature_arm_arm_vfpv2 (tdesc, regnum);
436 1.1.1.4 christos break;
437 1.1.1.4 christos
438 1.1.1.4 christos case ARM_M_TYPE_WITH_FPA:
439 1.1.1.4 christos regnum = create_feature_arm_arm_m_profile_with_fpa (tdesc, regnum);
440 1.1.1.4 christos break;
441 1.1.1.4 christos
442 1.1.1.4 christos default:
443 1.1.1.4 christos error (_("Invalid Arm M type: %d"), m_type);
444 1.1.1.4 christos }
445 1.1.1.4 christos
446 1.1.1.4 christos return tdesc;
447 1.1.1.4 christos }
448