return s->cpu->intevt;
case SH7750_CCR_A7:
return s->ccr;
- case 0x1f000030: /* Processor version PVR */
- return 0x00050000; /* SH7750R */
- case 0x1f000040: /* Processor version CVR */
- return 0x00110000; /* Minimum caches */
- case 0x1f000044: /* Processor version PRR */
- return 0x00000100; /* SH7750R */
+ case 0x1f000030: /* Processor version */
+ return s->cpu->pvr;
+ case 0x1f000040: /* Cache version */
+ return s->cpu->cvr;
+ case 0x1f000044: /* Processor revision */
+ return s->cpu->prr;
default:
error_access("long read", addr);
assert(0);
PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3),
};
-#define SH_CPU_SH7750 (1 << 0)
-#define SH_CPU_SH7750S (1 << 1)
-#define SH_CPU_SH7750R (1 << 2)
-#define SH_CPU_SH7751 (1 << 3)
-#define SH_CPU_SH7751R (1 << 4)
-#define SH_CPU_SH7750_ALL (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7750R)
-#define SH_CPU_SH7751_ALL (SH_CPU_SH7751 | SH_CPU_SH7751R)
-
/**********************************************************************
Memory mapped cache and TLB
**********************************************************************/
SH7750State *s;
int sh7750_io_memory;
int sh7750_mm_cache_and_tlb; /* memory mapped cache and tlb */
- int cpu_model = SH_CPU_SH7751R; /* for now */
s = qemu_mallocz(sizeof(SH7750State));
s->cpu = cpu;
_INTC_ARRAY(mask_registers),
_INTC_ARRAY(prio_registers));
- sh_intc_register_sources(&s->intc,
+ sh_intc_register_sources(&s->intc,
_INTC_ARRAY(vectors),
_INTC_ARRAY(groups));
sh_intc_source(&s->intc, TMU2_TUNI),
sh_intc_source(&s->intc, TMU2_TICPI));
- if (cpu_model & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
- sh_intc_register_sources(&s->intc,
+ if (cpu->id & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) {
+ sh_intc_register_sources(&s->intc,
_INTC_ARRAY(vectors_dma4),
_INTC_ARRAY(groups_dma4));
}
- if (cpu_model & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
- sh_intc_register_sources(&s->intc,
+ if (cpu->id & (SH_CPU_SH7750R | SH_CPU_SH7751R)) {
+ sh_intc_register_sources(&s->intc,
_INTC_ARRAY(vectors_dma8),
_INTC_ARRAY(groups_dma8));
}
- if (cpu_model & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
- sh_intc_register_sources(&s->intc,
+ if (cpu->id & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) {
+ sh_intc_register_sources(&s->intc,
_INTC_ARRAY(vectors_tmu34),
NULL, 0);
tmu012_init(0x1e100000, 0, s->periph_freq,
NULL, NULL);
}
- if (cpu_model & (SH_CPU_SH7751_ALL)) {
- sh_intc_register_sources(&s->intc,
+ if (cpu->id & (SH_CPU_SH7751_ALL)) {
+ sh_intc_register_sources(&s->intc,
_INTC_ARRAY(vectors_pci),
_INTC_ARRAY(groups_pci));
}
- if (cpu_model & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
- sh_intc_register_sources(&s->intc,
+ if (cpu->id & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) {
+ sh_intc_register_sources(&s->intc,
_INTC_ARRAY(vectors_irlm),
NULL, 0);
}
#define ELF_MACHINE EM_SH
+/* CPU Subtypes */
+#define SH_CPU_SH7750 (1 << 0)
+#define SH_CPU_SH7750S (1 << 1)
+#define SH_CPU_SH7750R (1 << 2)
+#define SH_CPU_SH7751 (1 << 3)
+#define SH_CPU_SH7751R (1 << 4)
+#define SH_CPU_SH7750_ALL (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7750R)
+#define SH_CPU_SH7751_ALL (SH_CPU_SH7751 | SH_CPU_SH7751R)
+
#include "cpu-defs.h"
#include "softfloat.h"
#define NB_MMU_MODES 2
typedef struct CPUSH4State {
+ int id; /* CPU model */
+
uint32_t flags; /* general execution flags */
uint32_t gregs[24]; /* general registers */
float32 fregs[32]; /* floating point registers */
uint32_t expevt; /* exception event register */
uint32_t intevt; /* interrupt event register */
+ uint32_t pvr; /* Processor Version Register */
+ uint32_t prr; /* Processor Revision Register */
+ uint32_t cvr; /* Cache Version Register */
+
CPU_COMMON tlb_t utlb[UTLB_SIZE]; /* unified translation table */
tlb_t itlb[ITLB_SIZE]; /* instruction translation table */
void *intc_handle;
int cpu_sh4_exec(CPUSH4State * s);
int cpu_sh4_signal_handler(int host_signum, void *pinfo,
void *puc);
+void sh4_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
uint32_t mem_value);
#define cpu_exec cpu_sh4_exec
#define cpu_gen_code cpu_sh4_gen_code
#define cpu_signal_handler cpu_sh4_signal_handler
+#define cpu_list sh4_cpu_list
/* MMU modes definitions */
#define MMU_MODE0_SUFFIX _kernel
env->mmucr = 0;
}
+typedef struct {
+ const unsigned char *name;
+ int id;
+ uint32_t pvr;
+ uint32_t prr;
+ uint32_t cvr;
+} sh4_def_t;
+
+static sh4_def_t sh4_defs[] = {
+ {
+ .name = "SH7750R",
+ .id = SH_CPU_SH7750R,
+ .pvr = 0x00050000,
+ .prr = 0x00000100,
+ .cvr = 0x00110000,
+ }, {
+ .name = "SH7751R",
+ .id = SH_CPU_SH7751R,
+ .pvr = 0x04050005,
+ .prr = 0x00000113,
+ .cvr = 0x00110000, /* Neutered caches, should be 0x20480000 */
+ },
+};
+
+static const sh4_def_t *cpu_sh4_find_by_name(const unsigned char *name)
+{
+ int i;
+
+ if (strcasecmp(name, "any") == 0)
+ return &sh4_defs[0];
+
+ for (i = 0; i < sizeof(sh4_defs) / sizeof(*sh4_defs); i++)
+ if (strcasecmp(name, sh4_defs[i].name) == 0)
+ return &sh4_defs[i];
+
+ return NULL;
+}
+
+void sh4_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
+{
+ int i;
+
+ for (i = 0; i < sizeof(sh4_defs) / sizeof(*sh4_defs); i++)
+ (*cpu_fprintf)(f, "%s\n", sh4_defs[i].name);
+}
+
+static int cpu_sh4_register(CPUSH4State *env, const sh4_def_t *def)
+{
+ env->pvr = def->pvr;
+ env->prr = def->prr;
+ env->cvr = def->cvr;
+ env->id = def->id;
+}
+
CPUSH4State *cpu_sh4_init(const char *cpu_model)
{
CPUSH4State *env;
+ const sh4_def_t *def;
+ def = cpu_sh4_find_by_name(cpu_model);
+ if (!def)
+ return NULL;
env = qemu_mallocz(sizeof(CPUSH4State));
if (!env)
return NULL;
cpu_exec_init(env);
sh4_translate_init();
cpu_sh4_reset(env);
+ cpu_sh4_register(env, def);
tlb_flush(env, 1);
return env;
}