This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
sim/igen: add gen-delay-slot generation option
- To: gdb-patches at sourceware dot cygnus dot com
- Subject: sim/igen: add gen-delay-slot generation option
- From: cgd at sibyte dot com (Chris G. Demetriou)
- Date: 04 Dec 2000 14:43:12 -0800
- Cc: ehs at sibyte dot com
The patch below:
(1) adds a new simulator generation option to igen, "gen-delay-slot".
This new option generates PC pipe manipulation operations in a way
that can be used to cleanly and correctly model MIPS branch delay
slots.
(2) changes the generated code so that any wired-zero registers are
cleared by common code (shared by all of the opcodes), rather than
by each individual opcode's implementation.
The changes were implemented by a coworker, Ed Satterthwaite (who's
CC'd on this message), then cleaned up for submission by me. We've
both got assignment paperwork on file.
I've tested this in the manner described in the message I recently
sent:
http://sources.redhat.com/ml/gdb/2000-12/msg00015.html
It doesn't change any test output for any of the targets there
(several of which -- all but fr30 and sparclite -- seem to
successfully run things through the resulting 'run' binaries). This
doesn't surprise me; as you would see by looking at the code, (1)
doesn't change the code unless you've specified the new option, and
(2) does changes the code in a fairly straightforward way. 8-)
goes in sim/igen.
2000-12-02 Ed Satterthwaite ehs@sibyte.com and
Chris Demetriou cgd@sibyte.com
* igen.c (main): Add gen-delay-slot option.
(print_semantic_function_formal,
print_semantic_function_actual, print_icache_function_formal,
print_icache_function_actual): Implement gen-delay-slot
option.
* igen.h (_igen_gen_options): Add delay_slot member.
* gen-engine.c (print_register_clear): New function
used to handle gen-zero-r option.
(print_run_body): Implement gen-delay-slot option. Use
print_register_clear.
(print_jump_body): Use print_register_clear.
* gen-semantics.c (print_semantic_body): Implement
gen-delay-slot option. Delete old code to handle
gen-zero-r option.
* gen-support.c (print_support_function_name,
gen_support_h): Implement gen-delay-slot option.
* ld-insn.c (option_names, option_map, parse_option_record):
Implement gen-delay-slot option.
chris
===================================================================
Index: gen-engine.c
===================================================================
RCS file: /cvs/src/src/sim/igen/gen-engine.c,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 gen-engine.c
*** gen-engine.c 1999/04/16 01:35:04 1.1.1.1
--- gen-engine.c 2000/12/03 00:22:02
*************** print_engine_issue_postfix_hook (lf *fil
*** 66,71 ****
--- 66,85 ----
static void
+ print_register_clear (lf *file)
+ {
+ /* Architecture expects a REG to be zero. Instead of having to
+ check every read to see if it is refering to that REG just zap it
+ at the start of every instruction */
+ if (options.gen.zero_reg)
+ {
+ lf_printf (file, "/* Architecture expects REG to be zero */\n");
+ lf_printf (file, "GPR_CLEAR(%d);\n", options.gen.zero_reg_nr);
+ lf_printf (file, "\n");
+ }
+ }
+
+ static void
print_run_body (lf *file,
gen_entry *table)
{
*************** print_run_body (lf *file,
*** 84,89 ****
--- 98,107 ----
lf_printf (file, "%sinstruction_address cia;\n", options.module.global.prefix.l);
}
lf_printf (file, "int current_cpu = next_cpu_nr;\n");
+ if (!options.gen.smp && options.gen.delay_slot)
+ {
+ lf_putstr (file, "sim_cpu *cpu = STATE_CPU (sd, current_cpu);\n");
+ }
if (options.gen.icache)
{
*************** In this case, we can take advantage of t
*** 105,113 ****
instruction address (CIA) does not need to be read from / written to
the CPU object after the execution of an instruction.
! Instead, CIA is only saved when the main loop exits. This occures
! when either sim_engine_halt or sim_engine_restart is called. Both of
! these functions save the current instruction address before halting /
restarting the simulator.
As a variation, there may also be support for an instruction cracking
--- 123,131 ----
instruction address (CIA) does not need to be read from / written to
the CPU object after the execution of an instruction.
! CIA is only saved when the main loop exits. This occurs when either
! sim_engine_halt or sim_engine_restart is called. Both of these
! functions save the current instruction address before halting /
restarting the simulator.
As a variation, there may also be support for an instruction cracking
*************** cache. */
*** 120,126 ****
lf_putstr (file, "SIM_ASSERT (current_cpu == 0);\n");
lf_putstr (file, "SIM_ASSERT (nr_cpus == 1);\n");
lf_putstr (file, "cia = CIA_GET (CPU);\n");
-
lf_putstr (file, "\n");
lf_putstr (file, "while (1)\n");
lf_putstr (file, " {\n");
--- 138,143 ----
*************** cache. */
*** 132,141 ****
lf_printf (file, "\n");
if (!options.gen.icache)
{
! lf_printf (file, "%sinstruction_word instruction_0 = IMEM%d (cia);\n",
options.module.global.prefix.l,
options.insn_bit_size);
print_engine_issue_prefix_hook (file);
print_idecode_body (file, table, "nia = ");
print_engine_issue_postfix_hook (file);
}
--- 149,168 ----
lf_printf (file, "\n");
if (!options.gen.icache)
{
! if (options.gen.delay_slot)
! {
! lf_printf (file, "%sinstruction_word instruction_0;\n",
! options.module.global.prefix.l);
! lf_putstr (file, "\n");
! lf_printf (file, "instruction_0 = IMEM%d (cia);\n",
! options.insn_bit_size);
! }
! else
! lf_printf (file, "%sinstruction_word instruction_0 = IMEM%d (cia);\n",
options.module.global.prefix.l,
options.insn_bit_size);
print_engine_issue_prefix_hook (file);
+ print_register_clear (file);
print_idecode_body (file, table, "nia = ");
print_engine_issue_postfix_hook (file);
}
*************** cache. */
*** 169,174 ****
--- 196,202 ----
lf_putstr (file, "{\n");
lf_indent (file, +2);
print_engine_issue_prefix_hook (file);
+ print_register_clear (file);
print_idecode_body (file, table, "nia =");
print_engine_issue_postfix_hook (file);
lf_indent (file, -2);
*************** cache. */
*** 177,182 ****
--- 205,211 ----
else
{
print_engine_issue_prefix_hook (file);
+ print_register_clear (file);
print_idecode_body (file, table, "semantic =");
lf_putstr (file, "nia = semantic (cpu, cache_entry, cia);\n");
print_engine_issue_postfix_hook (file);
*************** cache. */
*** 197,202 ****
--- 226,235 ----
case nia_is_invalid:
ERROR ("engine gen when NIA complex");
}
+ if (options.gen.delay_slot)
+ {
+ lf_printf (file, "CLOCK_PC_PIPE (cpu);\n");
+ }
/* events */
lf_putstr (file, "\n");
*************** after all the other CPU's and the event
*** 230,259 ****
lf_printf (file, "SIM_ASSERT (current_cpu >= 0);\n");
lf_printf (file, "SIM_ASSERT (current_cpu <= nr_cpus - 1);\n");
lf_printf (file, "SIM_ASSERT (nr_cpus <= MAX_NR_PROCESSORS);\n");
-
lf_putstr (file, "\n");
lf_putstr (file, "while (1)\n");
lf_putstr (file, " {\n");
lf_indent (file, +4);
lf_putstr (file, "sim_cpu *cpu = STATE_CPU (sd, current_cpu);\n");
! lf_putstr (file, "instruction_address cia = CIA_GET (cpu);\n");
! lf_putstr (file, "\n");
if (!options.gen.icache)
{
! lf_printf (file, "instruction_word instruction_0 = IMEM%d (cia);\n",
! options.insn_bit_size);
print_engine_issue_prefix_hook (file);
! print_idecode_body (file, table, "cia =");
! lf_putstr (file, "CIA_SET (cpu, cia);\n");
print_engine_issue_postfix_hook (file);
}
if (options.gen.icache)
{
! lf_putstr (file, "engine_cache *cache_entry =\n");
! lf_putstr (file, " cpu_icache_entry(processor, cia);\n");
! lf_putstr (file, "\n");
lf_putstr (file, "if (cache_entry->address == cia) {\n");
{
lf_indent (file, +2);
--- 263,324 ----
lf_printf (file, "SIM_ASSERT (current_cpu >= 0);\n");
lf_printf (file, "SIM_ASSERT (current_cpu <= nr_cpus - 1);\n");
lf_printf (file, "SIM_ASSERT (nr_cpus <= MAX_NR_PROCESSORS);\n");
lf_putstr (file, "\n");
+
lf_putstr (file, "while (1)\n");
lf_putstr (file, " {\n");
lf_indent (file, +4);
lf_putstr (file, "sim_cpu *cpu = STATE_CPU (sd, current_cpu);\n");
! if (options.gen.delay_slot)
! {
! lf_putstr (file, "\n");
! lf_putstr (file, "if (! RESET (cpu))\n");
! lf_putstr (file, " {\n");
! lf_indent (file, +4);
! lf_putstr (file, "instruction_address cia;\n");
! }
! else
! lf_putstr (file, "instruction_address cia = CIA_GET (cpu);\n");
if (!options.gen.icache)
{
! if (options.gen.delay_slot)
! {
! lf_printf (file, "instruction_word instruction_0;\n");
! lf_putstr (file, "\n");
! lf_printf (file, "cia = CIA_GET (cpu);\n");
! lf_printf (file, "instruction_0 = IMEM%d (cia);\n",
! options.insn_bit_size);
! }
! else
! lf_printf (file, "instruction_word instruction_0 = IMEM%d (cia);\n",
! options.insn_bit_size);
print_engine_issue_prefix_hook (file);
! print_register_clear (file);
! print_idecode_body (file, table, "cia = ");
print_engine_issue_postfix_hook (file);
+ lf_putstr (file, "CIA_SET (cpu, cia);\n");
+ if (options.gen.delay_slot)
+ {
+ lf_printf (file, "CLOCK_PC_PIPE (cpu);\n");
+ }
}
if (options.gen.icache)
{
! if (options.gen.delay_slot)
! {
! lf_putstr (file, "engine_cache *cache_entry;\n");
! lf_putstr (file, "\n");
! lf_printf (file, "cia = CIA_GET (cpu);\n");
! lf_putstr (file, "cache_entry = cpu_icache_entry(processor, cia);\n");
! }
! else
! {
! lf_putstr (file, "engine_cache *cache_entry =\n");
! lf_putstr (file, " cpu_icache_entry(processor, cia);\n");
! lf_putstr (file, "\n");
! }
lf_putstr (file, "if (cache_entry->address == cia) {\n");
{
lf_indent (file, +2);
*************** after all the other CPU's and the event
*** 285,290 ****
--- 350,356 ----
lf_putstr (file, "{\n");
lf_indent (file, +2);
print_engine_issue_prefix_hook (file);
+ print_register_clear (file);
print_idecode_body(file, table, "cia =");
print_engine_issue_postfix_hook (file);
lf_indent (file, -2);
*************** after all the other CPU's and the event
*** 293,298 ****
--- 359,365 ----
else
{
print_engine_issue_prefix_hook (file);
+ print_register_clear (file);
print_idecode_body(file, table, "semantic = ");
lf_putstr (file, "cia = semantic(processor, cache_entry, cia);\n");
print_engine_issue_postfix_hook (file);
*************** after all the other CPU's and the event
*** 305,310 ****
--- 372,382 ----
lf_putstr (file, "}\n");
}
+ if (options.gen.delay_slot)
+ {
+ lf_indent (file, -4);
+ lf_putstr (file, " }\n");
+ }
lf_putstr (file, "\n");
lf_putstr (file, "current_cpu += 1;\n");
lf_putstr (file, "if (current_cpu == nr_cpus)\n");
*************** print_jump_body (lf *file,
*** 653,663 ****
lf_indent (file, +1);
}
! print_engine_issue_prefix_hook (file);
lf_putstr (file, "instruction\n");
lf_putstr (file, " = vm_instruction_map_read(cpu_instruction_map(processor),\n");
lf_putstr (file, " processor, nia);\n");
print_engine_issue_prefix_hook (file);
print_idecode_body (file, entry, "/*IGORE*/");
print_engine_issue_postfix_hook (file);
--- 725,736 ----
lf_indent (file, +1);
}
! print_engine_issue_prefix_hook (file); /* XXX also 4 lines below? */
lf_putstr (file, "instruction\n");
lf_putstr (file, " = vm_instruction_map_read(cpu_instruction_map(processor),\n");
lf_putstr (file, " processor, nia);\n");
print_engine_issue_prefix_hook (file);
+ print_register_clear (file);
print_idecode_body (file, entry, "/*IGORE*/");
print_engine_issue_postfix_hook (file);
Index: gen-semantics.c
===================================================================
RCS file: /cvs/src/src/sim/igen/gen-semantics.c,v
retrieving revision 1.2
diff -c -p -r1.2 gen-semantics.c
*** gen-semantics.c 2000/05/29 19:28:53 1.2
--- gen-semantics.c 2000/12/03 00:22:02
*************** print_semantic_body (lf *file,
*** 219,226 ****
}
else
{
! lf_printf (file, "nia = cia + %d;\n",
! options.insn_bit_size / 8);
}
}
}
--- 219,233 ----
}
else
{
! if (options.gen.delay_slot)
! {
! lf_printf (file, "nia = NIA_GET (CPU); ");
! lf_printf (file, "ADVANCE_PC_PIPE (CPU, %d);\n",
! options.insn_bit_size / 8);
! }
! else
! lf_printf (file, "nia = cia + %d;\n",
! options.insn_bit_size / 8);
}
}
}
*************** print_semantic_body (lf *file,
*** 237,252 ****
lf_printf (file, " {\n");
lf_indent (file, +4);
/* FIXME - need to log a conditional failure */
- }
-
- /* Architecture expects a REG to be zero. Instead of having to
- check every read to see if it is refering to that REG just zap it
- at the start of every instruction */
- if (options.gen.zero_reg)
- {
- lf_printf (file, "\n");
- lf_printf (file, "/* Architecture expects REG to be zero */\n");
- lf_printf (file, "GPR_CLEAR(%d);\n", options.gen.zero_reg_nr);
}
/* generate the code (or at least something */
--- 244,249 ----
Index: gen-support.c
===================================================================
RCS file: /cvs/src/src/sim/igen/gen-support.c,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 gen-support.c
*** gen-support.c 1999/04/16 01:35:04 1.1.1.1
--- gen-support.c 2000/12/03 00:22:02
*************** print_support_function_name (lf *file,
*** 77,83 ****
lf_printf (file, "%s%s\n(",
options.module.support.prefix.l,
function->name);
! if (options.gen.smp)
lf_printf (file,
"sim_cpu *cpu, %sinstruction_address cia, int MY_INDEX",
options.module.support.prefix.l);
--- 77,83 ----
lf_printf (file, "%s%s\n(",
options.module.support.prefix.l,
function->name);
! if (options.gen.smp || options.gen.delay_slot)
lf_printf (file,
"sim_cpu *cpu, %sinstruction_address cia, int MY_INDEX",
options.module.support.prefix.l);
*************** gen_support_h (lf *file,
*** 111,117 ****
insn_table *table)
{
/* output the definition of `SD_'*/
! if (options.gen.smp)
{
lf_printf(file, "#define SD CPU_STATE (cpu)\n");
lf_printf(file, "#define CPU cpu\n");
--- 111,117 ----
insn_table *table)
{
/* output the definition of `SD_'*/
! if (options.gen.smp || options.gen.delay_slot)
{
lf_printf(file, "#define SD CPU_STATE (cpu)\n");
lf_printf(file, "#define CPU cpu\n");
Index: igen.c
===================================================================
RCS file: /cvs/src/src/sim/igen/igen.c,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 igen.c
*** igen.c 1999/04/16 01:35:04 1.1.1.1
--- igen.c 2000/12/03 00:22:02
*************** print_semantic_function_formal (lf *file
*** 65,71 ****
nr += lf_printf (file, "%sinstruction_address cia",
options.module.global.prefix.l);
}
! else if (options.gen.smp)
{
nr += lf_printf (file, "sim_cpu *cpu,\n");
for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
--- 65,71 ----
nr += lf_printf (file, "%sinstruction_address cia",
options.module.global.prefix.l);
}
! else if (options.gen.smp || options.gen.delay_slot)
{
nr += lf_printf (file, "sim_cpu *cpu,\n");
for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
*************** print_semantic_function_actual (lf *file
*** 104,110 ****
}
else
{
! if (options.gen.smp)
nr += lf_printf (file, "cpu");
else
nr += lf_printf (file, "sd");
--- 104,110 ----
}
else
{
! if (options.gen.smp || options.gen.delay_slot)
nr += lf_printf (file, "cpu");
else
nr += lf_printf (file, "sd");
*************** print_icache_function_formal (lf *file,
*** 133,139 ****
{
int nr = 0;
int word_nr;
! if (options.gen.smp)
nr += lf_printf (file, "sim_cpu *cpu,\n");
else
nr += lf_printf (file, "SIM_DESC sd,\n");
--- 133,139 ----
{
int nr = 0;
int word_nr;
! if (options.gen.smp || options.gen.delay_slot)
nr += lf_printf (file, "sim_cpu *cpu,\n");
else
nr += lf_printf (file, "SIM_DESC sd,\n");
*************** print_icache_function_actual (lf *file,
*** 153,159 ****
{
int nr = 0;
int word_nr;
! if (options.gen.smp)
nr += lf_printf (file, "cpu");
else
nr += lf_printf (file, "sd");
--- 153,159 ----
{
int nr = 0;
int word_nr;
! if (options.gen.smp || options.gen.delay_slot)
nr += lf_printf (file, "cpu");
else
nr += lf_printf (file, "sd");
*************** main (int argc,
*** 1086,1091 ****
--- 1086,1092 ----
printf ("\n");
printf ("\t gen-conditional-issue - conditionally issue each instruction\n");
printf ("\t gen-delayed-branch - need both cia and nia passed around\n");
+ printf ("\t gen-delay-slot - variant of gen-delayed-branch (in the MIPS style)\n");
printf ("\t gen-direct-access - use #defines to directly access values\n");
printf ("\t gen-zero-r<N> - arch assumes GPR(<N>) == 0, keep it that way\n");
printf ("\t gen-icache[=<N> - generate an instruction cracking cache of size <N>\n");
*************** main (int argc,
*** 1367,1372 ****
--- 1368,1377 ----
{
options.gen.delayed_branch = enable_p;
options.warning (NULL, "Option delayed-branch replaced by gen-delayed-branch\n");
+ }
+ else if (strcmp (argp, "gen-delay-slot") == 0)
+ {
+ options.gen.delay_slot = enable_p;
}
else if (strcmp (argp, "gen-direct-access") == 0)
{
Index: igen.h
===================================================================
RCS file: /cvs/src/src/sim/igen/igen.h,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 igen.h
*** igen.h 1999/04/16 01:35:04 1.1.1.1
--- igen.h 2000/12/03 00:22:02
*************** struct _igen_gen_options {
*** 51,56 ****
--- 51,57 ----
int conditional_issue;
int slot_verification;
int delayed_branch;
+ int delay_slot;
/* If zeroing a register, which one? */
int zero_reg;
Index: ld-insn.c
===================================================================
RCS file: /cvs/src/src/sim/igen/ld-insn.c,v
retrieving revision 1.1.1.1
diff -c -p -r1.1.1.1 ld-insn.c
*** ld-insn.c 1999/04/16 01:35:05 1.1.1.1
--- ld-insn.c 2000/12/03 00:22:02
*************** typedef enum {
*** 618,623 ****
--- 618,624 ----
multi_sim_option,
format_names_option,
gen_delayed_branch,
+ gen_delay_slot,
unknown_option,
} option_names;
*************** static const name_map option_map[] = {
*** 630,635 ****
--- 631,637 ----
{ "multi-sim", multi_sim_option },
{ "format-names", format_names_option },
{ "gen-delayed-branch", gen_delayed_branch },
+ { "gen-delay-slot", gen_delay_slot },
{ NULL, unknown_option },
};
*************** parse_option_record (table *file,
*** 723,728 ****
--- 725,735 ----
case gen_delayed_branch:
{
options.gen.delayed_branch = a2i (value);
+ break;
+ }
+ case gen_delay_slot:
+ {
+ options.gen.delay_slot = a2i (value);
break;
}
case unknown_option: