target/arm920t: remove command 'arm920t cp15i' deprecated in v0.4.0
[fw/openocd] / src / target / armv8_dpm.c
index e5d10df6e791d6a6e16119bba3d446d230e15e1c..1e88a445fdbc8bcd36f782ae82a356c1da3f79b9 100644 (file)
@@ -253,12 +253,12 @@ static int dpmv8_exec_opcode(struct arm_dpm *dpm,
        /* update dscr and el after each command execution */
        dpm->dscr = dscr;
        if (dpm->last_el != ((dscr >> 8) & 3))
-               LOG_DEBUG("EL %i -> %i", dpm->last_el, (dscr >> 8) & 3);
+               LOG_DEBUG("EL %i -> %" PRIu32, dpm->last_el, (dscr >> 8) & 3);
        dpm->last_el = (dscr >> 8) & 3;
 
        if (dscr & DSCR_ERR) {
-               LOG_ERROR("Opcode 0x%08"PRIx32", DSCR.ERR=1, DSCR.EL=%i", opcode, dpm->last_el);
-               armv8_dpm_handle_exception(dpm);
+               LOG_ERROR("Opcode 0x%08" PRIx32 ", DSCR.ERR=1, DSCR.EL=%i", opcode, dpm->last_el);
+               armv8_dpm_handle_exception(dpm, true);
                retval = ERROR_FAIL;
        }
 
@@ -560,13 +560,8 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
                LOG_DEBUG("restoring mode, cpsr = 0x%08"PRIx32, cpsr);
 
        } else {
-               LOG_DEBUG("setting mode 0x%"PRIx32, mode);
-
-               /* else force to the specified mode */
-               if (is_arm_mode(mode))
-                       cpsr = mode;
-               else
-                       cpsr = mode >> 4;
+               LOG_DEBUG("setting mode 0x%x", mode);
+               cpsr = mode;
        }
 
        switch (cpsr & 0x1f) {
@@ -578,6 +573,7 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
        case ARM_MODE_ABT:
        case ARM_MODE_IRQ:
        case ARM_MODE_FIQ:
+       case ARM_MODE_SYS:
                target_el = 1;
                break;
        /*
@@ -605,7 +601,7 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
                                armv8_opcode(armv8, ARMV8_OPC_DCPS) | target_el);
 
                /* DCPS clobbers registers just like an exception taken */
-               armv8_dpm_handle_exception(dpm);
+               armv8_dpm_handle_exception(dpm, false);
        } else {
                core_state = armv8_dpm_get_core_state(dpm);
                if (core_state != ARM_STATE_AARCH64) {
@@ -655,21 +651,41 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
 static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
 {
        struct armv8_common *armv8 = dpm->arm->arch_info;
-       uint64_t value_64;
-       int retval;
+       int retval = ERROR_FAIL;
+
+       if (r->size <= 64) {
+               uint64_t value_64;
+               retval = armv8->read_reg_u64(armv8, regnum, &value_64);
+
+               if (retval == ERROR_OK) {
+                       r->valid = true;
+                       r->dirty = false;
+                       buf_set_u64(r->value, 0, r->size, value_64);
+                       if (r->size == 64)
+                               LOG_DEBUG("READ: %s, %16.8llx", r->name, (unsigned long long) value_64);
+                       else
+                               LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned int) value_64);
+               }
+       } else if (r->size <= 128) {
+               uint64_t lvalue = 0, hvalue = 0;
+               retval = armv8->read_reg_u128(armv8, regnum, &lvalue, &hvalue);
+
+               if (retval == ERROR_OK) {
+                       r->valid = true;
+                       r->dirty = false;
 
-       retval = armv8->read_reg_u64(armv8, regnum, &value_64);
+                       buf_set_u64(r->value, 0, 64, lvalue);
+                       buf_set_u64(r->value + 8, 0, r->size - 64, hvalue);
 
-       if (retval == ERROR_OK) {
-               r->valid = true;
-               r->dirty = false;
-               buf_set_u64(r->value, 0, r->size, value_64);
-               if (r->size == 64)
-                       LOG_DEBUG("READ: %s, %16.8llx", r->name, (unsigned long long) value_64);
-               else
-                       LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned int) value_64);
+                       LOG_DEBUG("READ: %s, lvalue=%16.8llx", r->name, (unsigned long long) lvalue);
+                       LOG_DEBUG("READ: %s, hvalue=%16.8llx", r->name, (unsigned long long) hvalue);
+               }
        }
