ARM: disassemble two more v6+ instructions
authorDavid Brownell <dbrownell@users.sourceforge.net>
Mon, 7 Dec 2009 22:46:29 +0000 (14:46 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Mon, 7 Dec 2009 22:57:43 +0000 (14:57 -0800)
The SRS and RFE instructions speed exception entry/exit by
making it easy to save and restore PC and SPSR.  This handles
both ARM and Thumb2 encodings.

Fix minor PLD goofage; that "should never reach this point"
can't happen, so remove it.

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

index 29ca23cae1273c4b28f7af6eece027700db58c0a..e76e3859018e12a9d64a1680e40d2d5fac9c3ef5 100644 (file)
@@ -106,6 +106,16 @@ static uint32_t ror(uint32_t value, int places)
        return (value >> places) | (value << (32 - places));
 }
 
+static int evaluate_unknown(uint32_t opcode,
+               uint32_t address, struct arm_instruction *instruction)
+{
+       instruction->type = ARM_UNDEFINED_INSTRUCTION;
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+                       "\tUNDEFINED INSTRUCTION", address, opcode);
+       return ERROR_OK;
+}
+
 static int evaluate_pld(uint32_t opcode,
                uint32_t address, struct arm_instruction *instruction)
 {
@@ -118,14 +128,50 @@ static int evaluate_pld(uint32_t opcode,
 
                return ERROR_OK;
        }
-       else
-       {
-               instruction->type = ARM_UNDEFINED_INSTRUCTION;
-               return ERROR_OK;
+       return evaluate_unknown(opcode, address, instruction);
+}
+
+static int evaluate_srs(uint32_t opcode,
+               uint32_t address, struct arm_instruction *instruction)
+{
+       const char *wback = (opcode & (1 << 21)) ? "!" : "";
+       const char *mode;
+
+       switch ((opcode >> 23) & 0x3) {
+       case 0:
+               mode = "DA";
+               break;
+       case 1:
+               /* "IA" is default */
+               mode = "";
+               break;
+       case 2:
+               mode = "DB";
+               break;
+       case 3:
+               mode = "IB";
+               break;
        }
 
-       LOG_ERROR("should never reach this point");
-       return -1;
+       switch (opcode & 0x0e500000) {
+       case 0x08400000:
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32
+                               "\t0x%8.8" PRIx32
+                               "\tSRS%s\tSP%s, #%d",
+                               address, opcode,
+                               mode, wback, opcode & 0x1f);
+               break;
+       case 0x08100000:
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32
+                               "\t0x%8.8" PRIx32
+                               "\tRFE%s\tr%d%s",
+                               address, opcode,
+                               mode, (opcode >> 16) & 0xf, wback);
+               break;
+       default:
+               return evaluate_unknown(opcode, address, instruction);
+       }
+       return ERROR_OK;
 }
 
 static int evaluate_swi(uint32_t opcode,
@@ -1605,13 +1651,9 @@ int arm_evaluate_opcode(uint32_t opcode, uint32_t address, struct arm_instructio
                if ((opcode & 0x08000000) == 0x00000000)
                        return evaluate_pld(opcode, address, instruction);
 
-               /* Undefined instruction */
+               /* Undefined instruction (or ARMv6+ SRS/RFE) */
                if ((opcode & 0x0e000000) == 0x08000000)
-               {
-                       instruction->type = ARM_UNDEFINED_INSTRUCTION;
-                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
-                       return ERROR_OK;
-               }
+                       return evaluate_srs(opcode, address, instruction);
 
                /* Branch and branch with link and change to Thumb */
                if ((opcode & 0x0e000000) == 0x0a000000)
@@ -3414,11 +3456,28 @@ static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
        int op = (opcode >> 22) & 0x6;
        int t = (opcode >> 21) & 1;
        unsigned registers = opcode & 0xffff;
+       char *mode = "";
 
        if (opcode & (1 << 20))
                op |= 1;
 
        switch (op) {
+       case 0:
+               mode = "DB";
+               /* FALL THROUGH */
+       case 6:
+               sprintf(cp, "SRS%s\tsp%s, #%d", mode,
+                               t ? "!" : "",
+                               opcode & 0x1f);
+               return ERROR_OK;
+       case 1:
+               mode = "DB";
+               /* FALL THROUGH */
+       case 7:
+               sprintf(cp, "RFE%s\tr%d%s", mode,
+                               (opcode >> 16) & 0xf,
+                               t ? "!" : "");
+               return ERROR_OK;
        case 2:
                sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
                break;

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)