/* SPDX-License-Identifier: GPL-2.0-or-later */ /*************************************************************************** * Copyright (C) 2013-2015,2019-2020 Synopsys, Inc. * * Frank Dols * * Mischa Jonker * * Anton Kolesov * * Evgeniy Didin * ***************************************************************************/ #ifndef OPENOCD_TARGET_ARC_H #define OPENOCD_TARGET_ARC_H #include #include #include "algorithm.h" #include "breakpoints.h" #include "jtag/interface.h" #include "register.h" #include "target.h" #include "target_request.h" #include "target_type.h" #include "helper/bits.h" #include "arc_jtag.h" #include "arc_cmd.h" #include "arc_mem.h" #define ARC_COMMON_MAGIC 0xB32EB324U /* just a unique number */ #define AUX_DEBUG_REG 0x5 #define AUX_PC_REG 0x6 #define AUX_STATUS32_REG 0xA #define SET_CORE_FORCE_HALT BIT(1) #define SET_CORE_HALT_BIT BIT(0) /* STATUS32[0] = H field */ #define SET_CORE_ENABLE_INTERRUPTS BIT(31) /* STATUS32[5] or AE bit indicates if the processor is in exception state */ #define SET_CORE_AE_BIT BIT(5) /* Single instruction step bit in Debug register */ #define SET_CORE_SINGLE_INSTR_STEP BIT(11) #define AUX_STATUS32_REG_HALT_BIT BIT(0) #define AUX_STATUS32_REG_IE_BIT BIT(31) /* STATUS32[31] = IE field */ /* ARC register numbers */ enum { ARC_R0, ARC_R1, ARC_R2, ARC_R3, ARC_R4, ARC_R5, ARC_R6, ARC_R7, ARC_R8, ARC_R9, ARC_R10, ARC_R11, ARC_R12, ARC_R13, ARC_R14, ARC_R15, ARC_R16, ARC_R17, ARC_R18, ARC_R19, ARC_R20, ARC_R21, ARC_R22, ARC_R23, ARC_R24, ARC_R25, ARC_GP = 26, ARC_FP = 27, ARC_SP = 28, ARC_ILINK = 29, ARC_R30, ARC_BLINK = 31, ARC_LP_COUNT = 60, /* Reserved registers */ ARC_R61 = 61, ARC_R62 = 62, ARC_PCL = 63, ARC_PC = 64, ARC_LP_START = 65, ARC_LP_END = 66, ARC_STATUS32 = 67, }; #define CORE_REG_MAX_NUMBER (63) /* Limit reg_type/reg_type_field name to 20 symbols */ #define REG_TYPE_MAX_NAME_LENGTH 20 /* ARC 32bits opcodes */ #define ARC_SDBBP_32 0x256F003FU /* BRK */ /* ARC 16bits opcodes */ #define ARC_SDBBP_16 0x7FFF /* BRK_S */ /* Cache registers */ #define AUX_IC_IVIC_REG 0X10 #define IC_IVIC_INVALIDATE 0XFFFFFFFF #define AUX_DC_IVDC_REG 0X47 #define DC_IVDC_INVALIDATE BIT(0) #define AUX_DC_CTRL_REG 0X48 #define DC_CTRL_IM BIT(6) /* L2 cache registers */ #define SLC_AUX_CACHE_CTRL 0x903 #define L2_CTRL_IM BIT(6) #define L2_CTRL_BS BIT(8) /* Busy flag */ #define SLC_AUX_CACHE_FLUSH 0x904 #define L2_FLUSH_FL BIT(0) #define SLC_AUX_CACHE_INV 0x905 #define L2_INV_IV BIT(0) /* Action Point */ #define AP_AC_AT_INST_ADDR 0x0 #define AP_AC_AT_MEMORY_ADDR 0x2 #define AP_AC_AT_AUXREG_ADDR 0x4 #define AP_AC_TT_DISABLE 0x00 #define AP_AC_TT_WRITE 0x10 #define AP_AC_TT_READ 0x20 #define AP_AC_TT_READWRITE 0x30 struct arc_reg_bitfield { struct reg_data_type_bitfield bitfield; char name[REG_TYPE_MAX_NAME_LENGTH]; }; /* Register data type */ struct arc_reg_data_type { struct list_head list; struct reg_data_type data_type; struct reg_data_type_flags data_type_flags; struct reg_data_type_struct data_type_struct; char data_type_id[REG_TYPE_MAX_NAME_LENGTH]; struct arc_reg_bitfield *bitfields; union { struct reg_data_type_struct_field *reg_type_struct_field; struct reg_data_type_flags_field *reg_type_flags_field; }; }; /* Standard GDB register types */ static const struct reg_data_type standard_gdb_types[] = { { .type = REG_TYPE_INT, .id = "int" }, { .type = REG_TYPE_INT8, .id = "int8" }, { .type = REG_TYPE_INT16, .id = "int16" }, { .type = REG_TYPE_INT32, .id = "int32" }, { .type = REG_TYPE_INT64, .id = "int64" }, { .type = REG_TYPE_INT128, .id = "int128" }, { .type = REG_TYPE_UINT8, .id = "uint8" }, { .type = REG_TYPE_UINT16, .id = "uint16" }, { .type = REG_TYPE_UINT32, .id = "uint32" }, { .type = REG_TYPE_UINT64, .id = "uint64" }, { .type = REG_TYPE_UINT128, .id = "uint128" }, { .type = REG_TYPE_CODE_PTR, .id = "code_ptr" }, { .type = REG_TYPE_DATA_PTR, .id = "data_ptr" }, { .type = REG_TYPE_FLOAT, .id = "float" }, { .type = REG_TYPE_IEEE_SINGLE, .id = "ieee_single" }, { .type = REG_TYPE_IEEE_DOUBLE, .id = "ieee_double" }, }; enum arc_actionpointype { ARC_AP_BREAKPOINT, ARC_AP_WATCHPOINT, }; /* Actionpoint related fields */ struct arc_actionpoint { int used; uint32_t bp_value; uint32_t reg_address; enum arc_actionpointype type; }; struct arc_common { unsigned int common_magic; struct arc_jtag jtag_info; struct reg_cache *core_and_aux_cache; struct reg_cache *bcr_cache; /* Cache control */ bool has_dcache; bool has_icache; bool has_l2cache; /* If true, then D$ has been already flushed since core has been * halted. */ bool dcache_flushed; /* If true, then L2 has been already flushed since core has been * halted. */ bool l2cache_flushed; /* If true, then caches have been already flushed since core has been * halted. */ bool icache_invalidated; bool dcache_invalidated; bool l2cache_invalidated; /* Indicate if cache was built (for deinit function) */ bool core_aux_cache_built; bool bcr_cache_built; /* Closely Coupled memory(CCM) regions for performance-critical * code (optional). */ uint32_t iccm0_start; uint32_t iccm0_end; uint32_t iccm1_start; uint32_t iccm1_end; uint32_t dccm_start; uint32_t dccm_end; int irq_state; /* Register descriptions */ struct list_head reg_data_types; struct list_head core_reg_descriptions; struct list_head aux_reg_descriptions; struct list_head bcr_reg_descriptions; unsigned long num_regs; unsigned long num_core_regs; unsigned long num_aux_regs; unsigned long num_bcr_regs; unsigned long last_general_reg; /* PC register location in register cache. */ unsigned long pc_index_in_cache; /* DEBUG register location in register cache. */ unsigned long debug_index_in_cache; /* Actionpoints */ unsigned int actionpoints_num; unsigned int actionpoints_num_avail; struct arc_actionpoint *actionpoints_list; }; /* Borrowed from nds32.h */ #define CHECK_RETVAL(action) \ do { \ int __retval = (action); \ if (__retval != ERROR_OK) { \ LOG_DEBUG("error while calling \"%s\"", \ # action); \ return __retval; \ } \ } while (0) static inline struct arc_common *target_to_arc(struct target *target) { return target->arch_info; } /* ----- Inlined functions ------------------------------------------------- */ /** * Convert data in host endianness to the middle endian. This is required to * write 4-byte instructions. */ static inline void arc_h_u32_to_me(uint8_t *buf, int val) { buf[1] = (uint8_t) (val >> 24); buf[0] = (uint8_t) (val >> 16); buf[3] = (uint8_t) (val >> 8); buf[2] = (uint8_t) (val >> 0); } /** * Convert data in middle endian to host endian. This is required to read 32-bit * instruction from little endian ARCs. */ static inline uint32_t arc_me_to_h_u32(const uint8_t *buf) { return (uint32_t)(buf[2] | buf[3] << 8 | buf[0] << 16 | buf[1] << 24); } /* ARC Register description */ struct arc_reg_desc { struct target *target; /* Register name */ char *name; /* Actual place of storing reg_value */ uint8_t reg_value[4]; /* Actual place of storing register feature */ struct reg_feature feature; /* GDB XML feature */ char *gdb_xml_feature; /* Is this a register in g/G-packet? */ bool is_general; /* Architectural number: core reg num or AUX reg num */ uint32_t arch_num; /* Core or AUX register? */ bool is_core; /* Build configuration register? */ bool is_bcr; /* Data type */ struct reg_data_type *data_type; struct list_head list; }; /* Error codes */ #define ERROR_ARC_REGISTER_NOT_FOUND (-700) #define ERROR_ARC_REGISTER_FIELD_NOT_FOUND (-701) #define ERROR_ARC_REGISTER_IS_NOT_STRUCT (-702) #define ERROR_ARC_FIELD_IS_NOT_BITFIELD (-703) #define ERROR_ARC_REGTYPE_NOT_FOUND (-704) void free_reg_desc(struct arc_reg_desc *r); void arc_reg_data_type_add(struct target *target, struct arc_reg_data_type *data_type); int arc_reg_add(struct target *target, struct arc_reg_desc *arc_reg, const char * const type_name, const size_t type_name_len); struct reg *arc_reg_get_by_name(struct reg_cache *first, const char *name, bool search_all); int arc_reg_get_field(struct target *target, const char *reg_name, const char *field_name, uint32_t *value_ptr); int arc_cache_flush(struct target *target); int arc_cache_invalidate(struct target *target); int arc_add_auxreg_actionpoint(struct target *target, uint32_t auxreg_addr, uint32_t transaction); int arc_remove_auxreg_actionpoint(struct target *target, uint32_t auxreg_addr); int arc_set_actionpoints_num(struct target *target, uint32_t ap_num); #endif /* OPENOCD_TARGET_ARC_H */