]> git.sur5r.net Git - openocd/commitdiff
ARM: semihosting entry cleanup
authorDavid Brownell <dbrownell@users.sourceforge.net>
Sat, 5 Dec 2009 00:51:48 +0000 (16:51 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Sat, 5 Dec 2009 00:51:48 +0000 (16:51 -0800)
Clean up arm_semihosting() entry a bit, comment some issues and just
which SVC opcodes are getting intercepted.  Microcontroller profile
cores will need a new entry, since they use BKPT instead (and don't
have either SVC mode or an SPSR register).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
src/target/arm_semihosting.c

index 4788686296f265f333f8145ef73d15aef5c5c398..7fe0a973c92abdc3f580f9f979ea7e700f2fed54 100644 (file)
@@ -56,6 +56,9 @@ static int do_semihosting(struct target *target)
         * - no validation on target provided file descriptors
         * - no safety checks on opened/deleted/renamed file paths
         * Beware the target app you use this support with.
+        *
+        * TODO: explore mapping requests to GDB's "File-I/O Remote
+        * Protocol Extension" ... when GDB is active.
         */
        switch (r0) {
        case 0x01:      /* SYS_OPEN */
@@ -396,42 +399,70 @@ static int do_semihosting(struct target *target)
  * or an error was encountered, in which case the caller must return
  * immediately.
  *
- * @param target Pointer to the ARM target to process
+ * @param target Pointer to the ARM target to process.  This target must
+ *     not represent an ARMv6-M or ARMv7-M processor.
  * @param retval Pointer to a location where the return code will be stored
  * @return non-zero value if a request was processed or an error encountered
  */
 int arm_semihosting(struct target *target, int *retval)
 {
-       struct arm *armv4_5 = target_to_armv4_5(target);
+       struct arm *arm = target_to_armv4_5(target);
        uint32_t lr, spsr;
+       struct reg *r;
+
+       if (!arm->is_semihosting || arm->core_mode != ARMV4_5_MODE_SVC)
+               return 0;
 
-       if (!armv4_5->is_semihosting ||
-           armv4_5->core_mode != ARMV4_5_MODE_SVC ||
-           buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) != 0x08)
+       /* Check for PC == 8:  Supervisor Call vector
+        * REVISIT:  assumes low exception vectors, not hivecs...
+        * safer to test "was this entry from a vector catch".
+        */
+       r = arm->core_cache->reg_list + 15;
+       if (buf_get_u32(r->value, 0, 32) != 0x08)
                return 0;
 
-       lr = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, ARMV4_5_MODE_SVC, 14).value, 0, 32);
-       spsr = buf_get_u32(armv4_5->spsr->value, 0, 32);
+       r = arm_reg_current(arm, 14);
+       lr = buf_get_u32(r->value, 0, 32);
+
+       /* Core-specific code should make sure SPSR is retrieved
+        * when the above checks pass...
+        */
+       if (!arm->spsr->valid) {
+               LOG_ERROR("SPSR not valid!");
+               *retval = ERROR_FAIL;
+               return 1;
+       }
+
+       spsr = buf_get_u32(arm->spsr->value, 0, 32);
 
        /* check instruction that triggered this trap */
        if (spsr & (1 << 5)) {
-               /* was in Thumb mode */
+               /* was in Thumb (or ThumbEE) mode */
                uint8_t insn_buf[2];
                uint16_t insn;
+
                *retval = target_read_memory(target, lr-2, 2, 1, insn_buf);
                if (*retval != ERROR_OK)
                        return 1;
                insn = target_buffer_get_u16(target, insn_buf);
+
+               /* SVC 0xab */
                if (insn != 0xDFAB)
                        return 0;
+       } else if (spsr & (1 << 24)) {
+               /* was in Jazelle mode */
+               return 0;
        } else {
                /* was in ARM mode */
                uint8_t insn_buf[4];
                uint32_t insn;
+
                *retval = target_read_memory(target, lr-4, 4, 1, insn_buf);
                if (*retval != ERROR_OK)
                        return 1;
                insn = target_buffer_get_u32(target, insn_buf);
+
+               /* SVC 0x123456 */
                if (insn != 0xEF123456)
                        return 0;
        }