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