e2k: implement detecting ISA version by ELF flags, throw an error for protected mode and x86 recompiled binaries for now

This commit is contained in:
Alibek Omarov 2021-01-24 06:12:54 +03:00
parent 8c3fd2ef2d
commit 3a3878c337
4 changed files with 76 additions and 20 deletions

View File

@ -21,6 +21,7 @@
#include "qemu-common.h"
#include "qemu.h"
#include "cpu_loop-common.h"
#include "target_elf.h"
void helper_return(CPUE2KState *env);
@ -118,15 +119,50 @@ void cpu_loop(CPUE2KState *env)
void target_cpu_copy_regs(CPUE2KState *env, struct target_pt_regs *regs)
{
CPUState *cpu = env_cpu(env);
TaskState *ts = cpu->opaque;
struct image_info *info = ts->info;
uint32_t eflags = info->elf_flags;
env->ip = regs->ip;
env->pcsp = regs->pcsp;
env->psp = regs->psp;
env->usd.lo = regs->usd_lo;
env->usd.hi = regs->usd_hi;
env->sbr = regs->sbr;
env->elf_flags = info->elf_flags;
if (eflags & E2K_ELF_PM) {
fprintf(stderr, "Protected mode is unsupported\n");
exit(EXIT_FAILURE);
}
if (eflags & E2K_ELF_X86APP) {
fprintf(stderr, "x86 recompiler is unsupported\n");
exit(EXIT_FAILURE);
}
e2k_break_save_state(env);
env->pcs_base = env->pcsp.base;
env->ps_base = env->psp.base;
}
const char *cpu_get_model(uint32_t eflags)
{
const char *name = "any";
uint32_t machine = E2K_ELF_MACH(eflags);
/* TODO: can't check for EM_E2K_OLD flags because e_machine isn't saved anywhere... */
switch(machine) {
case E2K_MACH_EV2: name = "e2c+"; break;
case E2K_MACH_EV3: name = "e2s"; break;
case E2K_MACH_1CPLUS:
case E2K_MACH_8C:
case E2K_MACH_EV4: name = "e8c"; break;
case E2K_MACH_EV5: name = "e8c2"; break;
case E2K_MACH_EV6: name = "e16c"; break;
}
return name;
}

View File

@ -1,7 +1,27 @@
#ifndef E2K_TARGET_ELF_H
#define E2K_TARGET_ELF_H
static inline const char *cpu_get_model(uint32_t eflags)
{
return "any";
}
#define E2K_ELF_IPD_MASK ((1U << 1)|(1U << 0))
#define E2K_ELF_X86APP (1U << 2)
#define E2K_ELF_4MB_PAGES (1U << 3)
#define E2K_ELF_INCOMPAT (1U << 4)
#define E2K_ELF_PM (1U << 5)
#define E2K_ELF_OLD_MACH(x) (((x) >> 28) & 7)
#define E2K_ELF_MACH(x) (((x) >> 24) & 255)
#define E2K_MACH_BASE 0
#define E2K_MACH_EV1 1
#define E2K_MACH_EV2 2
#define E2K_MACH_EV3 3
#define E2K_MACH_EV4 4
#define E2K_MACH_EV5 5
#define E2K_MACH_EV6 6
/* elbrus-v4 based processors */
#define E2K_MACH_8C 19
#define E2K_MACH_1CPLUS 20
const char *cpu_get_model(uint32_t eflags);
#endif /* E2K_TARGET_ELF_H */

View File

@ -96,37 +96,35 @@ void cpu_e2k_set_id(CPUE2KState *env, unsigned int cpu)
#define DEFAULT_CPU_MODEL "e8c"
static const struct e2k_def_t e2k_defs[] = {
{
.name = "e8c", // default choice
.canonical_name = "MCST Elbrus 8C",
.gdb_arch = "elbrus-8c",
.isa_version = 4,
},
{
.name = "e2c+", // however it may work better
.name = "e2c+", /* however it may work better */
.canonical_name = "MCST Elbrus 2C+ (Monocube)",
.gdb_arch = "elbrus-v2",
.isa_version = 2,
},
{
.name = "e8c2",
.canonical_name = "MCST Elbrus 8CB",
.gdb_arch = "elbrus-v5",
.isa_version = 5,
},
#if 0 /* for reference, never tested */
{
.name = "e2s",
.canonical_name = "MCST Elbrus 4C",
.gdb_arch = "elbrus-v3",
.isa_version = 3,
},
{
.name = "e8c", /* default choice for system */
.canonical_name = "MCST Elbrus 8C",
.gdb_arch = "elbrus-8c",
.isa_version = 4,
},
{
.name = "e8c2",
.canonical_name = "MCST Elbrus 8CB",
.gdb_arch = "elbrus-v5",
.isa_version = 5,
},
{
.name = "e16c",
.canonical_name = "MCST Elbrus 16C",
.gdb_arch = "elbrus-v6",
.isa_version = 6,
},
#endif
};
static inline void cpu_dump_state_br(CPUE2KState *env, FILE *f, int flags)
@ -217,7 +215,7 @@ static ObjectClass *e2k_cpu_class_by_name(const char *cpu_model)
if (!strcasecmp(cpu_model, "any")) {
cpu_model = DEFAULT_CPU_MODEL;
}
#endif // CONFIG_USER_ONLY
#endif
typename = e2k_cpu_type_name(cpu_model);
oc = object_class_by_name(typename);

View File

@ -665,6 +665,8 @@ typedef struct {
uint32_t version;
struct e2k_def_t def;
uint32_t elf_flags;
} CPUE2KState;
/**