Transform 'u16' to 'uint16_t'
[openocd.git] / src / target / arm_disassembler.c
index dd77928252fd41131eac1b197d08f357f52f1b14..f28763347b33c0b3ea262b1328c2b4592b690581 100644 (file)
 #endif
 
 #include "arm_disassembler.h"
-
 #include "log.h"
 
-#include <string.h>
 
 /* textual represenation of the condition field */
 /* ALways (default) is ommitted (empty string) */
@@ -57,7 +55,7 @@ int evaluate_pld(u32 opcode, u32 address, arm_instruction_t *instruction)
                return ERROR_OK;
        }
        
-       ERROR("should never reach this point");
+       LOG_ERROR("should never reach this point");
        return -1;
 }
 
@@ -104,7 +102,7 @@ int evaluate_blx_imm(u32 opcode, u32 address, arm_instruction_t *instruction)
 
 int evaluate_b_bl(u32 opcode, u32 address, arm_instruction_t *instruction)
 {
-       u8 L;
+       uint8_t L;
        u32 immediate;
        int offset;
        u32 target_address;
@@ -141,12 +139,12 @@ int evaluate_b_bl(u32 opcode, u32 address, arm_instruction_t *instruction)
 /* both normal and extended instruction space (condition field b1111) */
 int evaluate_ldc_stc_mcrr_mrrc(u32 opcode, u32 address, arm_instruction_t *instruction)
 {
-       u8 cp_num = (opcode & 0xf00) >> 8;
+       uint8_t cp_num = (opcode & 0xf00) >> 8;
        
        /* MCRR or MRRC */
        if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
        {
-               u8 cp_opcode, Rd, Rn, CRm;
+               uint8_t cp_opcode, Rd, Rn, CRm;
                char *mnemonic;
                
                cp_opcode = (opcode & 0xf0) >> 4;
@@ -173,8 +171,8 @@ int evaluate_ldc_stc_mcrr_mrrc(u32 opcode, u32 address, arm_instruction_t *instr
        }
        else /* LDC or STC */
        {
-               u8 CRd, Rn, offset;
-               u8 U, N;
+               uint8_t CRd, Rn, offset;
+               uint8_t U, N;
                char *mnemonic;
                char addressing_mode[32];
                
@@ -223,7 +221,7 @@ int evaluate_cdp_mcr_mrc(u32 opcode, u32 address, arm_instruction_t *instruction
 {
        char* cond;
        char* mnemonic;
-       u8 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
+       uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
        
        cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
        cp_num = (opcode & 0xf00) >> 8;
@@ -270,8 +268,8 @@ int evaluate_cdp_mcr_mrc(u32 opcode, u32 address, arm_instruction_t *instruction
 /* Load/store instructions */
 int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
 {
-       u8 I, P, U, B, W, L;
-       u8 Rn, Rd;
+       uint8_t I, P, U, B, W, L;
+       uint8_t Rn, Rd;
        char *operation; /* "LDR" or "STR" */
        char *suffix; /* "", "B", "T", "BT" */
        char offset[32];
@@ -343,15 +341,18 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
        if (!I) /* #+-<offset_12> */
        {
                u32 offset_12 = (opcode & 0xfff);
-               snprintf(offset, 32, "#%s0x%x", (U) ? "" : "-", offset_12);
+               if (offset_12)
+                       snprintf(offset, 32, ", #%s0x%x", (U) ? "" : "-", offset_12);
+               else
+                       snprintf(offset, 32, "%s", "");
                
                instruction->info.load_store.offset_mode = 0;
                instruction->info.load_store.offset.offset = offset_12;
        }
        else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
        {
-               u8 shift_imm, shift;
-               u8 Rm;
+               uint8_t shift_imm, shift;
+               uint8_t Rm;
                
                shift_imm = (opcode & 0xf80) >> 7;
                shift = (opcode & 0x60) >> 5;
@@ -376,26 +377,26 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
 
                if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
                {
-                       snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
+                       snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
                }
                else /* +-<Rm>, <Shift>, #<shift_imm> */
                {
                        switch (shift)
                        {
                                case 0x0: /* LSL */
-                                       snprintf(offset, 32, "%sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
+                                       snprintf(offset, 32, "%sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
                                        break;
                                case 0x1: /* LSR */
-                                       snprintf(offset, 32, "%sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
+                                       snprintf(offset, 32, "%sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
                                        break;
                                case 0x2: /* ASR */
-                                       snprintf(offset, 32, "%sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
+                                       snprintf(offset, 32, "%sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
                                        break;
                                case 0x3: /* ROR */
-                                       snprintf(offset, 32, "%sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
+                                       snprintf(offset, 32, "%sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
                                        break;
                                case 0x4: /* RRX */
-                                       snprintf(offset, 32, "%sr%i, RRX", (U) ? "" : "-", Rm);
+                                       snprintf(offset, 32, "%sr%i, RRX", (U) ? "" : "-", Rm);
                                        break;
                        }
                }
@@ -405,7 +406,7 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
        {
                if (W == 0) /* offset */
                {
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i%s]",
+                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i%s]",
                                         address, opcode, operation, COND(opcode), suffix,
                                         Rd, Rn, offset);
                        
@@ -413,7 +414,7 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
                }
                else /* pre-indexed */
                {
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i%s]!",
+                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i%s]!",
                                         address, opcode, operation, COND(opcode), suffix,
                                         Rd, Rn, offset);
                        
@@ -422,7 +423,7 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
        }
        else /* post-indexed */
        {
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i]%s",
+               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i]%s",
                                 address, opcode, operation, COND(opcode), suffix,
                                 Rd, Rn, offset);
                
@@ -435,8 +436,8 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
 /* Miscellaneous load/store instructions */
 int evaluate_misc_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
 {
-       u8 P, U, I, W, L, S, H;
-       u8 Rn, Rd;
+       uint8_t P, U, I, W, L, S, H;
+       uint8_t Rn, Rd;
        char *operation; /* "LDR" or "STR" */
        char *suffix; /* "H", "SB", "SH", "D" */
        char offset[32];
@@ -518,7 +519,7 @@ int evaluate_misc_load_store(u32 opcode, u32 address, arm_instruction_t *instruc
        }
        else /* Register offset/index (+-<Rm>) */
        {
-               u8 Rm;
+               uint8_t Rm;
                Rm = (opcode & 0xf);
                snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
                
@@ -562,7 +563,7 @@ int evaluate_misc_load_store(u32 opcode, u32 address, arm_instruction_t *instruc
 /* Load/store multiples instructions */
 int evaluate_ldm_stm(u32 opcode, u32 address, arm_instruction_t *instruction)
 {
-       u8 P, U, S, W, L, Rn;
+       uint8_t P, U, S, W, L, Rn;
        u32 register_list;
        char *addressing_mode;
        char *mnemonic;
@@ -655,7 +656,7 @@ int evaluate_mul_and_extra_ld_st(u32 opcode, u32 address, arm_instruction_t *ins
                /* Multiply (accumulate) */
                if ((opcode & 0x0f800000) == 0x00000000)
                {
-                       u8 Rm, Rs, Rn, Rd, S;
+                       uint8_t Rm, Rs, Rn, Rd, S;
                        Rm = opcode & 0xf;
                        Rs = (opcode & 0xf00) >> 8;
                        Rn = (opcode & 0xf000) >> 12;
@@ -683,7 +684,7 @@ int evaluate_mul_and_extra_ld_st(u32 opcode, u32 address, arm_instruction_t *ins
                if ((opcode & 0x0f800000) == 0x00800000)
                {
                        char* mnemonic = NULL;
-                       u8 Rm, Rs, RdHi, RdLow, S;
+                       uint8_t Rm, Rs, RdHi, RdLow, S;
                        Rm = opcode & 0xf;
                        Rs = (opcode & 0xf00) >> 8;
                        RdHi = (opcode & 0xf000) >> 12;
@@ -720,7 +721,7 @@ int evaluate_mul_and_extra_ld_st(u32 opcode, u32 address, arm_instruction_t *ins
                /* Swap/swap byte */
                if ((opcode & 0x0f800000) == 0x01000000)
                {
-                       u8 Rm, Rd, Rn;
+                       uint8_t Rm, Rd, Rn;
                        Rm = opcode & 0xf;
                        Rd = (opcode & 0xf000) >> 12;
                        Rn = (opcode & 0xf0000) >> 16;
@@ -751,8 +752,8 @@ int evaluate_mrs_msr(u32 opcode, u32 address, arm_instruction_t *instruction)
                /* immediate variant */
                if (opcode & 0x02000000)
                {
-                       u8 immediate = (opcode & 0xff);
-                       u8 rotate = (opcode & 0xf00);
+                       uint8_t immediate = (opcode & 0xff);
+                       uint8_t rotate = (opcode & 0xf00);
                        
                        snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, 0x%8.8x",
                                         address, opcode, COND(opcode), PSR,
@@ -765,7 +766,7 @@ int evaluate_mrs_msr(u32 opcode, u32 address, arm_instruction_t *instruction)
                }
                else /* register variant */
                {
-                       u8 Rm = opcode & 0xf;
+                       uint8_t Rm = opcode & 0xf;
                        snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, r%i",
                                         address, opcode, COND(opcode), PSR,
                                         (opcode & 0x10000) ? "c" : "",
@@ -779,7 +780,7 @@ int evaluate_mrs_msr(u32 opcode, u32 address, arm_instruction_t *instruction)
        }
        else /* Move status register to register (MRS) */
        {
-               u8 Rd;
+               uint8_t Rd;
                
                instruction->type = ARM_MRS;
                Rd = (opcode & 0x0000f000) >> 12;
@@ -803,7 +804,7 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
        /* BX */
        if ((opcode & 0x006000f0) == 0x00200010)
        {
-               u8 Rm;
+               uint8_t Rm;
                instruction->type = ARM_BX;
                Rm = opcode & 0xf;
                
@@ -815,9 +816,9 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
        }
        
        /* CLZ */
-       if ((opcode & 0x0060000f0) == 0x00300010)
+       if ((opcode & 0x006000f0) == 0x00600010)
        {
-               u8 Rm, Rd;
+               uint8_t Rm, Rd;
                instruction->type = ARM_CLZ;
                Rm = opcode & 0xf;
                Rd = (opcode & 0xf000) >> 12;
@@ -826,10 +827,10 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
                                 address, opcode, COND(opcode), Rd, Rm);
        }
        
-       /* BLX */
-       if ((opcode & 0x0060000f0) == 0x00200030)
+       /* BLX(2) */
+       if ((opcode & 0x006000f0) == 0x00200030)
        {
-               u8 Rm;
+               uint8_t Rm;
                instruction->type = ARM_BLX;
                Rm = opcode & 0xf;
                
@@ -843,7 +844,7 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
        /* Enhanced DSP add/subtracts */
        if ((opcode & 0x0000000f0) == 0x00000050)
        {
-               u8 Rm, Rd, Rn;
+               uint8_t Rm, Rd, Rn;
                char *mnemonic = NULL;
                Rm = opcode & 0xf;
                Rd = (opcode & 0xf000) >> 12;
@@ -893,7 +894,7 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
                /* SMLA<x><y> */
                if ((opcode & 0x00600000) == 0x00000000)
                {
-                       u8 Rd, Rm, Rs, Rn;
+                       uint8_t Rd, Rm, Rs, Rn;
                        instruction->type = ARM_SMLAxy;
                        Rd = (opcode & 0xf0000) >> 16;
                        Rm = (opcode & 0xf);
@@ -908,7 +909,7 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
                /* SMLAL<x><y> */
                if ((opcode & 0x00600000) == 0x00400000)
                {
-                       u8 RdLow, RdHi, Rm, Rs;
+                       uint8_t RdLow, RdHi, Rm, Rs;
                        instruction->type = ARM_SMLAxy;
                        RdHi = (opcode & 0xf0000) >> 16;
                        RdLow = (opcode & 0xf000) >> 12;
@@ -923,7 +924,7 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
                /* SMLAW<y> */
                if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
                {
-                       u8 Rd, Rm, Rs, Rn;
+                       uint8_t Rd, Rm, Rs, Rn;
                        instruction->type = ARM_SMLAWy;
                        Rd = (opcode & 0xf0000) >> 16;
                        Rm = (opcode & 0xf);
@@ -938,7 +939,7 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
                /* SMUL<x><y> */
                if ((opcode & 0x00600000) == 0x00300000)
                {
-                       u8 Rd, Rm, Rs;
+                       uint8_t Rd, Rm, Rs;
                        instruction->type = ARM_SMULxy;
                        Rd = (opcode & 0xf0000) >> 16;
                        Rm = (opcode & 0xf);
@@ -952,7 +953,7 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
                /* SMULW<y> */
                if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
                {
-                       u8 Rd, Rm, Rs;
+                       uint8_t Rd, Rm, Rs;
                        instruction->type = ARM_SMULWy;
                        Rd = (opcode & 0xf0000) >> 16;
                        Rm = (opcode & 0xf);
@@ -969,7 +970,7 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
 
 int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
 {
-       u8 I, op, S, Rn, Rd;
+       uint8_t I, op, S, Rn, Rd;
        char *mnemonic = NULL;
        char shifter_operand[32];
        
@@ -1054,8 +1055,8 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
        
        if (I) /* immediate shifter operand (#<immediate>)*/
        {
-               u8 immed_8 = opcode & 0xff;
-               u8 rotate_imm = (opcode & 0xf00) >> 8;
+               uint8_t immed_8 = opcode & 0xff;
+               uint8_t rotate_imm = (opcode & 0xf00) >> 8;
                u32 immediate;
                
                immediate = ror(immed_8, rotate_imm * 2);
@@ -1067,13 +1068,13 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
        }
        else /* register-based shifter operand */
        {
-               u8 shift, Rm;
+               uint8_t shift, Rm;
                shift = (opcode & 0x60) >> 5;
                Rm = (opcode & 0xf);
                
                if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
                {
-                       u8 shift_imm;
+                       uint8_t shift_imm;
                        shift_imm = (opcode & 0xf80) >> 7;
 
                        instruction->info.data_proc.variant = 1;
@@ -1123,7 +1124,7 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
                }
                else /* Register shifts ("<Rm>, <shift> <Rs>") */
                {
-                       u8 Rs = (opcode & 0xf00) >> 8;
+                       uint8_t Rs = (opcode & 0xf00) >> 8;
                        
                        instruction->info.data_proc.variant = 2;
                        instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
@@ -1157,7 +1158,10 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
        }
        else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
        {
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, %s",
+               if (opcode==0xe1a00000) /* print MOV r0,r0 as NOP */
+                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tNOP",address, opcode);
+               else
+                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, %s",
                                 address, opcode, mnemonic, COND(opcode),
                                 (S) ? "S" : "", Rd, shifter_operand);
        }
@@ -1311,7 +1315,800 @@ int arm_evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction)
                        return evaluate_cdp_mcr_mrc(opcode, address, instruction);
        }
        
-       ERROR("should never reach this point");
+       LOG_ERROR("should never reach this point");
        return -1;
 }
 
+int evaluate_b_bl_blx_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       u32 offset = opcode & 0x7ff;
+       u32 opc = (opcode >> 11) & 0x3;
+       u32 target_address;
+       char *mnemonic = NULL;
+       
+       /* sign extend 11-bit offset */
+       if (((opc==0) || (opc==2)) && (offset & 0x00000400))
+               offset = 0xfffff800 | offset;
+       
+       target_address = address + 4 + (offset<<1);
+
+       switch(opc)
+       {
+               /* unconditional branch */
+               case 0:
+                       instruction->type = ARM_B;
+                       mnemonic = "B";
+                       break;
+               /* BLX suffix */
+               case 1:
+                       instruction->type = ARM_BLX;
+                       mnemonic = "BLX";
+                       break;
+               /* BL/BLX prefix */
+               case 2:
+                       instruction->type = ARM_UNKNOWN_INSTUCTION;
+                       mnemonic = "prefix";
+                       target_address = offset<<12;
+                       break;
+               /* BL suffix */
+               case 3:
+                       instruction->type = ARM_BL;
+                       mnemonic = "BL";
+                       break;
+       }
+       /* TODO: deals correctly with dual opcodes BL/BLX ... */
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s 0x%8.8x", address, opcode,mnemonic, target_address);
+       
+       instruction->info.b_bl_bx_blx.reg_operand = -1;
+       instruction->info.b_bl_bx_blx.target_address = target_address;
+
+       return ERROR_OK;
+}
+
+int evaluate_add_sub_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       uint8_t Rd = (opcode >> 0) & 0x7;
+       uint8_t Rn = (opcode >> 3) & 0x7;
+       uint8_t Rm_imm = (opcode >> 6) & 0x7;
+       u32 opc = opcode & (1<<9);
+       u32 reg_imm  = opcode & (1<<10);
+       char *mnemonic;
+       
+       if (opc)
+       {
+               instruction->type = ARM_SUB;
+               mnemonic = "SUBS";
+       }
+       else
+       {
+               instruction->type = ARM_ADD;
+               mnemonic = "ADDS";
+       }
+       
+       instruction->info.data_proc.Rd = Rd;
+       instruction->info.data_proc.Rn = Rn;
+       instruction->info.data_proc.S = 1;
+
+       if (reg_imm)
+       {
+               instruction->info.data_proc.variant = 0; /*immediate*/
+               instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
+               snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s r%i, r%i, #%d",
+                                address, opcode, mnemonic, Rd, Rn, Rm_imm);
+       }
+       else
+       {
+               instruction->info.data_proc.variant = 1; /*immediate shift*/
+               instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
+               snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s r%i, r%i, r%i",
+                                address, opcode, mnemonic, Rd, Rn, Rm_imm);
+       }
+
+       return ERROR_OK;
+}
+
+int evaluate_shift_imm_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       uint8_t Rd = (opcode >> 0) & 0x7;
+       uint8_t Rm = (opcode >> 3) & 0x7;
+       uint8_t imm = (opcode >> 6) & 0x1f;
+       uint8_t opc = (opcode >> 11) & 0x3;
+       char *mnemonic = NULL;
+       
+       switch(opc)
+       {
+               case 0:
+                       instruction->type = ARM_MOV;
+                       mnemonic = "LSLS";
+                       instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
+                       break;
+               case 1:
+                       instruction->type = ARM_MOV;
+                       mnemonic = "LSRS";
+                       instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
+                       break;
+               case 2:
+                       instruction->type = ARM_MOV;
+                       mnemonic = "ASRS";
+                       instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
+                       break;
+       }
+
+       if ((imm==0) && (opc!=0))
+               imm = 32;
+
+       instruction->info.data_proc.Rd = Rd;
+       instruction->info.data_proc.Rn = -1;
+       instruction->info.data_proc.S = 1;
+
+       instruction->info.data_proc.variant = 1; /*immediate_shift*/
+       instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
+       instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s r%i, r%i, #0x%02x",
+                                address, opcode, mnemonic, Rd, Rm, imm);
+
+       return ERROR_OK;
+}
+
+int evaluate_data_proc_imm_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       uint8_t imm = opcode & 0xff;
+       uint8_t Rd = (opcode >> 8) & 0x7;
+       u32 opc = (opcode >> 11) & 0x3;
+       char *mnemonic = NULL;
+       
+       instruction->info.data_proc.Rd = Rd;
+       instruction->info.data_proc.Rn = Rd;
+       instruction->info.data_proc.S = 1;
+       instruction->info.data_proc.variant = 0; /*immediate*/
+       instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
+       
+       switch(opc)
+       {
+               case 0:
+                       instruction->type = ARM_MOV;
+                       mnemonic = "MOVS";
+                       instruction->info.data_proc.Rn = -1;
+                       break;
+               case 1:
+                       instruction->type = ARM_CMP;
+                       mnemonic = "CMP";
+                       instruction->info.data_proc.Rd = -1;
+                       break;
+               case 2:
+                       instruction->type = ARM_ADD;
+                       mnemonic = "ADDS";
+                       break;
+               case 3:
+                       instruction->type = ARM_SUB;
+                       mnemonic = "SUBS";
+                       break;
+       }
+       
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s r%i, #0x%02x",
+                                address, opcode, mnemonic, Rd, imm);
+
+       return ERROR_OK;
+}
+
+int evaluate_data_proc_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       uint8_t high_reg, op, Rm, Rd,H1,H2;
+       char *mnemonic = NULL;
+       
+       high_reg = (opcode & 0x0400) >> 10;
+       op = (opcode & 0x03C0) >> 6;
+       
+       Rd = (opcode & 0x0007);
+       Rm = (opcode & 0x0038) >> 3;
+       H1 = (opcode & 0x0080) >> 7;
+       H2 = (opcode & 0x0040) >> 6;
+       
+       instruction->info.data_proc.Rd = Rd;
+       instruction->info.data_proc.Rn = Rd;
+       instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
+       instruction->info.data_proc.variant = 1 /*immediate shift*/;
+       instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
+
+       if (high_reg)
+       {
+               Rd |= H1 << 3;
+               Rm |= H2 << 3;
+               op >>= 2;
+       
+               switch (op)
+               {
+                       case 0x0:
+                               instruction->type = ARM_ADD;
+                               mnemonic = "ADD";
+                               break;
+                       case 0x1:
+                               instruction->type = ARM_CMP;
+                               mnemonic = "CMP";
+                               break;
+                       case 0x2:
+                               instruction->type = ARM_MOV;
+                               mnemonic = "MOV";
+                               break;
+                       case 0x3:
+                               if ((opcode & 0x7) == 0x0)
+                               {
+                                       instruction->info.b_bl_bx_blx.reg_operand = Rm;
+                                       if (H1)
+                                       {
+                                               instruction->type = ARM_BLX;
+                                               snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\tBLX r%i", address, opcode, Rm);
+                                       }
+                                       else
+                                       {
+                                               instruction->type = ARM_BX;
+                                               snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\tBX r%i", address, opcode, Rm);
+                                       }
+                               }
+                               else
+                               {
+                                       instruction->type = ARM_UNDEFINED_INSTRUCTION;
+                                       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\tUNDEFINED INSTRUCTION", address, opcode);
+                               }
+                               return ERROR_OK;        
+                               break;
+               }
+       }
+       else
+       {
+               switch (op)
+               {
+                       case 0x0:
+                               instruction->type = ARM_AND;
+                               mnemonic = "ANDS";
+                               break;
+                       case 0x1:
+                               instruction->type = ARM_EOR;
+                               mnemonic = "EORS";
+                               break;
+                       case 0x2:
+                               instruction->type = ARM_MOV;
+                               mnemonic = "LSLS";
+                               instruction->info.data_proc.variant = 2 /*register shift*/;
+                               instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
+                               break;
+                       case 0x3:
+                               instruction->type = ARM_MOV;
+                               mnemonic = "LSRS";
+                               instruction->info.data_proc.variant = 2 /*register shift*/;
+                               instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
+                               break;
+                       case 0x4:
+                               instruction->type = ARM_MOV;
+                               mnemonic = "ASRS";
+                               instruction->info.data_proc.variant = 2 /*register shift*/;
+                               instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
+                               break;
+                       case 0x5:
+                               instruction->type = ARM_ADC;
+                               mnemonic = "ADCS";
+                               break;
+                       case 0x6:
+                               instruction->type = ARM_SBC;
+                               mnemonic = "SBCS";
+                               break;
+                       case 0x7:
+                               instruction->type = ARM_MOV;
+                               mnemonic = "RORS";
+                               instruction->info.data_proc.variant = 2 /*register shift*/;
+                               instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
+                               break;
+                       case 0x8:
+                               instruction->type = ARM_TST;
+                               mnemonic = "TST";
+                               break;
+                       case 0x9:
+                               instruction->type = ARM_RSB;
+                               mnemonic = "NEGS";
+                               instruction->info.data_proc.variant = 0 /*immediate*/;
+                               instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
+                               instruction->info.data_proc.Rn = Rm;
+                               break;
+                       case 0xA:
+                               instruction->type = ARM_CMP;
+                               mnemonic = "CMP";
+                               break;
+                       case 0xB:
+                               instruction->type = ARM_CMN;
+                               mnemonic = "CMN";
+                               break;
+                       case 0xC:
+                               instruction->type = ARM_ORR;
+                               mnemonic = "ORRS";
+                               break;
+                       case 0xD:
+                               instruction->type = ARM_MUL;
+                               mnemonic = "MULS";
+                               break;
+                       case 0xE:
+                               instruction->type = ARM_BIC;
+                               mnemonic = "BICS";
+                               break;
+                       case 0xF:
+                               instruction->type = ARM_MVN;
+                               mnemonic = "MVNS";
+                               break;
+               }
+       }
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s r%i, r%i",
+                                address, opcode, mnemonic, Rd, Rm);
+
+       return ERROR_OK;
+}
+
+int evaluate_load_literal_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       u32 immediate;
+       uint8_t Rd = (opcode >> 8) & 0x7; 
+
+       instruction->type = ARM_LDR;
+       immediate = opcode & 0x000000ff;
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\tLDR r%i, [PC, #0x%x]", address, opcode, Rd, immediate*4);
+
+       instruction->info.load_store.Rd = Rd;
+       instruction->info.load_store.Rn = 15 /*PC*/;
+       instruction->info.load_store.index_mode = 0; /*offset*/
+       instruction->info.load_store.offset_mode = 0; /*immediate*/
+       instruction->info.load_store.offset.offset = immediate*4;
+
+       return ERROR_OK;
+}
+
+int evaluate_load_store_reg_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       uint8_t Rd = (opcode >> 0) & 0x7; 
+       uint8_t Rn = (opcode >> 3) & 0x7; 
+       uint8_t Rm = (opcode >> 6) & 0x7; 
+       uint8_t opc = (opcode >> 9) & 0x7; 
+       char *mnemonic = NULL;
+
+       switch(opc)
+       {
+               case 0:
+                       instruction->type = ARM_STR;
+                       mnemonic = "STR";
+                       break;
+               case 1:
+                       instruction->type = ARM_STRH;
+                       mnemonic = "STRH";
+                       break;
+               case 2:
+                       instruction->type = ARM_STRB;
+                       mnemonic = "STRB";
+                       break;
+               case 3:
+                       instruction->type = ARM_LDRSB;
+                       mnemonic = "LDRSB";
+                       break;
+               case 4:
+                       instruction->type = ARM_LDR;
+                       mnemonic = "LDR";
+                       break;
+               case 5:
+                       instruction->type = ARM_LDRH;
+                       mnemonic = "LDRH";
+                       break;
+               case 6:
+                       instruction->type = ARM_LDRB;
+                       mnemonic = "LDRB";
+                       break;
+               case 7:
+                       instruction->type = ARM_LDRSH;
+                       mnemonic = "LDRSH";
+                       break;
+       }
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s r%i, [r%i, r%i]", address, opcode, mnemonic, Rd, Rn, Rm);
+       
+       instruction->info.load_store.Rd = Rd;
+       instruction->info.load_store.Rn = Rn;
+       instruction->info.load_store.index_mode = 0; /*offset*/
+       instruction->info.load_store.offset_mode = 1; /*register*/
+       instruction->info.load_store.offset.reg.Rm = Rm;
+
+       return ERROR_OK;
+}
+
+int evaluate_load_store_imm_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       u32 offset = (opcode >> 6) & 0x1f;
+       uint8_t Rd = (opcode >> 0) & 0x7; 
+       uint8_t Rn = (opcode >> 3) & 0x7; 
+       u32 L = opcode & (1<<11);
+       u32 B = opcode & (1<<12);
+       char *mnemonic;
+       char suffix = ' ';
+       u32 shift = 2;
+
+       if (L)
+       {
+               instruction->type = ARM_LDR;
+               mnemonic = "LDR";
+       }
+       else
+       {
+               instruction->type = ARM_STR;
+               mnemonic = "STR";
+       }
+
+       if ((opcode&0xF000)==0x8000)
+       {
+               suffix = 'H';
+               shift = 1;
+       }
+       else if (B)
+       {
+               suffix = 'B';
+               shift = 0;
+       }
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s%c r%i, [r%i, #0x%x]", address, opcode, mnemonic, suffix, Rd, Rn, offset<<shift);
+       
+       instruction->info.load_store.Rd = Rd;
+       instruction->info.load_store.Rn = Rn;
+       instruction->info.load_store.index_mode = 0; /*offset*/
+       instruction->info.load_store.offset_mode = 0; /*immediate*/
+       instruction->info.load_store.offset.offset = offset<<shift;
+
+       return ERROR_OK;
+}
+
+int evaluate_load_store_stack_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       u32 offset = opcode  & 0xff;
+       uint8_t Rd = (opcode >> 8) & 0x7; 
+       u32 L = opcode & (1<<11);
+       char *mnemonic;
+
+       if (L)
+       {
+               instruction->type = ARM_LDR;
+               mnemonic = "LDR";
+       }
+       else
+       {
+               instruction->type = ARM_STR;
+               mnemonic = "STR";
+       }
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s r%i, [SP, #0x%x]", address, opcode, mnemonic, Rd, offset*4);
+       
+       instruction->info.load_store.Rd = Rd;
+       instruction->info.load_store.Rn = 13 /*SP*/;
+       instruction->info.load_store.index_mode = 0; /*offset*/
+       instruction->info.load_store.offset_mode = 0; /*immediate*/
+       instruction->info.load_store.offset.offset = offset*4;
+
+       return ERROR_OK;
+}
+
+int evaluate_add_sp_pc_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       u32 imm = opcode  & 0xff;
+       uint8_t Rd = (opcode >> 8) & 0x7; 
+       uint8_t Rn;
+       u32 SP = opcode & (1<<11);
+       char *reg_name;
+
+       instruction->type = ARM_ADD;
+       
+       if (SP)
+       {
+               reg_name = "SP";
+               Rn = 13;
+       }
+       else
+       {
+               reg_name = "PC";
+               Rn = 15;
+       }
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\tADD r%i, %s, #0x%x", address, opcode, Rd,reg_name, imm*4);
+
+       instruction->info.data_proc.variant = 0 /* immediate */;
+       instruction->info.data_proc.Rd = Rd;
+       instruction->info.data_proc.Rn = Rn;
+       instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
+
+       return ERROR_OK;
+}
+
+int evaluate_adjust_stack_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       u32 imm = opcode  & 0x7f;
+       uint8_t opc = opcode & (1<<7);
+       char *mnemonic;
+
+       
+       if (opc)
+       {
+               instruction->type = ARM_SUB;
+               mnemonic = "SUB";
+       }
+       else
+       {
+               instruction->type = ARM_ADD;
+               mnemonic = "ADD";
+       }
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s SP, #0x%x", address, opcode, mnemonic, imm*4);
+
+       instruction->info.data_proc.variant = 0 /* immediate */;
+       instruction->info.data_proc.Rd = 13 /*SP*/;
+       instruction->info.data_proc.Rn = 13 /*SP*/;
+       instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
+
+       return ERROR_OK;
+}
+
+int evaluate_breakpoint_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       u32 imm = opcode  & 0xff;
+       
+       instruction->type = ARM_BKPT;
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\tBKPT 0x%02x", address, opcode, imm);
+
+       return ERROR_OK;
+}
+
+int evaluate_load_store_multiple_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       u32 reg_list = opcode  & 0xff;
+       u32 L = opcode & (1<<11);
+       u32 R = opcode & (1<<8);
+       uint8_t Rn = (opcode >> 8) & 7;
+       uint8_t addr_mode = 0 /* IA */;
+       char reg_names[40];
+       char *reg_names_p;
+       char *mnemonic;
+       char ptr_name[7] = "";
+       int i;  
+
+       if ((opcode & 0xf000) == 0xc000)
+       { /* generic load/store multiple */
+               if (L)
+               {
+                       instruction->type = ARM_LDM;
+                       mnemonic = "LDMIA";
+               }
+               else
+               {
+                       instruction->type = ARM_STM;
+                       mnemonic = "STMIA";
+               }
+               snprintf(ptr_name,7,"r%i!, ",Rn);
+       }
+       else
+       { /* push/pop */
+               Rn = 13; /* SP */
+               if (L)
+               {
+                       instruction->type = ARM_LDM;
+                       mnemonic = "POP";
+                       if (R)
+                               reg_list |= (1<<15) /*PC*/;
+               }
+               else
+               {
+                       instruction->type = ARM_STM;
+                       mnemonic = "PUSH";
+                       addr_mode = 3; /*DB*/
+                       if (R)
+                               reg_list |= (1<<14) /*LR*/;
+               }
+       }
+
+       reg_names_p = reg_names;
+       for (i = 0; i <= 15; i++)
+       {
+               if (reg_list & (1<<i))
+                       reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
+       }
+       if (reg_names_p>reg_names)
+               reg_names_p[-2] = '\0';
+       else /* invalid op : no registers */
+               reg_names[0] = '\0';
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\t%s %s{%s}", address, opcode, mnemonic, ptr_name,reg_names);
+
+       instruction->info.load_store_multiple.register_list = reg_list;
+       instruction->info.load_store_multiple.Rn = Rn;
+       instruction->info.load_store_multiple.addressing_mode = addr_mode;
+
+       return ERROR_OK;
+}
+
+int evaluate_cond_branch_thumb(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       u32 offset = opcode  & 0xff;
+       uint8_t cond = (opcode >> 8) & 0xf;
+       u32 target_address;
+
+       if (cond == 0xf)
+       {
+               instruction->type = ARM_SWI;
+               snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\tSWI 0x%02x", address, opcode, offset);
+               return ERROR_OK;
+       }
+       else if (cond == 0xe)
+       {
+               instruction->type = ARM_UNDEFINED_INSTRUCTION;
+               snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\tUNDEFINED INSTRUCTION", address, opcode);
+               return ERROR_OK;
+       }
+
+       /* sign extend 8-bit offset */
+       if (offset & 0x00000080)
+               offset = 0xffffff00 | offset;
+       
+       target_address = address + 4 + (offset<<1);
+
+       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\tB%s 0x%8.8x", address, opcode,
+                        arm_condition_strings[cond], target_address);
+       
+       instruction->type = ARM_B;
+       instruction->info.b_bl_bx_blx.reg_operand = -1;
+       instruction->info.b_bl_bx_blx.target_address = target_address;
+
+       return ERROR_OK;
+}
+
+int thumb_evaluate_opcode(uint16_t opcode, u32 address, arm_instruction_t *instruction)
+{
+       /* clear fields, to avoid confusion */
+       memset(instruction, 0, sizeof(arm_instruction_t));
+       instruction->opcode = opcode;
+       
+       if ((opcode & 0xe000) == 0x0000)
+       {
+               /* add/substract register or immediate */
+               if ((opcode & 0x1800) == 0x1800)
+                       return evaluate_add_sub_thumb(opcode, address, instruction);
+               /* shift by immediate */
+               else
+                       return evaluate_shift_imm_thumb(opcode, address, instruction);
+       }
+       
+       /* Add/substract/compare/move immediate */
+       if ((opcode & 0xe000) == 0x2000)
+       {
+               return evaluate_data_proc_imm_thumb(opcode, address, instruction);
+       }
+       
+       /* Data processing instructions */
+       if ((opcode & 0xf800) == 0x4000)
+       {
+               return evaluate_data_proc_thumb(opcode, address, instruction);
+       }
+       
+       /* Load from literal pool */
+       if ((opcode & 0xf800) == 0x4800)
+       {
+               return evaluate_load_literal_thumb(opcode, address, instruction);
+       }
+
+       /* Load/Store register offset */
+       if ((opcode & 0xf000) == 0x5000)
+       {
+               return evaluate_load_store_reg_thumb(opcode, address, instruction);
+       }
+
+       /* Load/Store immediate offset */
+       if (((opcode & 0xe000) == 0x6000)
+               ||((opcode & 0xf000) == 0x8000))
+       {
+               return evaluate_load_store_imm_thumb(opcode, address, instruction);
+       }
+       
+       /* Load/Store from/to stack */
+       if ((opcode & 0xf000) == 0x9000)
+       {
+               return evaluate_load_store_stack_thumb(opcode, address, instruction);
+       }
+
+       /* Add to SP/PC */
+       if ((opcode & 0xf000) == 0xa000)
+       {
+               return evaluate_add_sp_pc_thumb(opcode, address, instruction);
+       }
+
+       /* Misc */
+       if ((opcode & 0xf000) == 0xb000)
+       {
+               if ((opcode & 0x0f00) == 0x0000)
+                       return evaluate_adjust_stack_thumb(opcode, address, instruction);
+               else if ((opcode & 0x0f00) == 0x0e00)
+                       return evaluate_breakpoint_thumb(opcode, address, instruction);
+               else if ((opcode & 0x0600) == 0x0400) /* push pop */
+                       return evaluate_load_store_multiple_thumb(opcode, address, instruction);
+               else
+               {
+                       instruction->type = ARM_UNDEFINED_INSTRUCTION;
+                       snprintf(instruction->text, 128, "0x%8.8x\t0x%4.4x\tUNDEFINED INSTRUCTION", address, opcode);
+                       return ERROR_OK;
+               }
+       }
+
+       /* Load/Store multiple */
+       if ((opcode & 0xf000) == 0xc000)
+       {
+               return evaluate_load_store_multiple_thumb(opcode, address, instruction);
+       }
+
+       /* Conditional branch + SWI */
+       if ((opcode & 0xf000) == 0xd000)
+       {
+               return evaluate_cond_branch_thumb(opcode, address, instruction);
+       }
+       
+       if ((opcode & 0xe000) == 0xe000)
+       {
+               /* Undefined instructions */
+               if ((opcode & 0xf801) == 0xe801)
+               {
+                       instruction->type = ARM_UNDEFINED_INSTRUCTION;
+                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
+                       return ERROR_OK;
+               }
+               else
+               { /* Branch to offset */
+                       return evaluate_b_bl_blx_thumb(opcode, address, instruction);
+               }
+       }
+
+       LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
+       return -1;
+}
+
+int arm_access_size(arm_instruction_t *instruction)
+{
+       if ((instruction->type == ARM_LDRB)
+               || (instruction->type == ARM_LDRBT)
+               || (instruction->type == ARM_LDRSB)
+               || (instruction->type == ARM_STRB)
+               || (instruction->type == ARM_STRBT))
+       {
+               return 1;
+       }
+       else if ((instruction->type == ARM_LDRH)
+               || (instruction->type == ARM_LDRSH)
+               || (instruction->type == ARM_STRH))
+       {
+               return 2;
+       }
+       else if ((instruction->type == ARM_LDR)
+               || (instruction->type == ARM_LDRT)
+               || (instruction->type == ARM_STR)
+               || (instruction->type == ARM_STRT))
+       {
+               return 4;
+       }
+       else if ((instruction->type == ARM_LDRD)
+               || (instruction->type == ARM_STRD))
+       {
+               return 8;
+       }
+       else
+       {
+               LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
+               return 0;
+       }
+}

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)