* dv-m68hc11tim.c (cycle_to_string): Add flags parameter to better
authorStephane Carrez <stcarrez@nerim.fr>
Fri, 8 Aug 2003 21:02:24 +0000 (21:02 +0000)
committerStephane Carrez <stcarrez@nerim.fr>
Fri, 8 Aug 2003 21:02:24 +0000 (21:02 +0000)
control the translation.
(m68hc11tim_print_timer): Update cycle_to_string conversion.
(m68hc11tim_timer_event): Fix handling of output
compare register with its interrupts.
(m68hc11tim_io_write_buffer): Check output compare
after setting M6811_TMSK1.
(m68hc11tim_io_read_buffer): Fix compilation warning.
* dv-m68hc11.c (m68hc11_option_handler): Likewise.
* dv-m68hc11spi.c (m68hc11spi_info): Likewise.
* dv-m68hc11sio.c (m68hc11sio_info): Likewise.
* interrupts.c (interrupts_info): Likewise.
(interrupts_reset): Recognize bootstrap mode.
* sim-main.h (PRINT_CYCLE, PRINT_TIME): New defines.
(_sim_cpu): Add cpu_start_mode.
(cycle_to_string): Add flags member.
* m68hc11_sim.c (OPTION_CPU_BOOTSTRAP): New option.
(cpu_options): Declare new option bootstrap.
(cpu_option_handler): Handle it.
(cpu_info): Update call to cycle_to_string.

sim/m68hc11/ChangeLog
sim/m68hc11/dv-m68hc11.c
sim/m68hc11/dv-m68hc11sio.c
sim/m68hc11/dv-m68hc11spi.c
sim/m68hc11/dv-m68hc11tim.c
sim/m68hc11/interrupts.c
sim/m68hc11/m68hc11_sim.c
sim/m68hc11/sim-main.h

index 5cd46d0efe3eb5f58e420db31cf8422a3aa39578..3d019d76589543f33c8e448bd78a7d0762d06eaf 100644 (file)
@@ -1,3 +1,26 @@
+2003-08-08  Stephane Carrez  <stcarrez@nerim.fr>
+
+       * dv-m68hc11tim.c (cycle_to_string): Add flags parameter to better
+       control the translation.
+       (m68hc11tim_print_timer): Update cycle_to_string conversion.
+       (m68hc11tim_timer_event): Fix handling of output
+       compare register with its interrupts.
+       (m68hc11tim_io_write_buffer): Check output compare
+       after setting M6811_TMSK1.
+       (m68hc11tim_io_read_buffer): Fix compilation warning.
+       * dv-m68hc11.c (m68hc11_option_handler): Likewise.
+       * dv-m68hc11spi.c (m68hc11spi_info): Likewise.
+       * dv-m68hc11sio.c (m68hc11sio_info): Likewise.
+       * interrupts.c (interrupts_info): Likewise.
+       (interrupts_reset): Recognize bootstrap mode.
+       * sim-main.h (PRINT_CYCLE, PRINT_TIME): New defines.
+       (_sim_cpu): Add cpu_start_mode.
+       (cycle_to_string): Add flags member.
+       * m68hc11_sim.c (OPTION_CPU_BOOTSTRAP): New option.
+       (cpu_options): Declare new option bootstrap.
+       (cpu_option_handler): Handle it.
+       (cpu_info): Update call to cycle_to_string.
+
 2003-08-08  Stephane Carrez  <stcarrez@nerim.fr>
 
        * sim-main.h (phys_to_virt): Use memory bank parameters to translate
index cad100a9b591b649484df6838641645ddfb490fe..5cc716182bc23d3d4cf7fc1f2dcdbe0a1c5700ba 100644 (file)
@@ -808,13 +808,15 @@ m68hc11_option_handler (SIM_DESC sd, sim_cpu *cpu,
                                "      %d       %d    %35.35s\n",
                                osc->name, freq,
                                cur_value, next_value,
-                               cycle_to_string (cpu, t));
+                               cycle_to_string (cpu, t,
+                                                PRINT_TIME | PRINT_CYCLE));
               else
                 sim_io_printf (sd, " %4.4s  %8.8s hz "
                                "      %d       %d    %35.35s\n",
                                osc->name, freq,
                                cur_value, next_value,
-                               cycle_to_string (cpu, t));
+                               cycle_to_string (cpu, t,
+                                                PRINT_TIME | PRINT_CYCLE));
             }
         }
       break;      
