More model specific changes

This commit is contained in:
Michael Meissner 1995-11-15 22:53:59 +00:00
parent 1b09c02b17
commit 80948f392b
8 changed files with 537 additions and 302 deletions

View File

@ -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>

View File

@ -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,

View File

@ -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) \

View File

@ -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");

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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