Fix for PR gdb/209, PR gdb/156:
[deliverable/binutils-gdb.git] / gdb / cris-tdep.c
index 63c83cb0a13a05a426e94778e139ff37d5b47d02..9159127c0a852256f2deba82f57cac6181bf1954 100644 (file)
@@ -352,10 +352,10 @@ cris_set_size_to_dword (unsigned short *insn)
   *insn |= 0x20; 
 }
 
-static char
+static signed char
 cris_get_signed_offset (unsigned short insn)
 {
-  return ((char) (insn & 0x00FF));
+  return ((signed char) (insn & 0x00FF));
 }
 
 /* Calls an op function given the op-type, working on the insn and the
@@ -1613,26 +1613,30 @@ constraint (unsigned int insn, const signed char *inst_args,
 
       case 'P':
         tmp = (insn >> 0xC) & 0xF;
-        for (i = 0; i < NUM_SPECREGS; i++)
-          /* Since we match four bits, we will give a value of
-             4 - 1 = 3 in a match.  If there is a corresponding
-             exact match of a special register in another pattern, it
-             will get a value of 4, which will be higher.  This should
-             be correct in that an exact pattern would match better that
-             a general pattern.
-             Note that there is a reason for not returning zero; the
-             pattern for "clear" is partly  matched in the bit-pattern
-             (the two lower bits must be zero), while the bit-pattern
-             for a move from a special register is matched in the
-             register constraint.
-             This also means we will will have a race condition if
-             there is a partly match in three bits in the bit pattern.  */
-          if (tmp == cris_spec_regs[i].number)
-            {
-              retval += 3;
-              break;
-            }
-        if (i == NUM_SPECREGS)
+
+        for (i = 0; cris_spec_regs[i].name != NULL; i++)
+          {
+            /* Since we match four bits, we will give a value of
+               4 - 1 = 3 in a match.  If there is a corresponding
+               exact match of a special register in another pattern, it
+               will get a value of 4, which will be higher.  This should
+               be correct in that an exact pattern would match better that
+               a general pattern.
+               Note that there is a reason for not returning zero; the
+               pattern for "clear" is partly  matched in the bit-pattern
+               (the two lower bits must be zero), while the bit-pattern
+               for a move from a special register is matched in the
+               register constraint.
+               This also means we will will have a race condition if
+               there is a partly match in three bits in the bit pattern.  */
+            if (tmp == cris_spec_regs[i].number)
+              {
+                retval += 3;
+                break;
+              }
+          }
+        
+        if (cris_spec_regs[i].name == NULL)
           return -1;
         break;
       }
@@ -1872,17 +1876,22 @@ bdap_prefix (unsigned short inst, inst_env_type *inst_env)
       return; 
     }
 
-  if (cris_get_mode (inst) == AUTOINC_MODE)
-    {
-      process_autoincrement (cris_get_size (inst), inst, inst_env); 
-    }
-    
+  /* The calculation of prefix_value used to be after process_autoincrement,
+     but that fails for an instruction such as jsr [$r0+12] which is encoded
+     as 5f0d 0c00 30b9 when compiled with -fpic.  Since PC is operand1 it
+     mustn't be incremented until we have read it and what it points at.  */
   inst_env->prefix_value = inst_env->reg[cris_get_operand2 (inst)];
 
   /* The offset is an indirection of the contents of the operand1 register.  */
   inst_env->prefix_value += 
-    read_memory_integer (inst_env->reg[cris_get_operand1 (inst)], cris_get_size (inst));
-  
+    read_memory_integer (inst_env->reg[cris_get_operand1 (inst)], 
+                         cris_get_size (inst));
+
+  if (cris_get_mode (inst) == AUTOINC_MODE)
+    {
+      process_autoincrement (cris_get_size (inst), inst, inst_env); 
+    }
+   
   /* A prefix doesn't change the xflag_found.  But the rest of the flags
      need updating.  */
   inst_env->slot_needed = 0;
@@ -3070,7 +3079,7 @@ reg_mode_add_sub_cmp_and_or_move_op (unsigned short inst,
           return;
         }
       /* The instruction has the PC as its target register.  */
-      operand1 = inst_env->reg[operand1]; 
+      operand1 = inst_env->reg[cris_get_operand1 (inst)]; 
       operand2 = inst_env->reg[REG_PC];
 
       /* Check if it's a extend, signed or zero instruction.  */
This page took 0.024418 seconds and 4 git commands to generate.