index ec7a46de50692de1a70cde7f5e9e05e2a15d0e68..655a6dbe0d144ff955c459bddbd212d6f1fc2683 100644 (file)
@@ -463,7 +463,8 @@ m68hc11sio_info (struct hw *me)
       n = (clock_cycle - t) / controller->baud_cycle;
       n = controller->data_length - n;
       sim_io_printf (sd, "  Transmit finished in %s (%d bit%s)\n",
-                    cycle_to_string (cpu, t), n, (n > 1 ? "s" : ""));
+                    cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE),
+                     n, (n > 1 ? "s" : ""));
     }
   if (controller->rx_poll_event)
     {
@@ -471,7 +472,7 @@ m68hc11sio_info (struct hw *me)
 
       t = hw_event_remain_time (me, controller->rx_poll_event);
       sim_io_printf (sd, "  Receive finished in %s\n",
-                    cycle_to_string (cpu, t));
+                    cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
     }
   
 }
index 5f5e0bbe9cbd54e75e3d0eb56966a87adf2c41e5..619a2d31fcb06764a564a41862445fdce4a5b21a 100644 (file)
@@ -1,6 +1,6 @@
 /*  dv-m68hc11spi.c -- Simulation of the 68HC11 SPI
-    Copyright (C) 2000, 2002 Free Software Foundation, Inc.
-    Written by Stephane Carrez (stcarrez@worldnet.fr)
+    Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
+    Written by Stephane Carrez (stcarrez@nerim.fr)
     (From a driver model Contributed by Cygnus Solutions.)
 
     This file is part of the program GDB, the GNU debugger.
@@ -358,11 +358,11 @@ m68hc11spi_info (struct hw *me)
                      controller->tx_bit + 1);
       t = hw_event_remain_time (me, controller->spi_event);
       sim_io_printf (sd, "  SPI current bit-cycle finished in %s\n",
-                    cycle_to_string (cpu, t));
+                    cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
 
       t += (controller->tx_bit + 1) * 2 * controller->clock;
       sim_io_printf (sd, "  SPI operation finished in %s\n",
-                    cycle_to_string (cpu, t));
+                    cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
     }
 }
 
index b0ff2c35faff8410444a611fee408746405a1fdc..0456f67891271e0b342f21ec8c4bc57e96efb97e 100644 (file)
@@ -25,7 +25,7 @@
 #include "sim-main.h"
 #include "hw-main.h"
 #include "sim-assert.h"
-
+#include <limits.h>
 
 /* DEVICE
 
@@ -250,7 +250,9 @@ m68hc11tim_timer_event (struct hw *me, void *data)
   unsigned mask;
   unsigned flags;
   unsigned long tcnt_internal;
-  unsigned long tcnt;
+  unsigned long tcnt, tcnt_prev;
+  signed64 tcnt_insn_end;
+  signed64 tcnt_insn_start;
   int i;
   sim_events *events;
   
@@ -289,11 +291,8 @@ m68hc11tim_timer_event (struct hw *me, void *data)
       break;
 
     case OVERFLOW_EVENT:
-      /* Compute the 68HC11 internal free running counter.
-         There may be 'nr_ticks_to_process' pending cycles that are
-         not (yet) taken into account by 'sim_events_time'.  */
-      tcnt_internal = sim_events_time (sd) - controller->tcnt_adjust;
-      tcnt_internal += events->nr_ticks_to_process;
+      /* Compute the 68HC11 internal free running counter.  */
+      tcnt_internal = (cpu->cpu_absolute_cycle - controller->tcnt_adjust);
 
       /* We must take into account the prescaler that comes
          before the counter (it's a power of 2).  */
