sim/igen: add gen-delay-slot generation option

Chris G. Demetriou cgd@sibyte.com
Mon Dec 4 14:43:00 GMT 2000


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:



More information about the Gdb-patches mailing list