-       return ERROR_OK;
+
+       if (retval != ERROR_OK)
+               LOG_ERROR("Failed to read %s register", r->name);
+
+       return retval;
 }
 
 /*
@@ -679,24 +695,43 @@ static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
 {
        struct armv8_common *armv8 = dpm->arm->arch_info;
        int retval = ERROR_FAIL;
-       uint64_t value_64;
 
-       value_64 = buf_get_u64(r->value, 0, r->size);
+       if (r->size <= 64) {
+               uint64_t value_64;
+
+               value_64 = buf_get_u64(r->value, 0, r->size);
+               retval = armv8->write_reg_u64(armv8, regnum, value_64);
+
+               if (retval == ERROR_OK) {
+                       r->dirty = false;
+                       if (r->size == 64)
+                               LOG_DEBUG("WRITE: %s, %16.8llx", r->name, (unsigned long long)value_64);
+                       else
+                               LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned int)value_64);
+               }
+       } else if (r->size <= 128) {
+               uint64_t lvalue, hvalue;
+
+               lvalue = buf_get_u64(r->value, 0, 64);
+               hvalue = buf_get_u64(r->value + 8, 0, r->size - 64);
+               retval = armv8->write_reg_u128(armv8, regnum, lvalue, hvalue);
+
+               if (retval == ERROR_OK) {
+                       r->dirty = false;
 
-       retval = armv8->write_reg_u64(armv8, regnum, value_64);
-       if (retval == ERROR_OK) {
-               r->dirty = false;
-               if (r->size == 64)
-                       LOG_DEBUG("WRITE: %s, %16.8llx", r->name, (unsigned long long)value_64);
-               else
-                       LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned int)value_64);
+                       LOG_DEBUG("WRITE: %s, lvalue=%16.8llx", r->name, (unsigned long long) lvalue);
+                       LOG_DEBUG("WRITE: %s, hvalue=%16.8llx", r->name, (unsigned long long) hvalue);
+               }
        }
 
-       return ERROR_OK;
+       if (retval != ERROR_OK)
+               LOG_ERROR("Failed to write %s register", r->name);
+
+       return retval;
 }
 
 /**
- * Read basic registers of the the current context:  R0 to R15, and CPSR;
+ * Read basic registers of the current context:  R0 to R15, and CPSR;
  * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
  * In normal operation this is called on entry to halting debug state,
  * possibly after some other operations supporting restore of debug state
@@ -750,6 +785,10 @@ int armv8_dpm_read_current_registers(struct arm_dpm *dpm)
                if (r->valid)
                        continue;
 
+               /* Skip reading FP-SIMD registers */
+               if (r->number >= ARMV8_V0 && r->number <= ARMV8_FPCR)
+                       continue;
+
                /*
                 * Only read registers that are available from the
                 * current EL (or core mode).
@@ -759,6 +798,10 @@ int armv8_dpm_read_current_registers(struct arm_dpm *dpm)
                                dpm->last_el != armv8_curel_from_core_mode(arm_reg->mode))
                        continue;
 
+               /* Special case: ARM_MODE_SYS has no SPSR at EL1 */
+               if (r->number == ARMV8_SPSR_EL1 && arm->core_mode == ARM_MODE_SYS)
+                       continue;
+
                retval = dpmv8_read_reg(dpm, r, i);
                if (retval != ERROR_OK)
                        goto fail;
@@ -1267,7 +1310,7 @@ void armv8_dpm_report_wfar(struct arm_dpm *dpm, uint64_t addr)
  * This function must not perform any actions that trigger another exception
  * or a recursion will happen.
  */
-void armv8_dpm_handle_exception(struct arm_dpm *dpm)
+void armv8_dpm_handle_exception(struct arm_dpm *dpm, bool do_restore)
 {
        struct armv8_common *armv8 = dpm->arm->arch_info;
        struct reg_cache *cache = dpm->arm->core_cache;
@@ -1312,6 +1355,9 @@ void armv8_dpm_handle_exception(struct arm_dpm *dpm)
        core_state = armv8_dpm_get_core_state(dpm);
        armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64);
        armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64);
+
+       if (do_restore)
+               armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
 }
 
 /*----------------------------------------------------------------------*/
@@ -1342,13 +1388,15 @@ void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr)
                case DSCRV8_ENTRY_BKPT: /* SW BKPT (?) */
                case DSCRV8_ENTRY_RESET_CATCH:  /* Reset catch */
                case DSCRV8_ENTRY_OS_UNLOCK:  /*OS unlock catch*/
-               case DSCRV8_ENTRY_EXCEPTION_CATCH:  /*exception catch*/
                case DSCRV8_ENTRY_SW_ACCESS_DBG: /*SW access dbg register*/
                        target->debug_reason = DBG_REASON_BREAKPOINT;
                        break;
                case DSCRV8_ENTRY_WATCHPOINT:   /* asynch watchpoint */
                        target->debug_reason = DBG_REASON_WATCHPOINT;
                        break;
+               case DSCRV8_ENTRY_EXCEPTION_CATCH:  /*exception catch*/
+                       target->debug_reason = DBG_REASON_EXC_CATCH;
+                       break;
                default:
                        target->debug_reason = DBG_REASON_UNDEFINED;
                        break;
@@ -1423,10 +1471,10 @@ int armv8_dpm_setup(struct arm_dpm *dpm)
        /* FIXME add vector catch support */
 
        dpm->nbp = 1 + ((dpm->didr >> 12) & 0xf);
-       dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp);
+       dpm->dbp = calloc(dpm->nbp, sizeof(*dpm->dbp));
 
        dpm->nwp = 1 + ((dpm->didr >> 20) & 0xf);
-       dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp);
+       dpm->dwp = calloc(dpm->nwp, sizeof(*dpm->dwp));
 
        if (!dpm->dbp || !dpm->dwp) {
                free(dpm->dbp);