} 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;
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;
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;
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;
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;
}
}
{
/* 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)
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
{
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");
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) {
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");
}
{
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
{
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");
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) {
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;
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");
# 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
# 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;
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;
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);
#
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;
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 */
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) {
# 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,
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);
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,
#
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);
# 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