target/xtensa: reorganize register handling in translators

To support circular register dependencies in FLIX bundles opcode inputs
and outputs must be separate and adjustable. Circular dependencies can
be broken by making temporary copies of opcode inputs and substituting
them into the arguments array instead of the original registers.

E.g. the circular register dependency in the following bundle:

  { mov a2, a3 ; mov a3, a2 }

can be resolved by making copy a2' = a2 and substituting it as input
argument of the second opcode:

  { mov a2, a3 ; mov a3, a2' }

Change opcode translator prototype to accept OpcodeArg array as
argument. For each register argument initialize OpcodeArg::{in,out} with
TCGv_* of the respective register. Don't explicitly use cpu_R in the
opcode translators, use OpcodeArg::{in,out} instead.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
This commit is contained in:
Max Filippov 2019-02-11 18:53:19 -08:00
parent c949009bc0
commit b0b24bdcd9
3 changed files with 386 additions and 344 deletions

View File

@ -345,14 +345,21 @@ typedef struct XtensaMemory {
} location[MAX_NMEMORY];
} XtensaMemory;
typedef struct opcode_arg {
uint32_t imm;
uint32_t raw_imm;
void *in;
void *out;
} OpcodeArg;
typedef struct DisasContext DisasContext;
typedef void (*XtensaOpcodeOp)(DisasContext *dc, const uint32_t arg[],
typedef void (*XtensaOpcodeOp)(DisasContext *dc, const OpcodeArg arg[],
const uint32_t par[]);
typedef bool (*XtensaOpcodeBoolTest)(DisasContext *dc,
const uint32_t arg[],
const OpcodeArg arg[],
const uint32_t par[]);
typedef uint32_t (*XtensaOpcodeUintTest)(DisasContext *dc,
const uint32_t arg[],
const OpcodeArg arg[],
const uint32_t par[]);
enum {
@ -450,6 +457,7 @@ struct XtensaConfig {
XtensaOpcodeOps **opcode_ops;
const XtensaOpcodeTranslators **opcode_translators;
xtensa_regfile a_regfile;
void ***regfile;
uint32_t clock_freq_khz;
@ -578,6 +586,7 @@ void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
XTENSA_CPU_TYPE_NAME(XTENSA_DEFAULT_CPU_NOMMU_MODEL)
void xtensa_translate_init(void);
void **xtensa_get_regfile_by_name(const char *name);
void xtensa_breakpoint_handler(CPUState *cs);
void xtensa_register_core(XtensaConfigList *node);
void xtensa_sim_open_console(Chardev *chr);

View File

@ -91,11 +91,13 @@ static void init_libisa(XtensaConfig *config)
unsigned i, j;
unsigned opcodes;
unsigned formats;
unsigned regfiles;
config->isa = xtensa_isa_init(config->isa_internal, NULL, NULL);
assert(xtensa_isa_maxlength(config->isa) <= MAX_INSN_LENGTH);
opcodes = xtensa_isa_num_opcodes(config->isa);
formats = xtensa_isa_num_formats(config->isa);
regfiles = xtensa_isa_num_regfiles(config->isa);
config->opcode_ops = g_new(XtensaOpcodeOps *, opcodes);
for (i = 0; i < formats; ++i) {
@ -125,6 +127,19 @@ static void init_libisa(XtensaConfig *config)
config->opcode_ops[i] = ops;
}
config->a_regfile = xtensa_regfile_lookup(config->isa, "AR");
config->regfile = g_new(void **, regfiles);
for (i = 0; i < regfiles; ++i) {
const char *name = xtensa_regfile_name(config->isa, i);
config->regfile[i] = xtensa_get_regfile_by_name(name);
#ifdef DEBUG
if (config->regfile[i] == NULL) {
fprintf(stderr, "regfile '%s' not found for %s\n",
name, config->name);
}
#endif
}
}
static void xtensa_finalize_config(XtensaConfig *config)

File diff suppressed because it is too large Load Diff