@@ -316,22 +315,22 @@ m68hc11tim_timer_event (struct hw *me, void *data)
       break;
 
     case COMPARE_EVENT:
-      eventp = &controller->cmp_timer_event;
+      /* Compute value of TCNT register (64-bit precision) at beginning
+         and end of instruction.  */
+      tcnt_insn_end = (cpu->cpu_absolute_cycle - controller->tcnt_adjust);
+      tcnt_insn_start = (tcnt_insn_end - cpu->cpu_current_cycle);
+
+      /* TCNT value at beginning of current instruction.  */
+      tcnt_prev = (tcnt_insn_start / controller->clock_prescaler) & 0x0ffff;
 
-      /* Compute the 68HC11 internal free running counter.
-         There may be 'nr_ticks_to_process' pending cycles that are
-         not (yet) taken into account by 'sim_events_time'.  */
-      events = STATE_EVENTS (sd);
-      tcnt_internal = sim_events_time (sd) - controller->tcnt_adjust;
-      tcnt_internal += events->nr_ticks_to_process;
+      /* TCNT value at end of current instruction.  */
+      tcnt = (tcnt_insn_end / controller->clock_prescaler) & 0x0ffff;
 
       /* We must take into account the prescaler that comes
          before the counter (it's a power of 2).  */
+      tcnt_internal = tcnt_insn_end;
       tcnt_internal &= 0x0ffff * controller->clock_prescaler;
 
-      /* Get current visible TCNT register value.  */
-      tcnt = tcnt_internal / controller->clock_prescaler;
-      
       flags = cpu->ios[M6811_TMSK1];
       mask  = 0x80;
       delay = 65536 * controller->clock_prescaler;
@@ -342,12 +341,28 @@ m68hc11tim_timer_event (struct hw *me, void *data)
       for (i = M6811_TOC1; i <= M6811_TOC5; i += 2, mask >>= 1)
         {
           unsigned long compare;
-          
-          compare = (cpu->ios[i] << 8) + cpu->ios[i+1];
-          if (compare == tcnt && (flags & mask))
+
+          compare = (cpu->ios[i] << 8) + cpu->ios[i + 1];
+
+          /* See if compare is reached; handle wrap arround.  */
+          if ((compare >= tcnt_prev && compare <= tcnt && tcnt_prev < tcnt)
+              || (compare >= tcnt_prev && tcnt_prev > tcnt)
+              || (compare < tcnt && tcnt_prev > tcnt))
             {
+              unsigned dt;
+
+              if (compare > tcnt)
+                dt = 0x10000 - compare - tcnt;
+              else
+                dt = tcnt - compare;
+
               cpu->ios[M6811_TFLG1] |= mask;
-              check_interrupt++;
+
+              /* Raise interrupt now at the correct CPU cycle so that
+                 we can find the interrupt latency.  */
+              cpu->cpu_absolute_cycle -= dt;
+              interrupts_update_pending (&cpu->cpu_interrupts);
+              cpu->cpu_absolute_cycle += dt;
             }
 
           /* Compute how many times for the next match.
@@ -359,14 +374,18 @@ m68hc11tim_timer_event (struct hw *me, void *data)
           else
             compare = compare - tcnt_internal
               + 65536 * controller->clock_prescaler;
-          
+
           if (compare < delay)
             delay = compare;
         }
 
       /* Deactivate the compare timer if no output compare is enabled.  */
-      if ((flags & 0xF0) == 0)
+      if ((flags & 0xF8) == 0)
         delay = 0;
+      else
+        delay += events->nr_ticks_to_process;
+
+      eventp = &controller->cmp_timer_event;
       break;
 
     default:
@@ -457,22 +476,35 @@ to_realtime (sim_cpu *cpu, signed64 t)
 }
 
 const char*
