Home | History | Annotate | Line # | Download | only in arch
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