diff options
Diffstat (limited to 'sim')
-rw-r--r-- | sim/ppc/ChangeLog | 27 | ||||
-rw-r--r-- | sim/ppc/cpu.c | 42 | ||||
-rw-r--r-- | sim/ppc/cpu.h | 4 | ||||
-rw-r--r-- | sim/ppc/igen.c | 410 | ||||
-rw-r--r-- | sim/ppc/inline.c | 8 | ||||
-rw-r--r-- | sim/ppc/mon.c | 58 | ||||
-rw-r--r-- | sim/ppc/mon.h | 21 | ||||
-rw-r--r-- | sim/ppc/ppc-instructions | 269 |
8 files changed, 537 insertions, 302 deletions
diff --git a/sim/ppc/ChangeLog b/sim/ppc/ChangeLog index f0d8efa..cd96e8e 100644 --- a/sim/ppc/ChangeLog +++ b/sim/ppc/ChangeLog @@ -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> diff --git a/sim/ppc/cpu.c b/sim/ppc/cpu.c index f145ae4..6defe2f 100644 --- a/sim/ppc/cpu.c +++ b/sim/ppc/cpu.c @@ -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, diff --git a/sim/ppc/cpu.h b/sim/ppc/cpu.h index a89f7b9..b66cffd 100644 --- a/sim/ppc/cpu.h +++ b/sim/ppc/cpu.h @@ -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) \ diff --git a/sim/ppc/igen.c b/sim/ppc/igen.c index af337a3..2765d46 100644 --- a/sim/ppc/igen.c +++ b/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"); diff --git a/sim/ppc/inline.c b/sim/ppc/inline.c index 715373a..894f0c9 100644 --- a/sim/ppc/inline.c +++ b/sim/ppc/inline.c @@ -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 diff --git a/sim/ppc/mon.c b/sim/ppc/mon.c index 0efb1bf..c6a6e95 100644 --- a/sim/ppc/mon.c +++ b/sim/ppc/mon.c @@ -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, diff --git a/sim/ppc/mon.h b/sim/ppc/mon.h index e8ac2e3..6df22c9 100644 --- a/sim/ppc/mon.h +++ b/sim/ppc/mon.h @@ -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, diff --git a/sim/ppc/ppc-instructions b/sim/ppc/ppc-instructions index 4aa91e4..2d7b5be 100644 --- a/sim/ppc/ppc-instructions +++ b/sim/ppc/ppc-instructions @@ -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", + }; + +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; + } -# 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 +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 |