-cycle_to_string (sim_cpu *cpu, signed64 t)
+cycle_to_string (sim_cpu *cpu, signed64 t, int flags)
 {
-  double dt;
-  char tbuf[32];
+  char time_buf[32];
+  char cycle_buf[32];
   static char buf[64];
 
-  dt = to_realtime (cpu, t);
-  if (dt < 0.001)
-    sprintf (tbuf, "(%3.1f us)", dt * 1000000.0);
-  else if (dt < 1.0)
-    sprintf (tbuf, "(%3.1f ms)", dt * 1000.0);
-  else
-    sprintf (tbuf, "(%3.1f s)", dt);
+  time_buf[0] = 0;
+  cycle_buf[0] = 0;
+  if (flags & PRINT_TIME)
+    {
+      double dt;
+
+      dt = to_realtime (cpu, t);
+      if (dt < 0.001)
+        sprintf (time_buf, " (%3.1f us)", dt * 1000000.0);
+      else if (dt < 1.0)
+        sprintf (time_buf, " (%3.1f ms)", dt * 1000.0);
+      else
+        sprintf (time_buf, " (%3.1f s)", dt);
+    }
 
-  sprintf (buf, "%llu cycle%s %10.10s", t,
-             (t > 1 ? "s" : ""), tbuf);
+  if (flags & PRINT_CYCLE)
+    sprintf (cycle_buf, " cycle%s",
+             (t > 1 ? "s" : ""));
+
+  if (t < LONG_MAX)
+    sprintf (buf, "%9lu%s%s", (unsigned long) t, cycle_buf, time_buf);
+  else
+    sprintf (buf, "%llu%s%s", t, cycle_buf, time_buf);
   return buf;
 }
 
@@ -496,7 +528,7 @@ m68hc11tim_print_timer (struct hw *me, const char *name,
 
       t  = hw_event_remain_time (me, event);
       sim_io_printf (sd, "  Next %s interrupt in %s\n",
-                     name, cycle_to_string (cpu, t));
+                     name, cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
     }
 }
 
@@ -643,7 +675,7 @@ m68hc11tim_io_read_buffer (struct hw *me,
           break;
         }
       *((unsigned8*) dest) = val;
-      dest++;
+      dest = (char*) dest + 1;
       base++;
       nr_bytes--;
       cnt++;
