target/mips32: add cpu info detection

Add detection for mips cpu types by using prid.
Add cpuinfo command for inspecting more verbose info.
Add MIPS Architecture specs in openocd docs.

Change-Id: I28573b7c51783628db986bad0e226dcc399b4fa6
Signed-off-by: Walter Ji <walter.ji@oss.cipunited.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/7912
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: Oleksij Rempel <linux@rempel-privat.de>
This commit is contained in:
Walter Ji 2023-09-26 17:21:42 +08:00 committed by Antonio Borneo
parent b717373247
commit 7de4b1202d
4 changed files with 482 additions and 87 deletions

View File

@ -10981,6 +10981,64 @@ addreg rtest 0x1234 org.gnu.gdb.or1k.group0 system
@end deffn @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 @section RISC-V Architecture
@uref{http://riscv.org/, RISC-V} is a free and open ISA. OpenOCD supports JTAG @uref{http://riscv.org/, RISC-V} is a free and open ISA. OpenOCD supports JTAG

View File

@ -160,6 +160,7 @@ static const struct {
#define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs) #define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs)
static int mips32_get_core_reg(struct reg *reg) static int mips32_get_core_reg(struct reg *reg)
{ {
int retval; int retval;
@ -333,9 +334,7 @@ int mips32_restore_context(struct target *target)
} }
/* write core regs */ /* write core regs */
mips32_pracc_write_regs(mips32); return mips32_pracc_write_regs(mips32);
return ERROR_OK;
} }
int mips32_arch_state(struct target *target) int mips32_arch_state(struct target *target)
@ -764,18 +763,56 @@ static int mips32_read_c0_prid(struct target *target)
return retval; 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. * NOTE: The proper detection of certain CPUs can become quite complicated.
* Please consult the following Linux kernel code when adding new CPUs: * Please consult the following Linux kernel code when adding new CPUs:
* arch/mips/include/asm/cpu.h * arch/mips/include/asm/cpu.h
* arch/mips/kernel/cpu-probe.c * arch/mips/kernel/cpu-probe.c
*
* @return ERROR_OK on success; error code on failure.
*/ */
int mips32_cpu_probe(struct target *target) int mips32_cpu_probe(struct target *target)
{ {
struct mips32_common *mips32 = target_to_mips32(target); struct mips32_common *mips32 = target_to_mips32(target);
const char *cpu_name = "unknown";
int retval; int retval;
if (mips32->prid) if (mips32->prid)
@ -785,11 +822,12 @@ int mips32_cpu_probe(struct target *target)
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
const struct cpu_entry *entry = mips32_find_cpu_by_prid(mips32->prid);
switch (mips32->prid & PRID_COMP_MASK) { switch (mips32->prid & PRID_COMP_MASK) {
case PRID_COMP_INGENIC_E1: case PRID_COMP_INGENIC_E1:
switch (mips32->prid & PRID_IMP_MASK) { switch (mips32->prid & PRID_IMP_MASK) {
case PRID_IMP_XBURST_REV1: case PRID_IMP_XBURST_REV1:
cpu_name = "Ingenic XBurst rev1";
mips32->cpu_quirks |= EJTAG_QUIRK_PAD_DRET; mips32->cpu_quirks |= EJTAG_QUIRK_PAD_DRET;
break; break;
default: default:
@ -800,13 +838,14 @@ int mips32_cpu_probe(struct target *target)
break; 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; return ERROR_OK;
} }
/* reads dsp implementation info from CP0 Config3 register {DSPP, DSPREV}*/ /* 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); uint32_t dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT);
if (dsp_present) { 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}*/ /* 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; int retval;
uint32_t fp_imp = (ejtag_info->config[1] & MIPS32_CONFIG1_FP_MASK) >> MIPS32_CONFIG1_FP_SHIFT; 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; 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)) { if (((ejtag_info->config[3] & MIPS32_CONFIG3_CDMM_MASK) != 0) && ((dcr & EJTAG_DCR_FDC) != 0)) {
mips32->fdc = 1; mips32->fdc = 1;
@ -1112,6 +1166,51 @@ static int mips32_verify_pointer(struct command_invocation *cmd,
return ERROR_OK; 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 * MIPS32 targets expose command interface
* to manipulate CP0 registers * to manipulate CP0 registers
@ -1172,6 +1271,207 @@ COMMAND_HANDLER(mips32_handle_cp0_command)
return ERROR_OK; 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) COMMAND_HANDLER(mips32_handle_scan_delay_command)
{ {
struct target *target = get_current_target(CMD_CTX); struct target *target = get_current_target(CMD_CTX);
@ -1203,6 +1503,13 @@ static const struct command_registration mips32_exec_command_handlers[] = {
.usage = "regnum select [value]", .usage = "regnum select [value]",
.help = "display/modify cp0 register", .help = "display/modify cp0 register",
}, },
{
.name = "cpuinfo",
.handler = mips32_handle_cpuinfo_command,
.mode = COMMAND_EXEC,
.help = "display CPU information",
.usage = "",
},
{ {
.name = "scan_delay", .name = "scan_delay",
.handler = mips32_handle_scan_delay_command, .handler = mips32_handle_scan_delay_command,

View File

@ -263,6 +263,96 @@ enum mips32_isa_rel {
MIPS32_RELEASE_UNKNOWN, 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 { enum mips32_fp_imp {
MIPS32_FP_IMP_NONE = 0, MIPS32_FP_IMP_NONE = 0,
MIPS32_FP_IMP_32 = 1, MIPS32_FP_IMP_32 = 1,
@ -306,7 +396,6 @@ struct mips32_common {
int fdc; int fdc;
int semihosting; int semihosting;
uint32_t cp0_mask;
/* FPU enabled (cp0.status.cu1) */ /* FPU enabled (cp0.status.cu1) */
bool fpu_enabled; bool fpu_enabled;
@ -315,6 +404,8 @@ struct mips32_common {
/* processor identification register */ /* processor identification register */
uint32_t prid; uint32_t prid;
/* detected CPU type */
const struct cpu_entry *cpu_info;
/* CPU specific quirks */ /* CPU specific quirks */
uint32_t cpu_quirks; uint32_t cpu_quirks;
@ -708,78 +799,6 @@ struct mips32_algorithm {
#define MIPS32_MMU_FIXED 3 #define MIPS32_MMU_FIXED 3
#define MIPS32_MMU_DUAL_VTLB_FTLB 4 #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[]; extern const struct command_registration mips32_command_handlers[];
int mips32_arch_state(struct target *target); int mips32_arch_state(struct target *target);

View File

@ -13,6 +13,11 @@
#define PRID_COMP_MASK 0xff0000 #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 #define PRID_COMP_INGENIC_E1 0xe10000
/* /*
@ -22,6 +27,12 @@
*/ */
#define PRID_IMP_MASK 0xff00 #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 */ #define PRID_IMP_XBURST_REV1 0x0200 /* XBurst®1 with MXU1.0/MXU1.1 SIMD ISA */
#endif /* OPENOCD_TARGET_MIPS_CPU_H */ #endif /* OPENOCD_TARGET_MIPS_CPU_H */