target: add generic Xtensa LX support
[fw/openocd] / src / target / xtensa / xtensa.h
index d6000d80e7a00f5ae4c4e365fd0869941b3215ad..fd03f07f85375ff10dcf57eab806063e5d4158bb 100644 (file)
@@ -2,6 +2,7 @@
 
 /***************************************************************************
  *   Generic Xtensa target                                                 *
+ *   Copyright (C) 2020-2022 Cadence Design Systems, Inc.                  *
  *   Copyright (C) 2019 Espressif Systems Ltd.                             *
  ***************************************************************************/
 
  * Holds the interface to Xtensa cores.
  */
 
-#define XT_ISNS_SZ_MAX                  3
+/* Big-endian vs. little-endian detection */
+#define XT_ISBE(X)                              ((X)->target->endianness == TARGET_BIG_ENDIAN)
 
-#define XT_PS_RING(_v_)                 ((uint32_t)((_v_) & 0x3) << 6)
-#define XT_PS_RING_MSK                  (0x3 << 6)
-#define XT_PS_RING_GET(_v_)             (((_v_) >> 6) & 0x3)
-#define XT_PS_CALLINC_MSK               (0x3 << 16)
-#define XT_PS_OWB_MSK                   (0xF << 8)
+/* 24-bit break; BE version field-swapped then byte-swapped for use in memory R/W fns */
+#define XT_INS_BREAK_LE(S, T)                   (0x004000 | (((S) & 0xF) << 8) | (((T) & 0xF) << 4))
+#define XT_INS_BREAK_BE(S, T)                   (0x000400 | (((S) & 0xF) << 12) | ((T) & 0xF))
+#define XT_INS_BREAK(X, S, T)                   (XT_ISBE(X) ? XT_INS_BREAK_BE(S, T) : XT_INS_BREAK_LE(S, T))
 
-#define XT_LOCAL_MEM_REGIONS_NUM_MAX    8
+/* 16-bit break; BE version field-swapped then byte-swapped for use in memory R/W fns */
+#define XT_INS_BREAKN_LE(IMM4)                  (0xF02D | (((IMM4) & 0xF) << 8))
+#define XT_INS_BREAKN_BE(IMM4)                  (0x0FD2 | (((IMM4) & 0xF) << 12))
+#define XT_INS_BREAKN(X, IMM4)                  (XT_ISBE(X) ? XT_INS_BREAKN_BE(IMM4) : XT_INS_BREAKN_LE(IMM4))
 
-#define XT_AREGS_NUM_MAX                64
-#define XT_USER_REGS_NUM_MAX            256
+#define XT_ISNS_SZ_MAX                          3
 
-#define XT_MEM_ACCESS_NONE              0x0
-#define XT_MEM_ACCESS_READ              0x1
-#define XT_MEM_ACCESS_WRITE             0x2
+#define XT_PS_RING(_v_)                         ((uint32_t)((_v_) & 0x3) << 6)
+#define XT_PS_RING_MSK                          (0x3 << 6)
+#define XT_PS_RING_GET(_v_)                     (((_v_) >> 6) & 0x3)
+#define XT_PS_CALLINC_MSK                       (0x3 << 16)
+#define XT_PS_OWB_MSK                           (0xF << 8)
+#define XT_PS_WOE_MSK                           BIT(18)
 
