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