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