@@ -754,6 +786,7 @@ m68hc11tim_io_write_buffer (struct hw *me,
         case M6811_TMSK1:
           cpu->ios[M6811_TMSK1] = val;
           interrupts_update_pending (&cpu->cpu_interrupts);
+          reset_compare = 1;
           break;
 
         case M6811_TFLG1:
@@ -770,7 +803,7 @@ m68hc11tim_io_write_buffer (struct hw *me,
           cpu->ios[base] = val;
           reset_compare = 1;
           break;
-      
+
         case M6811_TCTL1:
         case M6811_TCTL2:
           cpu->ios[base] = val;
@@ -784,7 +817,7 @@ m68hc11tim_io_write_buffer (struct hw *me,
       base++;
       nr_bytes--;
       cnt++;
-      source++;
+      source = (char*) source + 1;
     }
 
   /* Re-compute the next timer compare event.  */
index 5844c74ea128490bafd138d8ca84eea85717b422..b466d69dac9930b8b809cf419b629c8eb3378dbb 100644 (file)
@@ -1,6 +1,6 @@
 /* interrupts.c -- 68HC11 Interrupts Emulation
-   Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
-   Written by Stephane Carrez (stcarrez@worldnet.fr)
+   Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Written by Stephane Carrez (stcarrez@nerim.fr)
 
 This file is part of GDB, GAS, and the GNU binutils.
 
@@ -166,6 +166,20 @@ interrupts_reset (struct interrupts *interrupts)
 
   memset (interrupts->interrupts, 0,
           sizeof (interrupts->interrupts));
+
+  /* In bootstrap mode, initialize the vector table to point
+     to the RAM location.  */
+  if (interrupts->cpu->cpu_mode == M6811_SMOD)
+    {
+      bfd_vma addr = interrupts->vectors_addr;
+      uint16 vector = 0x0100 - 3 * (M6811_INT_NUMBER - 1);
+      for (i = 0; i < M6811_INT_NUMBER; i++)
+        {
+          memory_write16 (interrupts->cpu, addr, vector);
+          addr += 2;
+          vector += 3;
+        }
+    }
 }
 
 static int
@@ -517,7 +531,7 @@ interrupts_raise (struct interrupts *interrupts, enum M6811_INT number)
 void
 interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
 {
-  signed64 t;
+  signed64 t, prev_interrupt;
   int i;
   
   sim_io_printf (sd, "Interrupts Info:\n");
@@ -533,21 +547,25 @@ interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
         interrupts->max_mask_cycles = t;
 
       sim_io_printf (sd, "  Current interrupts masked sequence:   %s\n",
-                     cycle_to_string (interrupts->cpu, t));
+                     cycle_to_string (interrupts->cpu, t,
+                                      PRINT_TIME | PRINT_CYCLE));
     }
   t = interrupts->min_mask_cycles == CYCLES_MAX ?
     interrupts->max_mask_cycles :
     interrupts->min_mask_cycles;
   sim_io_printf (sd, "  Shortest interrupts masked sequence:  %s\n",
-                 cycle_to_string (interrupts->cpu, t));
+                 cycle_to_string (interrupts->cpu, t,
+                                  PRINT_TIME | PRINT_CYCLE));
 
   t = interrupts->max_mask_cycles;
   sim_io_printf (sd, "  Longest interrupts masked sequence:   %s\n",
-                 cycle_to_string (interrupts->cpu, t));
+                 cycle_to_string (interrupts->cpu, t,
+                                  PRINT_TIME | PRINT_CYCLE));
 
   t = interrupts->last_mask_cycles;
   sim_io_printf (sd, "  Last interrupts masked sequence:      %s\n",
-                 cycle_to_string (interrupts->cpu, t));
+                 cycle_to_string (interrupts->cpu, t,
+                                  PRINT_TIME | PRINT_CYCLE));
   
   if (interrupts->xirq_start_mask_cycle >= 0)
     {
@@ -558,22 +576,26 @@ interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
         interrupts->xirq_max_mask_cycles = t;
 
       sim_io_printf (sd, "  XIRQ Current interrupts masked sequence: %s\n",
-                     cycle_to_string (interrupts->cpu, t));
+                     cycle_to_string (interrupts->cpu, t,
+                                      PRINT_TIME | PRINT_CYCLE));
     }
 
   t = interrupts->xirq_min_mask_cycles == CYCLES_MAX ?
     interrupts->xirq_max_mask_cycles :
     interrupts->xirq_min_mask_cycles;
   sim_io_printf (sd, "  XIRQ Min interrupts masked sequence:  %s\n",
-                 cycle_to_string (interrupts->cpu, t));
+                 cycle_to_string (interrupts->cpu, t,
+                                  PRINT_TIME | PRINT_CYCLE));
 
   t = interrupts->xirq_max_mask_cycles;
   sim_io_printf (sd, "  XIRQ Max interrupts masked sequence:  %s\n",
-                 cycle_to_string (interrupts->cpu, t));
+                 cycle_to_string (interrupts->cpu, t,
+                                  PRINT_TIME | PRINT_CYCLE));
 
   t = interrupts->xirq_last_mask_cycles;
   sim_io_printf (sd, "  XIRQ Last interrupts masked sequence: %s\n",
-                 cycle_to_string (interrupts->cpu, t));
+                 cycle_to_string (interrupts->cpu, t,
+                                  PRINT_TIME | PRINT_CYCLE));
 
   if (interrupts->pending_mask)
     {
@@ -590,6 +612,9 @@ interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
       sim_io_printf (sd, "\n");
     }
 
