More model specific changes
This commit is contained in:
parent
1b09c02b17
commit
80948f392b
@ -1,15 +1,38 @@
|
||||
Wed Nov 15 17:32:13 1995 Michael Meissner <meissner@tiktok.cygnus.com>
|
||||
|
||||
* cpu.h (cpu_model): Add declaration.
|
||||
|
||||
* cpu.c (struct _cpu): Add model_ptr to hold model specific
|
||||
information.
|
||||
(cpu_model): Return the model internal pointer.
|
||||
(cpu_{create,init,halt}): Call the appropriate model function.
|
||||
|
||||
* inline.c (mon.c): Move include of mon.c after model.c.
|
||||
|
||||
* mon.c (_cpu_mon): Add fields to count unaligned memory
|
||||
references.
|
||||
(mon_issue): Call model_issue, not function_unit_issue.
|
||||
(mon_{read,write}): Count # of unaligned memory accesses.
|
||||
(mon_print_info): Switch to calling model_mon_info and
|
||||
model_mon_info_free instead of function_unit version. Print out
|
||||
number of unaligned reads/writes.
|
||||
|
||||
* {ppc-instructions,igen.c}: More global changes to add model
|
||||
specific features.
|
||||
|
||||
Tue Nov 14 04:47:25 1995 Michael Meissner <meissner@tiktok.cygnus.com>
|
||||
|
||||
* Makefile.in (devices.o, main.o): Update dependency.
|
||||
|
||||
* igen.c (gen_model_h): Use correct variable in loop.
|
||||
(gen_model_c): Use strcmp, strcasecmp.
|
||||
(gen_model_{c,h}): Use STATIC_MODEL for arrays.
|
||||
(gen_model_c): Use EXTERN_MODEL for arrays.
|
||||
(gen_model_h): Use STATIC_MODEL for arrays.
|
||||
(lf_print_c_semantic_function_header): Delete unused function.
|
||||
|
||||
* main.c (cpu.h): Include cpu.h to get model.h.
|
||||
|
||||
* inline.h (STATIC_MODEL): Define.
|
||||
* inline.h ({EXTERN,STATIC}_MODEL): Define.
|
||||
|
||||
Mon Nov 13 09:14:13 1995 Michael Meissner <meissner@tiktok.cygnus.com>
|
||||
|
||||
|
@ -62,6 +62,12 @@ struct _cpu {
|
||||
event_queue *events;
|
||||
int cpu_nr;
|
||||
|
||||
/* Current functional unit information */
|
||||
function_unit *func_unit;
|
||||
|
||||
/* Current CPU model information */
|
||||
model_data *model_ptr;
|
||||
|
||||
#if WITH_IDECODE_CACHE_SIZE
|
||||
/* a cache to store cracked instructions */
|
||||
idecode_cache icache[WITH_IDECODE_CACHE_SIZE];
|
||||
@ -93,6 +99,7 @@ cpu_create(psim *system,
|
||||
processor->virtual = vm_create(memory);
|
||||
processor->instruction_map = vm_create_instruction_map(processor->virtual);
|
||||
processor->data_map = vm_create_data_map(processor->virtual);
|
||||
processor->model_ptr = model_create (processor);
|
||||
|
||||
/* link back to core system */
|
||||
processor->system = system;
|
||||
@ -100,6 +107,10 @@ cpu_create(psim *system,
|
||||
processor->cpu_nr = cpu_nr;
|
||||
processor->monitor = monitor;
|
||||
|
||||
/* Create function unit if desired */
|
||||
if (WITH_FUNCTION_UNIT)
|
||||
processor->func_unit = function_unit_create ();
|
||||
|
||||
return processor;
|
||||
}
|
||||
|
||||
@ -107,8 +118,13 @@ cpu_create(psim *system,
|
||||
INLINE_CPU void
|
||||
cpu_init(cpu *processor)
|
||||
{
|
||||
bzero(&processor->regs, sizeof(processor->regs));
|
||||
memset(&processor->regs, 0, sizeof(processor->regs));
|
||||
/* FIXME - should any of VM be inited also ? */
|
||||
|
||||
if (WITH_FUNCTION_UNIT)
|
||||
function_unit_init (processor->func_unit);
|
||||
|
||||
model_init (processor, processor->model_ptr);
|
||||
}
|
||||
|
||||
|
||||
@ -138,13 +154,25 @@ cpu_monitor(cpu *processor)
|
||||
return processor->monitor;
|
||||
}
|
||||
|
||||
INLINE_CPU function_unit *
|
||||
cpu_function_unit(cpu *processor)
|
||||
{
|
||||
return processor->func_unit;
|
||||
}
|
||||
|
||||
INLINE_CPU model_data *
|
||||
cpu_model(cpu *processor)
|
||||
{
|
||||
return processor->model_ptr;
|
||||
}
|
||||
|
||||
/* The processors local concept of time */
|
||||
|
||||
INLINE_CPU signed64
|
||||
cpu_get_time_base(cpu *processor)
|
||||
{
|
||||
return (event_queue_time(processor->events)
|
||||
+ processor->time_base_local_time);
|
||||
- processor->time_base_local_time);
|
||||
}
|
||||
|
||||
INLINE_CPU void
|
||||
@ -235,6 +263,10 @@ cpu_halt(cpu *processor,
|
||||
signal);
|
||||
}
|
||||
else {
|
||||
if (WITH_FUNCTION_UNIT)
|
||||
function_unit_halt(processor, processor->func_unit);
|
||||
|
||||
model_halt(processor, processor->model_ptr);
|
||||
processor->program_counter = cia;
|
||||
psim_halt(processor->system, processor->cpu_nr, cia, reason, signal);
|
||||
}
|
||||
@ -302,12 +334,6 @@ cpu_synchronize_context(cpu *processor)
|
||||
cpu_flush_icache(processor);
|
||||
#endif
|
||||
|
||||
/* don't allow the processor to change endian modes */
|
||||
if ((cpu_registers(processor)->msr & msr_little_endian_mode)
|
||||
&& CURRENT_TARGET_BYTE_ORDER != LITTLE_ENDIAN) {
|
||||
error("vm_synchronize_context() - unsuported change of byte order\n");
|
||||
}
|
||||
|
||||
/* update virtual memory */
|
||||
vm_synchronize_context(processor->virtual,
|
||||
processor->regs.spr,
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "icache.h"
|
||||
#include "itable.h"
|
||||
#include "mon.h"
|
||||
#include "model.h"
|
||||
#include "function_unit.h"
|
||||
|
||||
|
||||
@ -180,6 +181,9 @@ INLINE_CPU void cpu_synchronize_context
|
||||
INLINE_CPU function_unit *cpu_function_unit
|
||||
(cpu *processor);
|
||||
|
||||
INLINE_CPU model_data *cpu_model
|
||||
(cpu *processor);
|
||||
|
||||
#define IS_PROBLEM_STATE(PROCESSOR) \
|
||||
(CURRENT_ENVIRONMENT == OPERATING_ENVIRONMENT \
|
||||
? (cpu_registers(PROCESSOR)->msr & msr_problem_state) \
|
||||
|
410
sim/ppc/igen.c
410
sim/ppc/igen.c
@ -578,10 +578,9 @@ typedef enum {
|
||||
} function_table_fields;
|
||||
|
||||
typedef enum {
|
||||
model_default = insn_form,
|
||||
model_name = insn_mnemonic,
|
||||
model_identifer = insn_name,
|
||||
model_func = insn_comment,
|
||||
model_default = insn_comment,
|
||||
} model_table_fields;
|
||||
|
||||
typedef struct _insn insn;
|
||||
@ -591,22 +590,14 @@ struct _insn {
|
||||
insn *next;
|
||||
};
|
||||
|
||||
typedef struct _model_func_unit model_func_unit;
|
||||
struct _model_func_unit {
|
||||
model_func_unit *next;
|
||||
char *name;
|
||||
char *comment;
|
||||
int number;
|
||||
unsigned mask;
|
||||
};
|
||||
|
||||
typedef struct _model model;
|
||||
struct _model {
|
||||
model *next;
|
||||
char *name;
|
||||
char *printable_name;
|
||||
model_func_unit *func_unit_start;
|
||||
model_func_unit *func_unit_end;
|
||||
char *insn_default;
|
||||
table_model_entry *func_unit_start;
|
||||
table_model_entry *func_unit_end;
|
||||
};
|
||||
|
||||
typedef struct _insn_table insn_table;
|
||||
@ -617,8 +608,6 @@ struct _insn_table {
|
||||
insn *insns;
|
||||
insn *functions;
|
||||
insn *last_function;
|
||||
int max_func_unit_name_len;
|
||||
unsigned max_func_unit_mask;
|
||||
opcode_rules *opcode_rule;
|
||||
opcode_field *opcode;
|
||||
int nr_entries;
|
||||
@ -629,10 +618,7 @@ struct _insn_table {
|
||||
|
||||
typedef enum {
|
||||
insn_model_name,
|
||||
insn_model_unit,
|
||||
insn_model_issue,
|
||||
insn_model_done,
|
||||
insn_model_flags,
|
||||
insn_model_fields,
|
||||
nr_insn_model_table_fields
|
||||
} insn_model_table_fields;
|
||||
|
||||
@ -688,11 +674,11 @@ insn_table_insert_insn(insn_table *table,
|
||||
char *name = insn_model_ptr->fields[insn_model_name];
|
||||
|
||||
for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
if (strcmp(name, model_ptr->name) == 0) {
|
||||
if (strcmp(name, model_ptr->printable_name) == 0) {
|
||||
|
||||
/* Replace the name field with that of the global model, so that when we
|
||||
want to print it out, we can just compare pointers. */
|
||||
insn_model_ptr->fields[insn_model_name] = model_ptr->name;
|
||||
insn_model_ptr->fields[insn_model_name] = model_ptr->printable_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -972,17 +958,10 @@ model_table_insert(insn_table *table,
|
||||
{
|
||||
/* create a new model */
|
||||
model *new_model = ZALLOC(model);
|
||||
model_func_unit *func_unit;
|
||||
char *ptr, *end, *end_name, *comment, *name;
|
||||
int ch;
|
||||
int name_len;
|
||||
int func_name_len;
|
||||
unsigned unit, mask;
|
||||
int number;
|
||||
|
||||
new_model->name = file_entry->fields[model_identifer];
|
||||
new_model->printable_name = file_entry->fields[model_name];
|
||||
name_len = strlen(new_model->name);
|
||||
new_model->insn_default = file_entry->fields[model_default];
|
||||
|
||||
/* append it to the end of the model list */
|
||||
if (last_model)
|
||||
@ -990,105 +969,6 @@ model_table_insert(insn_table *table,
|
||||
else
|
||||
models = new_model;
|
||||
last_model = new_model;
|
||||
|
||||
/* Parse the function units separated by commas */
|
||||
unit = 1;
|
||||
for (ptr = file_entry->fields[model_func];
|
||||
((ch = *ptr) != '\0') && (ch != '\n');
|
||||
ptr = (*end == ',') ? end+1 : end) {
|
||||
|
||||
while (ch == ' ' || ch == '\t')
|
||||
ch = *++ptr;
|
||||
|
||||
if (!ch || ch == '\n')
|
||||
break;
|
||||
|
||||
/* Search for comma or newline ending field */
|
||||
end = ptr;
|
||||
end_name = (char *)0;
|
||||
|
||||
if (ch == ',')
|
||||
continue;
|
||||
|
||||
while (ch != '\0' && ch != ',' && ch != '\n') {
|
||||
if (end_name == (char *)0 && (ch == '=' || isspace(ch)))
|
||||
end_name = end;
|
||||
|
||||
ch = *++end;
|
||||
}
|
||||
if (!end_name)
|
||||
end_name = end;
|
||||
|
||||
func_unit = ZALLOC(model_func_unit);
|
||||
if (new_model->func_unit_end)
|
||||
new_model->func_unit_end->next = func_unit;
|
||||
else
|
||||
new_model->func_unit_start = func_unit;
|
||||
|
||||
new_model->func_unit_end = func_unit;
|
||||
|
||||
/* Record function unit name as model name _ unit name */
|
||||
func_name_len = name_len + end_name - ptr + 2;
|
||||
if (table->max_func_unit_name_len < func_name_len)
|
||||
table->max_func_unit_name_len = func_name_len;
|
||||
|
||||
func_unit->name = name = (char *)zalloc(func_name_len);
|
||||
memcpy(name, new_model->name, name_len);
|
||||
name[name_len] = '_';
|
||||
memcpy(name + name_len + 1, ptr, end_name - ptr);
|
||||
|
||||
/* See if there are multiple functional units */
|
||||
if (*end_name == '=') {
|
||||
number = 0;
|
||||
for(end_name++; end_name < end && isdigit(*end_name); end_name++)
|
||||
number = number * 10 + (*end_name - '0');
|
||||
} else {
|
||||
number = 1;
|
||||
}
|
||||
|
||||
/* Now figure out the mask for these unit(s) */
|
||||
func_unit->number = number;
|
||||
mask = 0;
|
||||
while (number--) {
|
||||
ASSERT(unit != 0);
|
||||
mask |= unit;
|
||||
unit <<= 1;
|
||||
}
|
||||
func_unit->mask = mask;
|
||||
table->max_func_unit_mask |= mask;
|
||||
|
||||
/* Now figure out comments */
|
||||
for (comment = end_name; comment < end && ((ch = *comment) == ' ' || ch == '\t'); comment++)
|
||||
;
|
||||
|
||||
if (comment < end) {
|
||||
func_unit->comment = (char *)zalloc(end - comment + 1);
|
||||
memcpy(func_unit->comment, comment, end - comment);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add an 'sentinel' function unit at the end to simpify the loop */
|
||||
func_unit = ZALLOC(model_func_unit);
|
||||
if (new_model->func_unit_end)
|
||||
new_model->func_unit_end->next = func_unit;
|
||||
else
|
||||
new_model->func_unit_start = func_unit;
|
||||
|
||||
new_model->func_unit_end = func_unit;
|
||||
|
||||
/* Record function unit name as model name _ unit name */
|
||||
func_name_len = name_len + sizeof("_SENTINEL");
|
||||
if (table->max_func_unit_name_len < func_name_len)
|
||||
table->max_func_unit_name_len = func_name_len;
|
||||
|
||||
func_unit->name = name = (char *)zalloc(func_name_len);
|
||||
func_unit->number = 0;
|
||||
func_unit->mask = unit;
|
||||
func_unit->comment = "dummy";
|
||||
table->max_func_unit_mask |= unit;
|
||||
|
||||
memcpy(name, new_model->name, name_len);
|
||||
strcpy(name + name_len, "_SENTINEL");
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3058,9 +2938,14 @@ gen_model_h(insn_table *table, lf *file)
|
||||
{
|
||||
insn *insn_ptr;
|
||||
model *model_ptr;
|
||||
model_func_unit *func_unit_ptr;
|
||||
insn *macro;
|
||||
int hex_size;
|
||||
char *name;
|
||||
int model_create_p = 0;
|
||||
int model_init_p = 0;
|
||||
int model_halt_p = 0;
|
||||
int model_issue_p = 0;
|
||||
int model_mon_info_p = 0;
|
||||
int model_mon_info_free_p = 0;
|
||||
|
||||
lf_print_copyleft(file);
|
||||
lf_printf(file, "\n");
|
||||
@ -3088,43 +2973,6 @@ gen_model_h(insn_table *table, lf *file)
|
||||
lf_printf(file, "#endif\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
if (table->max_func_unit_mask > 0xffff) {
|
||||
hex_size = 8;
|
||||
lf_printf(file, "#ifndef MODEL_UNITS\n");
|
||||
lf_printf(file, "#define MODEL_UNITS unsigned32\n");
|
||||
lf_printf(file, "#endif\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_printf(file, "#ifndef MODEL_CYCLES\n");
|
||||
lf_printf(file, "#define MODEL_CYCLES unsigned16\n");
|
||||
lf_printf(file, "#endif\n");
|
||||
lf_printf(file, "\n");
|
||||
} else {
|
||||
hex_size = 4;
|
||||
lf_printf(file, "#ifndef MODEL_UNITS\n");
|
||||
lf_printf(file, "#define MODEL_UNITS unsigned16\n");
|
||||
lf_printf(file, "#endif\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_printf(file, "#ifndef MODEL_CYCLES\n");
|
||||
lf_printf(file, "#define MODEL_CYCLES unsigned8\n");
|
||||
lf_printf(file, "#endif\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
lf_printf(file, "#ifndef MODEL_FLAGS\n");
|
||||
lf_printf(file, "#define MODEL_FLAGS unsigned32\n");
|
||||
lf_printf(file, "#endif\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_printf(file, "typedef struct _model_time {\t/* Instruction cycle time */\n");
|
||||
lf_printf(file, " MODEL_UNITS units;\n");
|
||||
lf_printf(file, " MODEL_CYCLES initial;\n");
|
||||
lf_printf(file, " MODEL_CYCLES finish;\n");
|
||||
lf_printf(file, " MODEL_FLAGS flags;\n");
|
||||
lf_printf(file, "} model_time;\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_printf(file, "typedef enum _model_enum {\n");
|
||||
lf_printf(file, " MODEL_NONE,\n");
|
||||
for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
@ -3137,35 +2985,76 @@ gen_model_h(insn_table *table, lf *file)
|
||||
lf_printf(file, "#define DEFAULT_MODEL MODEL_%s\n", (models) ? models->name : "NONE");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
for (func_unit_ptr = model_ptr->func_unit_start; func_unit_ptr; func_unit_ptr = func_unit_ptr->next) {
|
||||
if (func_unit_ptr->comment) {
|
||||
lf_printf(file, "#define %-*s 0x%.*x /* %s functional unit */\n",
|
||||
table->max_func_unit_name_len, func_unit_ptr->name,
|
||||
hex_size, func_unit_ptr->mask,
|
||||
func_unit_ptr->comment);
|
||||
} else {
|
||||
lf_printf(file, "#define %-*s 0x%.*x\n",
|
||||
table->max_func_unit_name_len, func_unit_ptr->name,
|
||||
hex_size, func_unit_ptr->mask);
|
||||
}
|
||||
}
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
lf_printf(file, "typedef struct _model_data model_data;\n");
|
||||
lf_printf(file, "typedef struct _model_time model_time;\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_printf(file, "EXTERN_MODEL model_enum current_model;\n");
|
||||
lf_printf(file, "extern model_enum current_model;\n");
|
||||
lf_printf(file, "EXTERN_MODEL const char *model_name[ (int)nr_models ];\n");
|
||||
lf_printf(file, "EXTERN_MODEL const char *const *const model_func_unit_name[ (int)nr_models ];\n");
|
||||
lf_printf(file, "EXTERN_MODEL const model_time *const model_time_mapping[ (int)nr_models ];\n");
|
||||
lf_printf(file, "\n");
|
||||
lf_printf(file, "INLINE_MODEL void model_set\n");
|
||||
lf_printf(file, "(const char *name);\n");
|
||||
|
||||
for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
|
||||
model_c_or_h_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
|
||||
name = insn_ptr->file_entry->fields[function_name];
|
||||
if (strcmp (name, "model_create") == 0)
|
||||
model_create_p = 1;
|
||||
else if (strcmp (name, "model_init") == 0)
|
||||
model_init_p = 1;
|
||||
else if (strcmp (name, "model_halt") == 0)
|
||||
model_halt_p = 1;
|
||||
else if (strcmp (name, "model_issue") == 0)
|
||||
model_issue_p = 1;
|
||||
else if (strcmp (name, "model_mon_info") == 0)
|
||||
model_mon_info_p = 1;
|
||||
else if (strcmp (name, "model_mon_info_free") == 0)
|
||||
model_mon_info_free_p = 1;
|
||||
}
|
||||
|
||||
if (!model_create_p) {
|
||||
lf_printf(file, "INLINE_MODEL model_data *model_create\n");
|
||||
lf_printf(file, "(cpu *processor);\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_init_p) {
|
||||
lf_printf(file, "INLINE_MODEL void model_init\n");
|
||||
lf_printf(file, "(cpu *processor,\n");
|
||||
lf_printf(file, " model_data *model_ptr);\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_halt_p) {
|
||||
lf_printf(file, "INLINE_MODEL void model_halt\n");
|
||||
lf_printf(file, "(cpu *processor,\n");
|
||||
lf_printf(file, " model_data *model_ptr);\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_issue_p) {
|
||||
lf_printf(file, "INLINE_MODEL void model_issue\n");
|
||||
lf_printf(file, "(itable_index index,\n");
|
||||
lf_printf(file, " model_data *model_ptr,\n");
|
||||
lf_printf(file, " unsigned_word cia);\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_mon_info_p) {
|
||||
lf_printf(file, "INLINE_MODEL model_print *model_mon_info\n");
|
||||
lf_printf(file, "(model_data *model_ptr);\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_mon_info_free_p) {
|
||||
lf_printf(file, "INLINE_MODEL void model_mon_info_free\n");
|
||||
lf_printf(file, "(model_data *model_ptr,\n");
|
||||
lf_printf(file, " model_print *info_ptr);\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
lf_printf(file, "INLINE_MODEL void model_set\n");
|
||||
lf_printf(file, "(const char *name);\n");
|
||||
lf_printf(file, "\n");
|
||||
lf_printf(file, "#endif /* _MODEL_H_ */\n");
|
||||
}
|
||||
@ -3185,24 +3074,23 @@ model_c_insn(insn_table *entry,
|
||||
{
|
||||
model_c_passed_data *data_ptr = (model_c_passed_data *)data;
|
||||
lf *file = data_ptr->file;
|
||||
char *current_name = data_ptr->model_ptr->name;
|
||||
char *current_name = data_ptr->model_ptr->printable_name;
|
||||
table_model_entry *model_ptr = instruction->file_entry->model_first;
|
||||
int i;
|
||||
|
||||
while (model_ptr) {
|
||||
if (model_ptr->fields[insn_model_name] == current_name) {
|
||||
lf_printf(file, " {");
|
||||
for(i = insn_model_unit; i < nr_insn_model_table_fields; i++) {
|
||||
lf_printf(file, " %s,", model_ptr->fields[i]);
|
||||
}
|
||||
lf_printf(file, " }, /* %s */\n", instruction->file_entry->fields[insn_name]);
|
||||
lf_printf(file, " { %-48s },\t/* %s */\n",
|
||||
model_ptr->fields[insn_model_fields],
|
||||
instruction->file_entry->fields[insn_name]);
|
||||
return;
|
||||
}
|
||||
|
||||
model_ptr = model_ptr->next;
|
||||
}
|
||||
|
||||
lf_printf(file, " { %s_SENTINEL },\n", current_name);
|
||||
lf_printf(file, " { %-48s },\t/* %s */\n",
|
||||
data_ptr->model_ptr->insn_default,
|
||||
instruction->file_entry->fields[insn_name]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3240,8 +3128,13 @@ gen_model_c(insn_table *table, lf *file)
|
||||
{
|
||||
insn *insn_ptr;
|
||||
model *model_ptr;
|
||||
model_func_unit *func_unit_ptr;
|
||||
int i;
|
||||
char *name;
|
||||
int model_create_p = 0;
|
||||
int model_init_p = 0;
|
||||
int model_halt_p = 0;
|
||||
int model_issue_p = 0;
|
||||
int model_mon_info_p = 0;
|
||||
int model_mon_info_free_p = 0;
|
||||
|
||||
lf_print_copyleft(file);
|
||||
lf_printf(file, "\n");
|
||||
@ -3249,6 +3142,11 @@ gen_model_c(insn_table *table, lf *file)
|
||||
lf_printf(file, "#define _MODEL_C_\n");
|
||||
lf_printf(file, "\n");
|
||||
lf_printf(file, "#include \"cpu.h\"\n");
|
||||
lf_printf(file, "#include \"mon.h\"\n");
|
||||
lf_printf(file, "\n");
|
||||
lf_printf(file, "#ifdef HAVE_STDLIB_H\n");
|
||||
lf_printf(file, "#include <stdlib.h>\n");
|
||||
lf_printf(file, "#endif\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
for(insn_ptr = model_data; insn_ptr; insn_ptr = insn_ptr->next) {
|
||||
@ -3259,56 +3157,6 @@ gen_model_c(insn_table *table, lf *file)
|
||||
model_c_or_h_function(table, file, insn_ptr->file_entry, "STATIC_INLINE_MODEL");
|
||||
}
|
||||
|
||||
lf_printf(file, "/* map model enumeration into printable string */\n");
|
||||
lf_printf(file, "STATIC_MODEL const char *model_name[ (int)nr_models ] = {\n");
|
||||
lf_printf(file, " \"NONE\",\n");
|
||||
for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
lf_printf(file, " \"%s\",\n", model_ptr->printable_name);
|
||||
}
|
||||
lf_printf(file, "};\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_printf(file, "/* Emit each model's individual function unit names */\n");
|
||||
lf_printf(file, "static const char *const model_func_unit_name_NONE[] = {\n");
|
||||
lf_printf(file, " \"none\",\n");
|
||||
lf_printf(file, " (const char *)0\n");
|
||||
lf_printf(file, "};\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
lf_printf(file, "static const char *const model_func_unit_name_%s[] = {\n", model_ptr->name);
|
||||
lf_printf(file, " \"none\",\n");
|
||||
for (func_unit_ptr = model_ptr->func_unit_start; func_unit_ptr; func_unit_ptr = func_unit_ptr->next) {
|
||||
|
||||
if (func_unit_ptr->comment)
|
||||
lf_printf(file, " \"%s %s functional unit\",\n", func_unit_ptr->name, func_unit_ptr->comment);
|
||||
else
|
||||
lf_printf(file, " \"%s\",\n", func_unit_ptr->name);
|
||||
|
||||
for(i = 2; i < func_unit_ptr->number; i++) {
|
||||
if (func_unit_ptr->comment)
|
||||
lf_printf(file, " \"%s %s functional unit #%d\",\n", func_unit_ptr->name,
|
||||
func_unit_ptr->comment, i);
|
||||
else
|
||||
lf_printf(file, " \"%s #%d\",\n", func_unit_ptr->name, i);
|
||||
}
|
||||
}
|
||||
|
||||
lf_printf(file, " (const char *)0\n");
|
||||
lf_printf(file, "};\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
lf_printf(file, "/* Array to map model,function unit number to printable string. */\n");
|
||||
lf_printf(file, "STATIC_MODEL const char *const *const model_func_unit_name[] = {\n");
|
||||
lf_printf(file, " model_func_unit_name_NONE,\n");
|
||||
for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
lf_printf(file, " model_func_unit_name_%s,\n", model_ptr->name);
|
||||
}
|
||||
lf_printf(file, "};\n");
|
||||
lf_printf(file, "\n");
|
||||
lf_printf(file, "\f\n");
|
||||
|
||||
lf_printf(file, "/* Insn functional unit info */\n");
|
||||
for(model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
model_c_passed_data data;
|
||||
@ -3339,8 +3187,80 @@ gen_model_c(insn_table *table, lf *file)
|
||||
|
||||
for(insn_ptr = model_functions; insn_ptr; insn_ptr = insn_ptr->next) {
|
||||
model_c_function(table, file, insn_ptr->file_entry, "INLINE_MODEL");
|
||||
name = insn_ptr->file_entry->fields[function_name];
|
||||
if (strcmp (name, "model_create") == 0)
|
||||
model_create_p = 1;
|
||||
else if (strcmp (name, "model_init") == 0)
|
||||
model_init_p = 1;
|
||||
else if (strcmp (name, "model_halt") == 0)
|
||||
model_halt_p = 1;
|
||||
else if (strcmp (name, "model_issue") == 0)
|
||||
model_issue_p = 1;
|
||||
else if (strcmp (name, "model_mon_info") == 0)
|
||||
model_mon_info_p = 1;
|
||||
else if (strcmp (name, "model_mon_info_free") == 0)
|
||||
model_mon_info_free_p = 1;
|
||||
}
|
||||
|
||||
if (!model_create_p) {
|
||||
lf_printf(file, "INLINE_MODEL model_data *model_create(cpu *processor)\n");
|
||||
lf_printf(file, "{\n");
|
||||
lf_printf(file, " return (model_data *)0;\n");
|
||||
lf_printf(file, "}\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_init_p) {
|
||||
lf_printf(file, "INLINE_MODEL void model_init(cpu *processor,\n");
|
||||
lf_printf(file, " model_data *model_ptr)\n");
|
||||
lf_printf(file, "{\n");
|
||||
lf_printf(file, "}\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_halt_p) {
|
||||
lf_printf(file, "INLINE_MODEL void model_halt(cpu *processor,\n");
|
||||
lf_printf(file, " model_data *model_ptr)\n");
|
||||
lf_printf(file, "{\n");
|
||||
lf_printf(file, "}\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_issue_p) {
|
||||
lf_printf(file, "INLINE_MODEL void model_issue(itable_index index,\n");
|
||||
lf_printf(file, " model_data *model_ptr,\n");
|
||||
lf_printf(file, " unsigned_word cia);\n");
|
||||
lf_printf(file, "{\n");
|
||||
lf_printf(file, "}\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_mon_info_p) {
|
||||
lf_printf(file, "INLINE_MODEL model_print *model_mon_info(model_data *model_ptr)\n");
|
||||
lf_printf(file, "{\n");
|
||||
lf_printf(file, " return (model_print *)0;\n");
|
||||
lf_printf(file, "}\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
if (!model_mon_info_free_p) {
|
||||
lf_printf(file, "INLINE_MODEL void model_mon_info_free(model_data *model_ptr,\n");
|
||||
lf_printf(file, " model_print *info_ptr)\n");
|
||||
lf_printf(file, "{\n");
|
||||
lf_printf(file, "}\n");
|
||||
lf_printf(file, "\n");
|
||||
}
|
||||
|
||||
lf_printf(file, "\f\n");
|
||||
lf_printf(file, "/* map model enumeration into printable string */\n");
|
||||
lf_printf(file, "STATIC_MODEL const char *model_name[ (int)nr_models ] = {\n");
|
||||
lf_printf(file, " \"NONE\",\n");
|
||||
for (model_ptr = models; model_ptr; model_ptr = model_ptr->next) {
|
||||
lf_printf(file, " \"%s\",\n", model_ptr->printable_name);
|
||||
}
|
||||
lf_printf(file, "};\n");
|
||||
lf_printf(file, "\n");
|
||||
|
||||
lf_printf(file, "INLINE_MODEL void\n");
|
||||
lf_printf(file, "model_set(const char *name)\n");
|
||||
lf_printf(file, "{\n");
|
||||
|
@ -50,14 +50,18 @@
|
||||
#include "events.c"
|
||||
#endif
|
||||
|
||||
#if MON_INLINE
|
||||
#include "mon.c"
|
||||
#if MODEL_INLINE
|
||||
#include "model.c"
|
||||
#endif
|
||||
|
||||
#if FUNCTION_UNIT_INLINE
|
||||
#include "function_unit.c"
|
||||
#endif
|
||||
|
||||
#if MON_INLINE
|
||||
#include "mon.c"
|
||||
#endif
|
||||
|
||||
#if REGISTERS_INLINE
|
||||
#include "registers.c"
|
||||
#endif
|
||||
|
@ -53,12 +53,16 @@
|
||||
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
int getrusage();
|
||||
#endif
|
||||
|
||||
struct _cpu_mon {
|
||||
unsigned issue_count[nr_itable_entries];
|
||||
unsigned read_count;
|
||||
unsigned write_count;
|
||||
unsigned unaligned_read_count;
|
||||
unsigned unaligned_write_count;
|
||||
unsigned event_count[nr_mon_events];
|
||||
function_unit_print *func_unit_print;
|
||||
};
|
||||
|
||||
@ -90,7 +94,7 @@ INLINE_MON void
|
||||
mon_init(mon *monitor,
|
||||
int nr_cpus)
|
||||
{
|
||||
bzero(monitor, sizeof(*monitor));
|
||||
memset(monitor, 0, sizeof(*monitor));
|
||||
monitor->nr_cpus = nr_cpus;
|
||||
}
|
||||
|
||||
@ -103,9 +107,7 @@ mon_issue(itable_index index,
|
||||
cpu_mon *monitor = cpu_monitor(processor);
|
||||
ASSERT(index <= nr_itable_entries);
|
||||
monitor->issue_count[index] += 1;
|
||||
|
||||
if (WITH_FUNCTION_UNIT)
|
||||
function_unit_issue(index, cpu_function_unit(processor), cia);
|
||||
model_issue(index, cpu_model(processor), cia);
|
||||
}
|
||||
|
||||
|
||||
@ -118,6 +120,8 @@ mon_read(unsigned_word ea,
|
||||
{
|
||||
cpu_mon *monitor = cpu_monitor(processor);
|
||||
monitor->read_count += 1;
|
||||
if ((nr_bytes - 1) & ea)
|
||||
monitor->unaligned_read_count += 1;
|
||||
}
|
||||
|
||||
|
||||
@ -130,6 +134,18 @@ mon_write(unsigned_word ea,
|
||||
{
|
||||
cpu_mon *monitor = cpu_monitor(processor);
|
||||
monitor->write_count += 1;
|
||||
if ((nr_bytes - 1) & ea)
|
||||
monitor->unaligned_write_count += 1;
|
||||
}
|
||||
|
||||
INLINE_MON void
|
||||
mon_event(mon_events event,
|
||||
cpu *processor,
|
||||
unsigned_word cia)
|
||||
{
|
||||
cpu_mon *monitor = cpu_monitor(processor);
|
||||
ASSERT(event >= 0 && event < nr_mon_events);
|
||||
monitor->event_count[event] += 1;
|
||||
}
|
||||
|
||||
STATIC_INLINE_MON unsigned
|
||||
@ -227,11 +243,11 @@ mon_print_info(psim *system,
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
|
||||
if (WITH_FUNCTION_UNIT)
|
||||
if (CURRENT_MODEL)
|
||||
{
|
||||
function_unit *func_unit = cpu_function_unit(psim_cpu(system, cpu_nr));
|
||||
function_unit_print *ptr = function_unit_mon_info(func_unit);
|
||||
function_unit_print *orig_ptr = ptr;
|
||||
model_data *model_ptr = cpu_model(psim_cpu(system, cpu_nr));
|
||||
model_print *ptr = model_mon_info(model_ptr);
|
||||
model_print *orig_ptr = ptr;
|
||||
|
||||
while (ptr) {
|
||||
if (ptr->count)
|
||||
@ -248,7 +264,7 @@ mon_print_info(psim *system,
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
function_unit_mon_free(func_unit, orig_ptr);
|
||||
model_mon_info_free(model_ptr, orig_ptr);
|
||||
}
|
||||
|
||||
if (monitor->cpu_monitor[cpu_nr].read_count)
|
||||
@ -266,7 +282,31 @@ mon_print_info(psim *system,
|
||||
sizeof(buffer),
|
||||
monitor->cpu_monitor[cpu_nr].write_count),
|
||||
(monitor->cpu_monitor[cpu_nr].write_count == 1) ? "" : "s");
|
||||
|
||||
if (monitor->cpu_monitor[cpu_nr].unaligned_read_count)
|
||||
printf_filtered ("CPU #%*d executed %*s unaligned data read%s.\n",
|
||||
len_cpu, cpu_nr+1,
|
||||
len_num, mon_add_commas(buffer,
|
||||
sizeof(buffer),
|
||||
monitor->cpu_monitor[cpu_nr].read_count),
|
||||
(monitor->cpu_monitor[cpu_nr].read_count == 1) ? "" : "s");
|
||||
|
||||
if (monitor->cpu_monitor[cpu_nr].unaligned_write_count)
|
||||
printf_filtered ("CPU #%*d executed %*s unaligned data write%s.\n",
|
||||
len_cpu, cpu_nr+1,
|
||||
len_num, mon_add_commas(buffer,
|
||||
sizeof(buffer),
|
||||
monitor->cpu_monitor[cpu_nr].write_count),
|
||||
(monitor->cpu_monitor[cpu_nr].write_count == 1) ? "" : "s");
|
||||
|
||||
if (monitor->cpu_monitor[cpu_nr].event_count[mon_event_icache_miss])
|
||||
printf_filtered ("CPU #%*d executed %*s icache miss%s.\n",
|
||||
len_cpu, cpu_nr+1,
|
||||
len_num, mon_add_commas(buffer,
|
||||
sizeof(buffer),
|
||||
monitor->cpu_monitor[cpu_nr].event_count[mon_event_icache_miss]),
|
||||
(monitor->cpu_monitor[cpu_nr].event_count[mon_event_icache_miss] == 1) ? "" : "es");
|
||||
|
||||
printf_filtered("CPU #%*d executed %*s instructions in total.\n",
|
||||
len_cpu, cpu_nr+1,
|
||||
len_num, mon_add_commas(buffer,
|
||||
|
@ -31,6 +31,22 @@
|
||||
|
||||
/* monitor/logger: counts what the simulation is up to */
|
||||
|
||||
/* Interfact to model to return model specific information */
|
||||
typedef struct _model_print model_print;
|
||||
struct _model_print {
|
||||
model_print *next;
|
||||
const char *name;
|
||||
const char *suffix_singular;
|
||||
const char *suffix_plural;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
/* Additional events to monitor */
|
||||
typedef enum _mon_events {
|
||||
mon_event_icache_miss,
|
||||
nr_mon_events
|
||||
} mon_events;
|
||||
|
||||
typedef struct _mon mon;
|
||||
typedef struct _cpu_mon cpu_mon;
|
||||
|
||||
@ -68,6 +84,11 @@ INLINE_MON void mon_write
|
||||
cpu *processor,
|
||||
unsigned_word cia);
|
||||
|
||||
INLINE_MON void mon_event
|
||||
(mon_events event,
|
||||
cpu *processor,
|
||||
unsigned_word cia);
|
||||
|
||||
INLINE_MON void mon_print_info
|
||||
(psim *system,
|
||||
mon *monitor,
|
||||
|
@ -64,20 +64,117 @@
|
||||
# 5 Specific CPU model, must be an identifier
|
||||
#
|
||||
# 6 Comma separated list of functional units
|
||||
|
||||
# PowerPC models
|
||||
::model:604:ppc604:PPC_FUNCTION_UNIT_UNKNOWN, PPC_FUNCTION_UNIT_UNKNOWN, 1, 1, 0
|
||||
::model:603e:ppc603e:PPC_FUNCTION_UNIT_UNKNOWN, PPC_FUNCTION_UNIT_UNKNOWN, 1, 1, 0
|
||||
::model:603:ppc603:PPC_FUNCTION_UNIT_UNKNOWN, PPC_FUNCTION_UNIT_UNKNOWN, 1, 1, 0
|
||||
|
||||
# Flags for model.h
|
||||
::model-macro:::#define PPC_LOAD 0x00000001
|
||||
::model-macro:::#define PPC_STORE 0x00000002
|
||||
::model-macro:::#define PPC_SERIALIZE 0x00000004
|
||||
::model-data:::
|
||||
typedef enum _ppc_function_unit {
|
||||
PPC_FUNCTION_UNIT_UNKNOWN, /* unknown function unit */
|
||||
PPC_FUNCTION_UNIT_IU, /* integer unit (603 style) */
|
||||
PPC_FUNCTION_UNIT_SRU, /* system register unit (603 style) */
|
||||
PPC_FUNCTION_UNIT_SCIU1, /* 1st single cycle integer unit (604 style) */
|
||||
PPC_FUNCTION_UNIT_SCIU2, /* 2nd single cycle integer unit (604 style) */
|
||||
PPC_FUNCTION_UNIT_MCIU, /* multiple cycle integer unit (604 style) */
|
||||
PPC_FUNCTION_UNIT_FPU, /* floating point unit */
|
||||
PPC_FUNCTION_UNIT_LSU, /* load/store unit */
|
||||
PPC_FUNCTION_UNIT_BPU, /* branch unit */
|
||||
nr_ppc_function_units
|
||||
} ppc_function_unit;
|
||||
|
||||
/* Structure to hold timing information on a per instruction basis */
|
||||
struct _model_time {
|
||||
ppc_function_unit first_unit; /* first functional unit this insn could use */
|
||||
ppc_function_unit last_unit; /* last functional unit this insn could use */
|
||||
unsigned16 issue; /* # cycles before function unit can process other insns */
|
||||
unsigned16 done; /* # cycles before insn is done */
|
||||
unsigned32 flags; /* flag bits */
|
||||
};
|
||||
|
||||
/* Flags */
|
||||
#define PPC_LOAD 0x00000001 /* insn is a load */
|
||||
#define PPC_STORE 0x00000002 /* insn is a store */
|
||||
#define PPC_SERIALIZE 0x00000004 /* insn forces serialization */
|
||||
|
||||
/* Structure to hold the current state information for the simulated CPU model */
|
||||
struct _model_data {
|
||||
const char *name; /* model name */
|
||||
const model_time *timing; /* timing information */
|
||||
unsigned_word old_program_counter; /* previous PC */
|
||||
unsigned nr_branches; /* # branches */
|
||||
unsigned nr_units[nr_ppc_function_units]; /* function unit counts */
|
||||
unsigned16 busy[nr_ppc_function_units]; /* how long until free */
|
||||
};
|
||||
|
||||
STATIC_MODEL const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
|
||||
"unknown functional unit",
|
||||
"integer functional unit",
|
||||
"system register functional unit",
|
||||
"1st single cycle integer functional unit",
|
||||
"2nd single cycle integer functional unit",
|
||||
"multiple cycle integer functional unit",
|
||||
"floating point functional unit",
|
||||
"load/store functional unit",
|
||||
"branch functional unit",
|
||||
};
|
||||
|
||||
# PowerPC models
|
||||
::model:604:PPC604:SCIU=2 single cycle integer,MCIU=1 multiple cycle integer,FPU=1 floating point,LSU=1 memory,BPU=1 branch
|
||||
::model:603e:PPC603e:IU=1 integer,FPU=1 floating point,LSU=1 memory,SRU=1 system register,BPU=1 branch
|
||||
::model:603:PPC603:IU=1 integer,FPU=1 floating point,LSU=1 memory,SRU=1 system register,BPU=1 branch
|
||||
model_data *::model-function::model_create:cpu *processor
|
||||
if (CURRENT_MODEL == MODEL_NONE)
|
||||
return (model_data *)0;
|
||||
else {
|
||||
model_data *model_ptr = ZALLOC(model_data);
|
||||
model_ptr->name = model_name[CURRENT_MODEL];
|
||||
model_ptr->timing = model_time_mapping[CURRENT_MODEL];
|
||||
return model_ptr;
|
||||
}
|
||||
|
||||
void::model-function::model_init:cpu *processor, model_data *model_ptr
|
||||
void::model-function::model_halt:cpu *processor, model_data *model_ptr
|
||||
|
||||
void::model-function::model_issue:itable_index index, model_data *model_ptr, unsigned_word cia
|
||||
if (model_ptr->old_program_counter+4 != cia)
|
||||
model_ptr->nr_branches++;
|
||||
|
||||
model_ptr->old_program_counter = cia;
|
||||
model_ptr->nr_units[ (int)model_ptr->timing[ (int)index ].first_unit ]++;
|
||||
|
||||
model_print *::model-function::model_mon_info:model_data *model_ptr
|
||||
model_print *head;
|
||||
model_print *tail;
|
||||
ppc_function_unit i;
|
||||
|
||||
head = tail = ZALLOC(model_print);
|
||||
tail->count = model_ptr->nr_branches;
|
||||
tail->name = "branch";
|
||||
tail->suffix_plural = "es";
|
||||
tail->suffix_singular = "";
|
||||
|
||||
for (i = PPC_FUNCTION_UNIT_UNKNOWN; i < nr_ppc_function_units; i++) {
|
||||
if (model_ptr->nr_units[i]) {
|
||||
tail->next = ZALLOC(model_print);
|
||||
tail = tail->next;
|
||||
tail->count = model_ptr->nr_units[i];
|
||||
tail->name = ppc_function_unit_name[i];
|
||||
tail->suffix_plural = "s";
|
||||
tail->suffix_singular = "";
|
||||
}
|
||||
}
|
||||
|
||||
tail->next = (model_print *)0;
|
||||
return head;
|
||||
|
||||
void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
|
||||
model_print *next;
|
||||
|
||||
while (ptr) {
|
||||
next = ptr->next;
|
||||
free((void *)ptr);
|
||||
ptr = next;
|
||||
}
|
||||
|
||||
void::model-function::model_init:void
|
||||
void::model-function::model_halt:void
|
||||
void::model-function::model_print_info:void
|
||||
|
||||
# The following (illegal) instruction is `known' by gen and is
|
||||
# called when ever an illegal instruction is encountered
|
||||
@ -554,16 +651,16 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
|
||||
# I.2.4.1 Branch Instructions
|
||||
#
|
||||
0.18,6.LI,30.AA,31.LK:I:t::Branch
|
||||
*PPC603:PPC603_BPU:1:1:0
|
||||
*PPC603e:PPC603_BPU:1:1:0
|
||||
*PPC604:PPC603_BPU:1:1:0
|
||||
*603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
if (AA) NIA = IEA(EXTS(LI_0b00));
|
||||
else NIA = IEA(CIA + EXTS(LI_0b00));
|
||||
if (LK) LR = (spreg)CIA+4;
|
||||
0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:t::Branch Conditional
|
||||
*PPC603:PPC603_BPU:1:1:0
|
||||
*PPC603e:PPC603_BPU:1:1:0
|
||||
*PPC604:PPC603_BPU:1:1:0
|
||||
*603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
int M, ctr_ok, cond_ok;
|
||||
if (is_64bit_implementation && is_64bit_mode) M = 0;
|
||||
else M = 32;
|
||||
@ -575,9 +672,9 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
|
||||
else NIA = IEA(CIA + EXTS(BD_0b00));
|
||||
if (LK) LR = (spreg)IEA(CIA + 4);
|
||||
0.19,6.BO,11.BI,16./,21.16,31.LK:XL:t::Branch Conditional to Link Register
|
||||
*PPC603:PPC603_BPU:1:1:0
|
||||
*PPC603e:PPC603_BPU:1:1:0
|
||||
*PPC604:PPC603_BPU:1:1:0
|
||||
*603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
int M, ctr_ok, cond_ok;
|
||||
if (is_64bit_implementation && is_64bit_mode) M = 0;
|
||||
else M = 32;
|
||||
@ -587,9 +684,9 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
|
||||
if (ctr_ok && cond_ok) NIA = IEA(LR_0b00);
|
||||
if (LK) LR = (spreg)IEA(CIA + 4);
|
||||
0.19,6.BO,11.BI,16./,21.528,31.LK:XL:t::Branch Conditional to Count Register
|
||||
*PPC603:PPC603_BPU:1:1:0
|
||||
*PPC603e:PPC603_BPU:1:1:0
|
||||
*PPC604:PPC603_BPU:1:1:0
|
||||
*603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
|
||||
int cond_ok;
|
||||
cond_ok = BO{0} || (CR{BI} == BO{1});
|
||||
if (cond_ok) NIA = IEA(CTR_0b00);
|
||||
@ -1075,90 +1172,159 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
|
||||
#
|
||||
|
||||
0.14,6.RT,11.RA,16.SI:D:T::Add Immediate
|
||||
*PPC603:PPC603_IU:1:1:0
|
||||
*PPC603e:PPC603e_IU|PPC603e_SRU:1:1:0
|
||||
*PPC604:PPC604_SCIU:1:1:0
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_SRU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
if (RA_is_0) *rT = EXTS(SI);
|
||||
else *rT = *rA + EXTS(SI);
|
||||
|
||||
0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_SRU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
if (RA_is_0) *rT = EXTS(SI) << 16;
|
||||
else *rT = *rA + (EXTS(SI) << 16);
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_SRU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_ADD(*rB);
|
||||
ALU_END(*rT, 0/*CA*/, OE, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_NOT;
|
||||
ALU_ADD(*rB);
|
||||
ALU_ADD(1);
|
||||
ALU_END(*rT, 0/*CA*/, OE, Rc);
|
||||
|
||||
0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_ADD(EXTS(SI));
|
||||
ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
|
||||
|
||||
0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_ADD(EXTS(SI));
|
||||
ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
|
||||
|
||||
0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_NOT;
|
||||
ALU_ADD(EXTS(SI));
|
||||
ALU_ADD(1);
|
||||
ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_ADD(*rB);
|
||||
ALU_END(*rT, 1/*CA*/, OE, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
/* RT <- ~RA + RB + 1 === RT <- RB - RA */
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_NOT;
|
||||
ALU_ADD(*rB);
|
||||
ALU_ADD(1);
|
||||
ALU_END(*rT, 1/*CA*/, OE, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_ADD(*rB);
|
||||
ALU_ADD_CA;
|
||||
ALU_END(*rT, 1/*CA*/, OE, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_NOT;
|
||||
ALU_ADD(*rB);
|
||||
ALU_ADD_CA;
|
||||
ALU_END(*rT, 1/*CA*/, OE, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
# ALU_BEGIN(*rA);
|
||||
# ALU_ADD_CA;
|
||||
# ALU_SUB(1);
|
||||
# ALU_END(*rT, 1/*CA*/, OE, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
# ALU_BEGIN(*rA);
|
||||
# ALU_NOT;
|
||||
# ALU_ADD_CA;
|
||||
# ALU_SUB(1);
|
||||
# ALU_END(*rT, 1/*CA*/, OE, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_ADD_CA;
|
||||
ALU_END(*rT, 1/*CA*/, OE, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_NOT;
|
||||
ALU_ADD_CA;
|
||||
ALU_END(*rT, 1/*CA*/, OE, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
|
||||
*604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
|
||||
ALU_BEGIN(*rA);
|
||||
ALU_NOT;
|
||||
ALU_ADD(1);
|
||||
ALU_END(*rT,0/*CA*/,OE,Rc);
|
||||
|
||||
0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 3, 3, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 3, 3, 0
|
||||
*604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 3, 3, 0
|
||||
signed_word prod = *rA * EXTS(SI);
|
||||
*rT = prod;
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
|
||||
*604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 4, 4, 0
|
||||
signed64 a = (signed32)(*rA);
|
||||
signed64 b = (signed32)(*rB);
|
||||
signed64 prod = a * b;
|
||||
@ -1167,24 +1333,39 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
|
||||
if (t != prod && OE)
|
||||
XER |= (xer_overflow | xer_summary_overflow);
|
||||
CR0_COMPARE(t, 0, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
|
||||
*604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 4, 4, 0
|
||||
signed64 a = (signed32)(*rA);
|
||||
signed64 b = (signed32)(*rB);
|
||||
signed64 prod = a * b;
|
||||
signed_word t = EXTRACTED64(prod, 0, 31);
|
||||
*rT = t;
|
||||
CR0_COMPARE(t, 0, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 6, 6, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 6, 6, 0
|
||||
*604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 4, 4, 0
|
||||
unsigned64 a = (unsigned32)(*rA);
|
||||
unsigned64 b = (unsigned32)(*rB);
|
||||
unsigned64 prod = a * b;
|
||||
signed_word t = EXTRACTED64(prod, 0, 31);
|
||||
*rT = t;
|
||||
CR0_COMPARE(t, 0, Rc);
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
|
||||
*604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 20, 20, 0
|
||||
signed64 dividend = (signed32)(*rA);
|
||||
signed64 divisor = (signed32)(*rB);
|
||||
if (divisor == 0 /* nb 0x8000..0 is sign extended */
|
||||
@ -1199,7 +1380,11 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
|
||||
CR0_COMPARE((signed_word)quotent, 0, Rc);
|
||||
}
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
|
||||
|
||||
0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
|
||||
*603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
|
||||
*603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
|
||||
*604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 20, 20, 0
|
||||
unsigned64 dividend = (unsigned32)(*rA);
|
||||
unsigned64 divisor = (unsigned32)(*rB);
|
||||
if (divisor == 0) {
|
||||
@ -1561,7 +1746,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
|
||||
# I.3.3.14 Move to/from System Register Instructions
|
||||
#
|
||||
|
||||
0.31,6.RS,11.spr,21.467,31./:XFX:::Move to Special Purpose Register
|
||||
0.31,6.RS,11.spr,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
|
||||
int n = (spr{5:9} << 5) | spr{0:4};
|
||||
if (spr{0} && IS_PROBLEM_STATE(processor))
|
||||
program_interrupt(processor, cia,
|
||||
@ -1580,15 +1765,13 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
|
||||
switch (n) {
|
||||
case spr_tbu:
|
||||
cpu_set_time_base(processor,
|
||||
(MASKED64(cpu_get_time_base(processor),
|
||||
32, 63)
|
||||
| ((signed64)new_val << 32)));
|
||||
(MASKED64(cpu_get_time_base(processor), 32, 63)
|
||||
| INSERTED64(new_val, 0, 31)));
|
||||
break;
|
||||
case spr_tbl:
|
||||
cpu_set_time_base(processor,
|
||||
(MASKED64(cpu_get_time_base(processor),
|
||||
32, 63)
|
||||
| ((signed64)new_val << 32)));
|
||||
(MASKED64(cpu_get_time_base(processor), 0, 31)
|
||||
| INSERTED64(new_val, 32, 63)));
|
||||
break;
|
||||
case spr_dec:
|
||||
cpu_set_decrementer(processor, new_val);
|
||||
@ -1602,7 +1785,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
|
||||
SPREG(n) = new_val;
|
||||
}
|
||||
}
|
||||
0.31,6.RT,11.spr,21.339,31./:XFX:uea::Move from Special Purpose Register
|
||||
0.31,6.RT,11.spr,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
|
||||
int n = (spr{5:9} << 5) | spr{0:4};
|
||||
if (spr{0} && IS_PROBLEM_STATE(processor))
|
||||
program_interrupt(processor, cia,
|
||||
@ -2329,7 +2512,10 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
|
||||
#
|
||||
|
||||
0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
|
||||
; /* nop for now */
|
||||
/* blindly flush all instruction cache entries */
|
||||
#if WITH_IDECODE_CACHE_SIZE
|
||||
cpu_flush_icache(processor);
|
||||
#endif
|
||||
|
||||
0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
|
||||
cpu_synchronize_context(processor);
|
||||
@ -2385,8 +2571,19 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
|
||||
# III.2.3.1 System Linkage Instructions
|
||||
#
|
||||
|
||||
#0.17,6./,11./,16./,30.1,31./:SC:::System Call
|
||||
0.19,6./,11./,16./,21.50,31./:XL:::Return From Interrupt
|
||||
#0.17,6./,11./,16./,30.1,31./:SC::sc:System Call
|
||||
0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
|
||||
if (IS_PROBLEM_STATE(processor)) {
|
||||
program_interrupt(processor, cia,
|
||||
privileged_instruction_program_interrupt);
|
||||
}
|
||||
else {
|
||||
MSR = (MASKED(SRR1, 0, 32)
|
||||
| MASKED(SRR1, 37, 41)
|
||||
| MASKED(SRR1, 48, 63));
|
||||
NIA = MASKED(SRR0, 0, 61);
|
||||
cpu_synchronize_context(processor);
|
||||
}
|
||||
|
||||
#
|
||||
# III.3.4.1 Move to/from System Register Instructions
|
||||
|
Loading…
Reference in New Issue
Block a user