diff --git a/doc/openocd.texi b/doc/openocd.texi index cc133f7916..cf41bc538a 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -10981,6 +10981,64 @@ addreg rtest 0x1234 org.gnu.gdb.or1k.group0 system @end deffn +@section MIPS Architecture +@cindex microMIPS +@cindex MIPS32 +@cindex MIPS64 + +@uref{http://mips.com/, MIPS} is a simple, streamlined, highly scalable RISC +architecture. The architecture is evolving over time, from MIPS I~V to +MIPS release 1~6 iterations, the architecture is now able to handle various tasks +with different ASEs, including SIMD(MSA), DSP, VZ, MT and more. +MIPS32 supports 32-bit programs while MIPS64 can support both 32-bit and 64-bit programs. + +@subsection MIPS Terminology + +The term ASE means Application-Specific Extension, ASEs provide features that +improve the efficiency and performance of certain workloads, such as +digital signal processing(DSP), Virtualization(VZ), Multi-Threading(MT), +SIMD(MSA) and more. +The MIPS CPU Uses Coprocessors to configure its behaviour or to let software +know the capabilities of current CPU, the commonly used ones are Config0~3 Registers +and Status register. + +@subsection MIPS FPU & Vector Registers + +MIPS processors does not all comes with FPU co-processor, and when it does, the FPU +appears as Coprocessor 1 whereas the Coprocessor 0 is for the main processor. + +Most of MIPS FPUs are 64 bits, IEEE 754 standard, and they provides both 32-bit +single precision and 64-bit double precision calculations. Fixed point format +calculations are also provided with both 32 and 64-bit modes. + +The MIPS SIMD Architecture(MSA) operates on 32 128-bit wide vector registers. +If both MSA and the scalar floating-point unit (FPU) are present, the 128-bit MSA +vector registers extend and share the 64-bit FPU registers. MSA and FPU can not be +both present, unless the FPU has 64-bit floating-point register. + +@subsection MIPS Configuration Commands + +@deffn {Command} {mips32 cpuinfo} +Displays detailed information about current CPU core. This includes core type, +vendor, instruction set, cache size, and other relevant details. +@end deffn + +@deffn {Config Command} {mips32 scan_delay} [nanoseconds] +Display or set scan delay in nano seconds. A value below 2_000_000 will set the +scan delay into legacy mode. +@end deffn + +@deffn {Config Command} {mips32 cp0} regnum select [value] +Displays or sets coprocessor 0 register by register number and select. + +For common MIPS Coprocessor 0 registers, you can find the definitions of them +on MIPS Privileged Resource Architecture Documents(MIPS Document MD00090). + +For core specific cp0 registers, you can find the definitions of them on Core +Specific Software User's Manual, for example, MIPS M5150 Software User Manual +(MD00980). +@end deffn + @section RISC-V Architecture @uref{http://riscv.org/, RISC-V} is a free and open ISA. OpenOCD supports JTAG diff --git a/src/target/mips32.c b/src/target/mips32.c index 5c346c42dd..af5f2c50d8 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -160,6 +160,7 @@ static const struct { #define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs) + static int mips32_get_core_reg(struct reg *reg) { int retval; @@ -333,9 +334,7 @@ int mips32_restore_context(struct target *target) } /* write core regs */ - mips32_pracc_write_regs(mips32); - - return ERROR_OK; + return mips32_pracc_write_regs(mips32); } int mips32_arch_state(struct target *target) @@ -764,18 +763,56 @@ static int mips32_read_c0_prid(struct target *target) return retval; } -/* - * Detect processor type and apply required quirks. +/** + * mips32_find_cpu_by_prid - Find CPU information by processor ID. + * @param[in] prid: Processor ID of the CPU. + * + * @brief This function looks up the CPU entry in the mips32_cpu_entry array based on the provided + * processor ID. It also handles special cases like AMD/Alchemy CPUs that use Company Options + * instead of Processor IDs. + * + * @return Pointer to the corresponding cpu_entry struct, or the 'unknown' entry if not found. + */ +static const struct cpu_entry *mips32_find_cpu_by_prid(uint32_t prid) +{ + /* AMD/Alchemy CPU uses Company Options instead of Processor ID. + * Therefore an extra transform step for prid to map it to an assigned ID, + */ + if ((prid & PRID_COMP_MASK) == PRID_COMP_ALCHEMY) { + /* Clears Processor ID field, then put Company Option field to its place */ + prid = (prid & 0xFFFF00FF) | ((prid & 0xFF000000) >> 16); + } + + /* Mask out Company Option */ + prid &= 0x00FFFFFF; + + for (unsigned int i = 0; i < MIPS32_NUM_CPU_ENTRIES; i++) { + const struct cpu_entry *entry = &mips32_cpu_entry[i]; + if ((entry->prid & MIPS32_CORE_MASK) <= prid && prid <= entry->prid) + return entry; + } + + /* If nothing matched, then return unknown entry */ + return &mips32_cpu_entry[MIPS32_NUM_CPU_ENTRIES - 1]; +} + +/** + * mips32_cpu_probe - Detects processor type and applies necessary quirks. + * @param[in] target: The target CPU to probe. + * + * @brief This function probes the CPU, reads its PRID (Processor ID), and determines the CPU type. + * It applies any quirks necessary for specific processor types. * * NOTE: The proper detection of certain CPUs can become quite complicated. * Please consult the following Linux kernel code when adding new CPUs: * arch/mips/include/asm/cpu.h * arch/mips/kernel/cpu-probe.c + * + * @return ERROR_OK on success; error code on failure. */ int mips32_cpu_probe(struct target *target) { struct mips32_common *mips32 = target_to_mips32(target); - const char *cpu_name = "unknown"; int retval; if (mips32->prid) @@ -785,11 +822,12 @@ int mips32_cpu_probe(struct target *target) if (retval != ERROR_OK) return retval; + const struct cpu_entry *entry = mips32_find_cpu_by_prid(mips32->prid); + switch (mips32->prid & PRID_COMP_MASK) { case PRID_COMP_INGENIC_E1: switch (mips32->prid & PRID_IMP_MASK) { case PRID_IMP_XBURST_REV1: - cpu_name = "Ingenic XBurst rev1"; mips32->cpu_quirks |= EJTAG_QUIRK_PAD_DRET; break; default: @@ -800,13 +838,14 @@ int mips32_cpu_probe(struct target *target) break; } - LOG_DEBUG("CPU: %s (PRId %08x)", cpu_name, mips32->prid); + mips32->cpu_info = entry; + LOG_DEBUG("CPU: %s (PRId %08x)", entry->cpu_name, mips32->prid); return ERROR_OK; } /* reads dsp implementation info from CP0 Config3 register {DSPP, DSPREV}*/ -void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejtag_info) +static void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejtag_info) { uint32_t dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT); if (dsp_present) { @@ -818,7 +857,7 @@ void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejt } /* read fpu implementation info from CP0 Config1 register {CU1, FP}*/ -int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejtag *ejtag_info) +static int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejtag *ejtag_info) { int retval; uint32_t fp_imp = (ejtag_info->config[1] & MIPS32_CONFIG1_FP_MASK) >> MIPS32_CONFIG1_FP_SHIFT; @@ -858,8 +897,23 @@ int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejtag *ejta return ERROR_OK; } -/* Checks if current target implements Common Device Memory Map and therefore Fast Debug Channel (MD00090) */ -void mips32_read_config_fdc(struct mips32_common *mips32, struct mips_ejtag *ejtag_info, uint32_t dcr) +/** + * mips32_read_config_fdc - Read Fast Debug Channel configuration + * @param[in,out] mips32: MIPS32 common structure + * @param[in] ejtag_info: EJTAG information structure + * @param[in] dcr: Device Configuration Register value + * + * @brief Checks if the current target implements the Common Device Memory Map (CDMM) and Fast Debug Channel (FDC). + * + * This function examines the configuration registers and the Device Configuration Register (DCR) to determine + * if the current MIPS32 target supports the Common Device Memory Map (CDMM) and the Fast Debug Channel (FDC). + * If supported, it sets the corresponding flags in the MIPS32 common structure. \n + * + * NOTE:These are defined on MD00090, page 67 and MD00047F, page 82, respectively. + * MIPS Documents are pretty much all available online, + * it should pop up first when you search "MDxxxxx" + */ +static void mips32_read_config_fdc(struct mips32_common *mips32, struct mips_ejtag *ejtag_info, uint32_t dcr) { if (((ejtag_info->config[3] & MIPS32_CONFIG3_CDMM_MASK) != 0) && ((dcr & EJTAG_DCR_FDC) != 0)) { mips32->fdc = 1; @@ -1112,6 +1166,51 @@ static int mips32_verify_pointer(struct command_invocation *cmd, return ERROR_OK; } +/** + * mips32_read_config_mmu - Reads MMU configuration and logs relevant information. + * @param[in] ejtag_info: EJTAG interface information. + * + * @brief Reads the MMU configuration from the CP0 register and calculates the number of TLB entries, + * ways, and sets. Handles different MMU types like VTLB only, root RPU/Fixed, and VTLB and FTLB. + * + * @return ERROR_OK on success; error code on failure. + */ +static int mips32_read_config_mmu(struct mips_ejtag *ejtag_info) +{ + uint32_t config4, tlb_entries = 0, ways = 0, sets = 0; + uint32_t config0 = ejtag_info->config[0]; + uint32_t config1 = ejtag_info->config[1]; + uint32_t config3 = ejtag_info->config[3]; + uint32_t mmu_type = (config0 >> 7) & 7; + uint32_t vz_present = (config3 & BIT(23)); + + int retval = mips32_cp0_read(ejtag_info, &config4, 16, 4); + if (retval != ERROR_OK) + return retval; + + /* mmu type = 1: VTLB only (Note: Does not account for Config4.ExtVTLB) + * mmu type = 3: root RPU/Fixed (Note: Only valid with VZ ASE) + * mmu type = 4: VTLB and FTLB + */ + if ((mmu_type == 1 || mmu_type == 4) || (mmu_type == 3 && vz_present)) { + tlb_entries = (uint32_t)(((config1 >> 25) & 0x3f) + 1); + if (mmu_type == 4) { + /* Release 6 definition for Config4[0:15] (MD01251, page 243) */ + /* The FTLB ways field is defined as [2, 3, 4, 5, 6, 7, 8, ...0 (reserved)] */ + int index = ((config4 >> 4) & 0xf); + ways = index > 6 ? 0 : index + 2; + + /* The FTLB sets field is defined as [1, 2, 4, 8, ..., 16384, 32768] (powers of 2) */ + index = (config4 & 0xf); + sets = 1 << index; + tlb_entries = tlb_entries + (ways * sets); + } + } + LOG_USER("TLB Entries: %d (%d ways, %d sets per way)", tlb_entries, ways, sets); + + return ERROR_OK; +} + /** * MIPS32 targets expose command interface * to manipulate CP0 registers @@ -1172,6 +1271,207 @@ COMMAND_HANDLER(mips32_handle_cp0_command) return ERROR_OK; } +/** + * mips32_handle_cpuinfo_command - Handles the 'cpuinfo' command. + * @param[in] cmd: Command invocation context. + * + * @brief Executes the 'cpuinfo' command which displays detailed information about the current CPU core. + * This includes core type, vendor, instruction set, cache size, and other relevant details. + * + * @return ERROR_OK on success; error code on failure. + */ +COMMAND_HANDLER(mips32_handle_cpuinfo_command) +{ + int retval; + struct target *target = get_current_target(CMD_CTX); + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + + uint32_t prid = mips32->prid; /* cp0 PRID - 15, 0 */ + uint32_t config0 = ejtag_info->config[0]; /* cp0 config - 16, 0 */ + uint32_t config1 = ejtag_info->config[1]; /* cp0 config - 16, 1 */ + uint32_t config3 = ejtag_info->config[3]; /* cp0 config - 16, 3 */ + + /* Following configs are not read during probe */ + uint32_t config5; /* cp0 config - 16, 5 */ + + /* No args for now */ + if (CMD_ARGC != 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (target->state != TARGET_HALTED) { + command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME); + return ERROR_TARGET_NOT_HALTED; + } + + retval = mips32_cp0_read(ejtag_info, &config5, 16, 5); + if (retval != ERROR_OK) + return retval; + + /* Determine Core info */ + const struct cpu_entry *entry = mips32->cpu_info; + /* Display Core Type info */ + command_print(CMD, "CPU Core: %s", entry->cpu_name); + + /* Display Core Vendor ID if it's unknown */ + if (entry == &mips32_cpu_entry[MIPS32_NUM_CPU_ENTRIES - 1]) + command_print(CMD, "Vendor: Unknown CPU vendor code %x.", ((prid & 0x00ffff00) >> 16)); + else + command_print(CMD, "Vendor: %s", entry->vendor); + + /* If MIPS release 2 or above, then get exception base info */ + enum mips32_isa_rel ar = mips32->isa_rel; + if (ar > MIPS32_RELEASE_1) { /* release 2 and above */ + uint32_t ebase; + retval = mips32_cp0_read(ejtag_info, &ebase, 15, 1); + if (retval != ERROR_OK) + return retval; + + command_print(CMD, "Current CPU ID: %d", (ebase & 0x1ff)); + } else { + command_print(CMD, "Current CPU ID: 0"); + } + + char *instr; + switch ((config3 & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT) { + case 0: + instr = "MIPS32"; + break; + case 1: + instr = "microMIPS"; + break; + case 2: + instr = "MIPS32 (at reset) and microMIPS"; + break; + case 3: + instr = "microMIPS (at reset) and MIPS32"; + break; + } + + /* Display Instruction Set Info */ + command_print(CMD, "Instr set: %s", instr); + command_print(CMD, "Instr rel: %s", + ar == MIPS32_RELEASE_1 ? "1" + : ar == MIPS32_RELEASE_2 ? "2" + : ar == MIPS32_RELEASE_6 ? "6" + : "unknown"); + command_print(CMD, "PRId: %x", prid); + /* Some of MIPS CPU Revisions(for M74K) can be seen on MD00541, page 26 */ + uint32_t rev = prid & 0x000000ff; + command_print(CMD, "RTL Rev: %d.%d.%d", (rev & 0xE0), (rev & 0x1C), (rev & 0x3)); + + command_print(CMD, "Max Number of Instr Breakpoints: %d", mips32->num_inst_bpoints); + command_print(CMD, "Max Number of Data Breakpoints: %d", mips32->num_data_bpoints); + + /* MMU Support */ + uint32_t mmu_type = (config0 >> 7) & 7; /* MMU Type Info */ + char *mmu; + switch (mmu_type) { + case MIPS32_MMU_TLB: + mmu = "TLB"; + break; + case MIPS32_MMU_BAT: + mmu = "BAT"; + break; + case MIPS32_MMU_FIXED: + mmu = "FIXED"; + break; + case MIPS32_MMU_DUAL_VTLB_FTLB: + mmu = "DUAL VAR/FIXED"; + break; + default: + mmu = "Unknown"; + } + command_print(CMD, "MMU Type: %s", mmu); + + retval = mips32_read_config_mmu(ejtag_info); + if (retval != ERROR_OK) + return retval; + + /* Definitions of I/D Cache Sizes are available on MD01251, page 224~226 */ + int index; + uint32_t ways, sets, bpl; + + /* Determine Instr Cache Size */ + /* Ways mapping = [1, 2, 3, 4, 5, 6, 7, 8] */ + ways = ((config1 >> MIPS32_CFG1_IASHIFT) & 7); + + /* Sets per way = [64, 128, 256, 512, 1024, 2048, 4096, 32] */ + index = ((config1 >> MIPS32_CFG1_ISSHIFT) & 7); + sets = index == 7 ? 32 : 32 << (index + 1); + + /* Bytes per line = [0, 4, 8, 16, 32, 64, 128, Reserved] */ + index = ((config1 >> MIPS32_CFG1_ILSHIFT) & 7); + bpl = index == 0 ? 0 : 4 << (index - 1); + command_print(CMD, "Instr Cache: %d (%d ways, %d lines, %d byte per line)", ways * sets * bpl, ways, sets, bpl); + + /* Determine data cache size, same as above */ + ways = ((config1 >> MIPS32_CFG1_DASHIFT) & 7); + + index = ((config1 >> MIPS32_CFG1_DSSHIFT) & 7); + sets = index == 7 ? 32 : 32 << (index + 1); + + index = ((config1 >> MIPS32_CFG1_DLSHIFT) & 7); + bpl = index == 0 ? 0 : 4 << (index - 1); + command_print(CMD, " Data Cache: %d (%d ways, %d lines, %d byte per line)", ways * sets * bpl, ways, sets, bpl); + + /* does the core hava FPU*/ + mips32_read_config_fpu(mips32, ejtag_info); + + /* does the core support a DSP */ + mips32_read_config_dsp(mips32, ejtag_info); + + /* VZ module */ + uint32_t vzase = (config3 & BIT(23)); + if (vzase) + command_print(CMD, "VZ implemented: yes"); + else + command_print(CMD, "VZ implemented: no"); + + /* multithreading */ + uint32_t mtase = (config3 & BIT(2)); + if (mtase) { + command_print(CMD, "MT implemented: yes"); + + /* Get VPE and Thread info */ + uint32_t tcbind; + uint32_t mvpconf0; + + /* Read tcbind register */ + retval = mips32_cp0_read(ejtag_info, &tcbind, 2, 2); + if (retval != ERROR_OK) + return retval; + + command_print(CMD, " | Current VPE: %d", (tcbind & 0xf)); + command_print(CMD, " | Current TC: %d", ((tcbind >> 21) & 0xff)); + + /* Read mvpconf0 register */ + retval = mips32_cp0_read(ejtag_info, &mvpconf0, 0, 2); + if (retval != ERROR_OK) + return retval; + + command_print(CMD, " | Total TC: %d", (mvpconf0 & 0xf) + 1); + command_print(CMD, " | Total VPE: %d", ((mvpconf0 >> 10) & 0xf) + 1); + } else { + command_print(CMD, "MT implemented: no"); + } + + /* MIPS SIMD Architecture (MSA) */ + uint32_t msa = (config3 & BIT(28)); + command_print(CMD, "MSA implemented: %s", msa ? "yes" : "no"); + + /* Move To/From High COP0 (MTHC0/MFHC0) instructions are implemented. + * Implicates current ISA release >= 5.*/ + uint32_t mvh = (config5 & BIT(5)); + command_print(CMD, "MVH implemented: %s", mvh ? "yes" : "no"); + + /* Common Device Memory Map implemented? */ + uint32_t cdmm = (config3 & BIT(3)); + command_print(CMD, "CDMM implemented: %s", cdmm ? "yes" : "no"); + + return ERROR_OK; +} + COMMAND_HANDLER(mips32_handle_scan_delay_command) { struct target *target = get_current_target(CMD_CTX); @@ -1203,7 +1503,14 @@ static const struct command_registration mips32_exec_command_handlers[] = { .usage = "regnum select [value]", .help = "display/modify cp0 register", }, - { + { + .name = "cpuinfo", + .handler = mips32_handle_cpuinfo_command, + .mode = COMMAND_EXEC, + .help = "display CPU information", + .usage = "", + }, + { .name = "scan_delay", .handler = mips32_handle_scan_delay_command, .mode = COMMAND_ANY, diff --git a/src/target/mips32.h b/src/target/mips32.h index fc896248b6..1bb75da995 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -263,6 +263,96 @@ enum mips32_isa_rel { MIPS32_RELEASE_UNKNOWN, }; +enum mips32_isa_supported { + MIPS16, + MIPS32, + MIPS64, + MICROMIPS_ONLY, + MIPS32_AT_RESET_AND_MICROMIPS, + MICROMIPS_AT_RESET_AND_MIPS32, +}; +#define MIPS32_CORE_MASK 0xFFFFFF00 +#define MIPS32_VARIANT_MASK 0x00FF + +/* This struct contains mips cpu types with their name respectively. + * The PrID register format is as following: + * - Company Optionsp[31:24] + * - Company ID[23:16] + * - Processor ID[15:8] + * - Revision[7:0] + * Here the revision field represents the maximum value of revision. + */ +static const struct cpu_entry { + uint32_t prid; + enum mips32_isa_supported isa; + const char *vendor; + const char *cpu_name; +} mips32_cpu_entry[] = { + /* MIPS Technologies cores */ + {0x000180FF, MIPS32, "MIPS", "4Kc"}, + {0x000181FF, MIPS64, "MIPS", "5Kc"}, + {0x000182FF, MIPS64, "MIPS", "20Kc"}, + {0x000183FF, MIPS32, "MIPS", "4KM"}, + + {0x000184FF, MIPS32, "MIPS", "4KEc"}, + {0x000190FF, MIPS32, "MIPS", "4KEc"}, + + {0x000185FF, MIPS32, "MIPS", "4KEm"}, + {0x000191FF, MIPS32, "MIPS", "4KEm"}, + + {0x000186FF, MIPS32, "MIPS", "4KSc"}, + {0x000187FF, MIPS32, "MIPS", "M4K"}, + {0x000188FF, MIPS64, "MIPS", "25Kf"}, + {0x000189FF, MIPS64, "MIPS", "5KEc"}, + {0x000192FF, MIPS32, "MIPS", "4KSD"}, + {0x000193FF, MIPS32, "MIPS", "24Kc"}, + {0x000195FF, MIPS32, "MIPS", "34Kc"}, + {0x000196FF, MIPS32, "MIPS", "24KEc"}, + {0x000197FF, MIPS32, "MIPS", "74Kc"}, + {0x000199FF, MIPS32, "MIPS", "1004Kc"}, + {0x00019AFF, MIPS32, "MIPS", "1074Kc"}, + {0x00019BFF, MIPS32, "MIPS", "M14K"}, + {0x00019CFF, MIPS32, "MIPS", "M14Kc"}, + {0x00019DFF, MIPS32, "MIPS", "microAptiv_UC(M14KE)"}, + {0x00019EFF, MIPS32, "MIPS", "microAptiv_UP(M14KEc)"}, + {0x0001A0FF, MIPS32, "MIPS", "interAptiv"}, + {0x0001A1FF, MIPS32, "MIPS", "interAptiv_CM"}, + {0x0001A2FF, MIPS32, "MIPS", "proAptiv"}, + {0x0001A3FF, MIPS32, "MIPS", "proAptiv_CM"}, + {0x0001A6FF, MIPS32, "MIPS", "M5100"}, + {0x0001A7FF, MIPS32, "MIPS", "M5150"}, + {0x0001A8FF, MIPS32, "MIPS", "P5600"}, + {0x0001A9FF, MIPS32, "MIPS", "I5500"}, + + /* Broadcom */ + {0x000200FF, MIPS32, "Broadcom", "Broadcom"}, + + /* AMD Alchemy Series*/ + /* NOTE: AMD/Alchemy series uses Company Option instead of + * Processor ID, to match the find function, Processor ID field + * is the copy of Company Option field */ + {0x000300FF, MIPS32, "AMD Alchemy", "AU1000"}, + {0x010301FF, MIPS32, "AMD Alchemy", "AU1500"}, + {0x020302FF, MIPS32, "AMD Alchemy", "AU1100"}, + {0x030303FF, MIPS32, "AMD Alchemy", "AU1550"}, + {0x04030401, MIPS32, "AMD Alchemy", "AU1200"}, + {0x040304FF, MIPS32, "AMD Alchemy", "AU1250"}, + {0x050305FF, MIPS32, "AMD Alchemy", "AU1210"}, + + /* Altera */ + {0x001000FF, MIPS32, "Altera", "Altera"}, + + /* Lexra */ + {0x000B00FF, MIPS32, "Lexra", "Lexra"}, + + /* Ingenic */ + {0x00e102FF, MIPS32, "Ingenic", "Ingenic XBurst rev1"}, + + {0xFFFFFFFF, MIPS32, "Unknown", "Unknown"} +}; + +#define MIPS32_NUM_CPU_ENTRIES (ARRAY_SIZE(mips32_cpu_entry)) + enum mips32_fp_imp { MIPS32_FP_IMP_NONE = 0, MIPS32_FP_IMP_32 = 1, @@ -306,7 +396,6 @@ struct mips32_common { int fdc; int semihosting; - uint32_t cp0_mask; /* FPU enabled (cp0.status.cu1) */ bool fpu_enabled; @@ -315,6 +404,8 @@ struct mips32_common { /* processor identification register */ uint32_t prid; + /* detected CPU type */ + const struct cpu_entry *cpu_info; /* CPU specific quirks */ uint32_t cpu_quirks; @@ -708,78 +799,6 @@ struct mips32_algorithm { #define MIPS32_MMU_FIXED 3 #define MIPS32_MMU_DUAL_VTLB_FTLB 4 -enum mips32_cpu_vendor { - MIPS32_CPU_VENDOR_MTI, - MIPS32_CPU_VENDOR_ALCHEMY, - MIPS32_CPU_VENDOR_BROADCOM, - MIPS32_CPU_VENDOR_ALTERA, - MIPS32_CPU_VENDOR_LEXRA, -}; - -enum mips32_isa_supported { - MIPS16, - MIPS32, - MIPS64, - MICROMIPS_ONLY, - MIPS32_AT_RESET_AND_MICROMIPS, - MICROMIPS_AT_RESET_AND_MIPS32, -}; - -struct mips32_cpu_features { - /* Type of CPU (4Kc, 24Kf, etc.) */ - uint32_t cpu_core; - - /* Internal representation of cpu type */ - uint32_t cpu_type; - - /* Processor vendor */ - enum mips32_cpu_vendor vendor; - - /* Supported ISA and boot config */ - enum mips32_isa_supported isa; - - /* PRID */ - uint32_t prid; - - /* Processor implemented the MultiThreading ASE */ - bool mtase; - - /* Processor implemented the DSP ASE */ - bool dspase; - - /* Processor implemented the SmartMIPS ASE */ - bool smase; - - /* Processor implemented the MIPS16[e] ASE */ - bool m16ase; - - /* Processor implemented the microMIPS ASE */ - bool micromipsase; - - /* Processor implemented the Virtualization ASE */ - uint32_t vzase; - - uint32_t vz_guest_id_width; - - /* ebase.cpuid number */ - uint32_t cpuid; - - uint32_t inst_cache_size; - uint32_t data_cache_size; - uint32_t mmu_type; - uint32_t tlb_entries; - uint32_t num_shadow_regs; - - /* Processor implemented the MSA module */ - bool msa; - - /* Processor implemented mfhc0 and mthc0 instructions */ - bool mvh; - - bool guest_ctl1_present; - bool cdmm; -}; - extern const struct command_registration mips32_command_handlers[]; int mips32_arch_state(struct target *target); diff --git a/src/target/mips_cpu.h b/src/target/mips_cpu.h index 8190b32e43..2f31dbd664 100644 --- a/src/target/mips_cpu.h +++ b/src/target/mips_cpu.h @@ -12,7 +12,12 @@ /* Assigned Company values for bits 23:16 of the PRId register. */ #define PRID_COMP_MASK 0xff0000 -#define PRID_COMP_LEGACY 0x000000 +#define PRID_COMP_LEGACY 0x000000 +#define PRID_COMP_MTI 0x010000 +#define PRID_COMP_BROADCOM 0x020000 +#define PRID_COMP_ALCHEMY 0x030000 +#define PRID_COMP_LEXRA 0x0b0000 +#define PRID_COMP_ALTERA 0x100000 #define PRID_COMP_INGENIC_E1 0xe10000 /* @@ -22,6 +27,12 @@ */ #define PRID_IMP_MASK 0xff00 +#define PRID_IMP_MAPTIV_UC 0x9D00 +#define PRID_IMP_MAPTIV_UP 0x9E00 +#define PRID_IMP_IAPTIV_CM 0xA000 +#define PRID_IMP_IAPTIV 0xA100 +#define PRID_IMP_M5150 0xA700 + #define PRID_IMP_XBURST_REV1 0x0200 /* XBurst®1 with MXU1.0/MXU1.1 SIMD ISA */ #endif /* OPENOCD_TARGET_MIPS_CPU_H */