-enum xtensa_mem_err_detect {
-       XT_MEM_ERR_DETECT_NONE,
-       XT_MEM_ERR_DETECT_PARITY,
-       XT_MEM_ERR_DETECT_ECC,
+#define XT_LOCAL_MEM_REGIONS_NUM_MAX            8
+
+#define XT_AREGS_NUM_MAX                        64
+#define XT_USER_REGS_NUM_MAX                    256
+
+#define XT_MEM_ACCESS_NONE                      0x0
+#define XT_MEM_ACCESS_READ                      0x1
+#define XT_MEM_ACCESS_WRITE                     0x2
+
+#define XT_MAX_TIE_REG_WIDTH                    (512)  /* TIE register file max 4096 bits */
+#define XT_QUERYPKT_RESP_MAX                    (XT_MAX_TIE_REG_WIDTH * 2 + 1)
+
+enum xtensa_qerr_e {
+       XT_QERR_INTERNAL = 0,
+       XT_QERR_FAIL,
+       XT_QERR_INVAL,
+       XT_QERR_MEM,
+       XT_QERR_NUM,
+};
+
+/* An and ARn registers potentially used as scratch regs */
+enum xtensa_ar_scratch_set_e {
+       XT_AR_SCRATCH_A3 = 0,
+       XT_AR_SCRATCH_AR3,
+       XT_AR_SCRATCH_A4,
+       XT_AR_SCRATCH_AR4,
+       XT_AR_SCRATCH_NUM
+};
+
+struct xtensa_keyval_info_s {
+       char *chrval;
+       int intval;
+};
+
+enum xtensa_type {
+       XT_UNDEF = 0,
+       XT_LX,
 };
 
 struct xtensa_cache_config {
        uint8_t way_count;
-       uint8_t line_size;
-       uint16_t size;
-       bool writeback;
-       enum xtensa_mem_err_detect mem_err_check;
+       uint32_t line_size;
+       uint32_t size;
+       int writeback;
 };
 
 struct xtensa_local_mem_region_config {
        target_addr_t base;
        uint32_t size;
-       enum xtensa_mem_err_detect mem_err_check;
        int access;
 };
 
@@ -66,13 +103,14 @@ struct xtensa_mmu_config {
        bool enabled;
        uint8_t itlb_entries_count;
        uint8_t dtlb_entries_count;
-       bool ivarway56;
-       bool dvarway56;
 };
 
-struct xtensa_exception_config {
+struct xtensa_mpu_config {
        bool enabled;
-       uint8_t depc_num;
+       uint8_t nfgseg;
+       uint32_t minsegsize;
+       bool lockable;
+       bool execonly;
 };
 
 struct xtensa_irq_config {
@@ -82,8 +120,8 @@ struct xtensa_irq_config {
 
 struct xtensa_high_prio_irq_config {
        bool enabled;
+       uint8_t level_num;
        uint8_t excm_level;
-       uint8_t nmi_num;
 };
 
 struct xtensa_debug_config {
@@ -91,7 +129,7 @@ struct xtensa_debug_config {
        uint8_t irq_level;
        uint8_t ibreaks_num;
        uint8_t dbreaks_num;
-       uint8_t icount_sz;
+       uint8_t perfcount_num;
 };
 
 struct xtensa_tracing_config {
@@ -100,48 +138,26 @@ struct xtensa_tracing_config {
        bool reversed_mem_access;
 };
 
-struct xtensa_timer_irq_config {
-       bool enabled;
-       uint8_t comp_num;
-};
-
 struct xtensa_config {
-       bool density;
+       enum xtensa_type core_type;
        uint8_t aregs_num;
        bool windowed;
        bool coproc;
-       bool fp_coproc;
-       bool loop;
-       uint8_t miscregs_num;
-       bool threadptr;
-       bool boolean;
-       bool cond_store;
-       bool ext_l32r;
-       bool mac16;
-       bool reloc_vec;
-       bool proc_id;
-       bool mem_err_check;
-       uint16_t user_regs_num;
-       const struct xtensa_user_reg_desc *user_regs;
-       int (*fetch_user_regs)(struct target *target);
-       int (*queue_write_dirty_user_regs)(struct target *target);
+       bool exceptions;
+       struct xtensa_irq_config irq;
+       struct xtensa_high_prio_irq_config high_irq;
+       struct xtensa_mmu_config mmu;
+       struct xtensa_mpu_config mpu;
+       struct xtensa_debug_config debug;
+       struct xtensa_tracing_config trace;
        struct xtensa_cache_config icache;
        struct xtensa_cache_config dcache;
        struct xtensa_local_mem_config irom;
        struct xtensa_local_mem_config iram;
        struct xtensa_local_mem_config drom;
        struct xtensa_local_mem_config dram;
-       struct xtensa_local_mem_config uram;
-       struct xtensa_local_mem_config xlmi;
-       struct xtensa_mmu_config mmu;
-       struct xtensa_exception_config exc;
-       struct xtensa_irq_config irq;
-       struct xtensa_high_prio_irq_config high_irq;
-       struct xtensa_timer_irq_config tim_irq;
-       struct xtensa_debug_config debug;
-       struct xtensa_tracing_config trace;
-       unsigned int gdb_general_regs_num;
-       const unsigned int *gdb_regs_mapping;
+       struct xtensa_local_mem_config sram;
+       struct xtensa_local_mem_config srom;
 };
 
 typedef uint32_t xtensa_insn_t;
@@ -175,13 +191,26 @@ struct xtensa_sw_breakpoint {
  */
 struct xtensa {
        unsigned int common_magic;
-       const struct xtensa_config *core_config;
+       struct xtensa_chip_common *xtensa_chip;
+       struct xtensa_config *core_config;
        struct xtensa_debug_module dbg_mod;
        struct reg_cache *core_cache;
-       unsigned int regs_num;
+       unsigned int total_regs_num;
+       unsigned int core_regs_num;
+       bool regmap_contiguous;
+       unsigned int genpkt_regs_num;
+       struct xtensa_reg_desc **contiguous_regs_desc;
+       struct reg **contiguous_regs_list;
+       /* Per-config Xtensa registers as specified via "xtreg" in xtensa-core*.cfg */
+       struct xtensa_reg_desc *optregs;
+       unsigned int num_optregs;
+       struct reg *empty_regs;
+       char qpkt_resp[XT_QUERYPKT_RESP_MAX];
        /* An array of pointers to buffers to backup registers' values while algo is run on target.
         * Size is 'regs_num'. */
        void **algo_context_backup;
+       unsigned int eps_dbglevel_idx;
+       unsigned int dbregs_num;
        struct target *target;
        bool reset_asserted;
        enum xtensa_stepping_isr_mode stepping_isr_mode;
@@ -192,11 +221,18 @@ struct xtensa {
        bool permissive_mode;   /* bypass memory checks */
        bool suppress_dsr_errors;
        uint32_t smp_break;
+       uint32_t spill_loc;
+       unsigned int spill_bytes;
+       uint8_t *spill_buf;
+       int8_t probe_lsddr32p;
        /* Sometimes debug module's 'powered' bit is cleared after reset, but get set after some
         * time.This is the number of polling periods after which core is considered to be powered
         * off (marked as unexamined) if the bit retains to be cleared (e.g. if core is disabled by
         * SW running on target).*/
        uint8_t come_online_probes_num;
+       bool proc_syscall;
+       bool halt_request;
+       struct xtensa_keyval_info_s scratch_ars[XT_AR_SCRATCH_NUM];
        bool regs_fetched;      /* true after first register fetch completed successfully */
 };
 
@@ -210,7 +246,6 @@ static inline struct xtensa *target_to_xtensa(struct target *target)
 
 int xtensa_init_arch_info(struct target *target,
        struct xtensa *xtensa,
-       const struct xtensa_config *cfg,
        const struct xtensa_debug_module_config *dm_cfg);
 int xtensa_target_init(struct command_context *cmd_ctx, struct target *target);
 void xtensa_target_deinit(struct target *target);
@@ -233,11 +268,41 @@ static inline bool xtensa_data_addr_valid(struct target *target, uint32_t addr)
                return true;
        if (xtensa_addr_in_mem(&xtensa->core_config->dram, addr))
                return true;
-       if (xtensa_addr_in_mem(&xtensa->core_config->uram, addr))
+       if (xtensa_addr_in_mem(&xtensa->core_config->sram, addr))
                return true;
        return false;
 }
 
+static inline int xtensa_queue_dbg_reg_read(struct xtensa *xtensa, unsigned int reg, uint8_t *data)
+{
+       struct xtensa_debug_module *dm = &xtensa->dbg_mod;
+
+       if (!xtensa->core_config->trace.enabled &&
+               (reg <= NARADR_MEMADDREND || (reg >= NARADR_PMG && reg <= NARADR_PMSTAT7))) {
+               LOG_ERROR("Can not access %u reg when Trace Port option disabled!", reg);
+               return ERROR_FAIL;
+       }
+       return dm->dbg_ops->queue_reg_read(dm, reg, data);
+}
+
+static inline int xtensa_queue_dbg_reg_write(struct xtensa *xtensa, unsigned int reg, uint32_t data)
+{
+       struct xtensa_debug_module *dm = &xtensa->dbg_mod;
+
+       if (!xtensa->core_config->trace.enabled &&
+               (reg <= NARADR_MEMADDREND || (reg >= NARADR_PMG && reg <= NARADR_PMSTAT7))) {
+               LOG_ERROR("Can not access %u reg when Trace Port option disabled!", reg);
+               return ERROR_FAIL;
+       }
+       return dm->dbg_ops->queue_reg_write(dm, reg, data);
+}
+
+static inline int xtensa_core_status_clear(struct target *target, uint32_t bits)
+{
+       struct xtensa *xtensa = target_to_xtensa(target);
+       return xtensa_dm_core_status_clear(&xtensa->dbg_mod, bits);
+}
+
 int xtensa_core_status_check(struct target *target);
 
 int xtensa_examine(struct target *target);
@@ -248,11 +313,15 @@ int xtensa_smpbreak_write(struct xtensa *xtensa, uint32_t set);
 int xtensa_smpbreak_read(struct xtensa *xtensa, uint32_t *val);
 xtensa_reg_val_t xtensa_reg_get(struct target *target, enum xtensa_reg_id reg_id);
 void xtensa_reg_set(struct target *target, enum xtensa_reg_id reg_id, xtensa_reg_val_t value);
+void xtensa_reg_set_deep_relgen(struct target *target, enum xtensa_reg_id a_idx, xtensa_reg_val_t value);
 int xtensa_fetch_all_regs(struct target *target);
 int xtensa_get_gdb_reg_list(struct target *target,
        struct reg **reg_list[],
        int *reg_list_size,
        enum target_register_class reg_class);
+uint32_t xtensa_cause_get(struct target *target);
+void xtensa_cause_clear(struct target *target);
+void xtensa_cause_reset(struct target *target);
 int xtensa_poll(struct target *target);
 void xtensa_on_poll(struct target *target);
 int xtensa_halt(struct target *target);
@@ -281,16 +350,22 @@ int xtensa_write_buffer(struct target *target, target_addr_t address, uint32_t c
 int xtensa_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum);
 int xtensa_assert_reset(struct target *target);
 int xtensa_deassert_reset(struct target *target);
+int xtensa_soft_reset_halt(struct target *target);
 int xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint);
 int xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint);
 int xtensa_watchpoint_add(struct target *target, struct watchpoint *watchpoint);
 int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoint);
 void xtensa_set_permissive_mode(struct target *target, bool state);
-int xtensa_fetch_user_regs_u32(struct target *target);
-int xtensa_queue_write_dirty_user_regs_u32(struct target *target);
 const char *xtensa_get_gdb_arch(struct target *target);
-
-
+int xtensa_gdb_query_custom(struct target *target, const char *packet, char **response_p);
+
+COMMAND_HELPER(xtensa_cmd_xtdef_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtopt_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtmem_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtmpu_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtmmu_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtreg_do, struct xtensa *xtensa);
+COMMAND_HELPER(xtensa_cmd_xtregfmt_do, struct xtensa *xtensa);
 COMMAND_HELPER(xtensa_cmd_permissive_mode_do, struct xtensa *xtensa);
 COMMAND_HELPER(xtensa_cmd_mask_interrupts_do, struct xtensa *xtensa);
 COMMAND_HELPER(xtensa_cmd_smpbreak_do, struct target *target);
@@ -300,8 +375,6 @@ COMMAND_HELPER(xtensa_cmd_tracestart_do, struct xtensa *xtensa);
 COMMAND_HELPER(xtensa_cmd_tracestop_do, struct xtensa *xtensa);
 COMMAND_HELPER(xtensa_cmd_tracedump_do, struct xtensa *xtensa, const char *fname);
 
-extern const struct reg_arch_type xtensa_user_reg_u32_type;
-extern const struct reg_arch_type xtensa_user_reg_u128_type;
 extern const struct command_registration xtensa_command_handlers[];
 
 #endif /* OPENOCD_TARGET_XTENSA_H */