+  prev_interrupt = 0;
+  sim_io_printf (sd, "N  Interrupt     Cycle Taken         Latency"
+                 "   Delta between interrupts\n");
   for (i = 0; i < MAX_INT_HISTORY; i++)
     {
       int which;
@@ -604,10 +629,18 @@ interrupts_info (SIM_DESC sd, struct interrupts *interrupts)
         break;
 
       dt = h->taken_cycle - h->raised_cycle;
-      sim_io_printf (sd, "%2d %-10.10s %30.30s ", i,
+      sim_io_printf (sd, "%2d %-9.9s %15.15s ", i,
                      interrupt_names[h->type],
-                     cycle_to_string (interrupts->cpu, h->taken_cycle));
-      sim_io_printf (sd, "%s\n",
-                     cycle_to_string (interrupts->cpu, dt));
+                     cycle_to_string (interrupts->cpu, h->taken_cycle, 0));
+      sim_io_printf (sd, "%15.15s",
+                     cycle_to_string (interrupts->cpu, dt, 0));
+      if (prev_interrupt)
+        {
+          dt = prev_interrupt - h->taken_cycle;
+          sim_io_printf (sd, " %s",
+                         cycle_to_string (interrupts->cpu, dt, PRINT_TIME));
+        }
+      sim_io_printf (sd, "\n");
+      prev_interrupt = h->taken_cycle;
     }
 }
index 1daa39c13ea31e91e36b3a7126b7ce9f10da1d04..444147b9492bb1e036d0370c4a0173dbccd1a601 100644 (file)
@@ -27,6 +27,7 @@ enum {
   OPTION_CPU_RESET = OPTION_START,
   OPTION_EMUL_OS,
   OPTION_CPU_CONFIG,
+  OPTION_CPU_BOOTSTRAP,
   OPTION_CPU_MODE
 };
 
@@ -46,6 +47,10 @@ static const OPTION cpu_options[] =
       '\0', NULL, "Specify the initial CPU configuration register",
       cpu_option_handler },
 
+  { {"bootstrap", no_argument, NULL, OPTION_CPU_BOOTSTRAP },
+      '\0', NULL, "Start the processing in bootstrap mode",
+      cpu_option_handler },
+
   { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
 };
 
@@ -77,7 +82,11 @@ cpu_option_handler (SIM_DESC sd, sim_cpu *cpu,
       else
         cpu->cpu_use_local_config = 0;
       break;
-      
+
+    case OPTION_CPU_BOOTSTRAP:
+       cpu->cpu_start_mode = "bootstrap";
+       break;
+
     case OPTION_CPU_MODE:
       break;
     }
@@ -1049,7 +1058,8 @@ cpu_info (SIM_DESC sd, sim_cpu *cpu)
 {
   sim_io_printf (sd, "CPU info:\n");
   sim_io_printf (sd, "  Absolute cycle: %s\n",
-                 cycle_to_string (cpu, cpu->cpu_absolute_cycle));
+                 cycle_to_string (cpu, cpu->cpu_absolute_cycle,
+                                  PRINT_TIME | PRINT_CYCLE));
   
   sim_io_printf (sd, "  Syscall emulation: %s\n",
                  cpu->cpu_emul_syscall ? "yes, via 0xcd <n>" : "no");
index 054933b1bc38ce74e3cc1c84326a0bf2cf106757..a4bd3a62bf892f679c1865c16e09a414a3825a81 100644 (file)
@@ -200,6 +200,7 @@ struct _sim_cpu {
 
   /* The mode in which the CPU is configured (MODA and MODB pins).  */
   unsigned int          cpu_mode;
+  const char*           cpu_start_mode;
 
   /* The cpu being configured.  */
   enum cpu_type         cpu_type;
@@ -591,7 +592,9 @@ extern void sim_set_profile (int n);
 extern void sim_set_profile_size (int n);
 extern void sim_board_reset (SIM_DESC sd);
 
-extern const char *cycle_to_string (sim_cpu *cpu, signed64 t);
+#define PRINT_TIME  0x01
+#define PRINT_CYCLE 0x02
+extern const char *cycle_to_string (sim_cpu *cpu, signed64 t, int flags);
 
 #endif