OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [cpu/] [or32/] [execute.c] - Blame information for rev 233

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jeremybenn
/* execute.c -- OR1K architecture dependent simulation
2
 
3
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
5
   Copyright (C) 2008 Embecosm Limited
6 233 julius
   Copyright (C) 2010 ORSoC AB
7 19 jeremybenn
 
8
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
9 233 julius
   Contributor Julius Baxter <julius.baxter@orsoc.se>
10 19 jeremybenn
 
11
   This file is part of OpenRISC 1000 Architectural Simulator.
12
 
13
   This program is free software; you can redistribute it and/or modify it
14
   under the terms of the GNU General Public License as published by the Free
15
   Software Foundation; either version 3 of the License, or (at your option)
16
   any later version.
17
 
18
   This program is distributed in the hope that it will be useful, but WITHOUT
19
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
21
   more details.
22
 
23
   You should have received a copy of the GNU General Public License along
24
   with this program.  If not, see <http://www.gnu.org/licenses/>. */
25
 
26
/* This program is commented throughout in a fashion suitable for processing
27
   with Doxygen. */
28
 
29
 
30
/* Most of the OR1K simulation is done in here.
31
 
32
   When SIMPLE_EXECUTION is defined below a file insnset.c is included!
33
*/
34
 
35
/* Autoconf and/or portability configuration */
36
#include "config.h"
37
#include "port.h"
38
 
39
/* System includes */
40
#include <stdlib.h>
41
 
42
/* Package includes */
43
#include "execute.h"
44
#include "toplevel-support.h"
45
#include "except.h"
46
#include "labels.h"
47
#include "gdbcomm.h"
48
#include "sched.h"
49
#include "stats.h"
50
#include "opcode/or32.h"
51
#include "dmmu.h"
52
#include "immu.h"
53
#include "sim-cmd.h"
54
#include "vapi.h"
55
#include "debug-unit.h"
56
#include "branch-predict.h"
57
#include "sprs.h"
58
#include "rsp-server.h"
59 233 julius
#include "softfloat.h"
60 19 jeremybenn
 
61
/* Includes and macros for simple execution */
62
#if SIMPLE_EXECUTION
63
 
64
#define SET_PARAM0(val) set_operand(0, val, current->insn_index, current->insn)
65
 
66
#define PARAM0 eval_operand(0, current->insn_index, current->insn)
67
#define PARAM1 eval_operand(1, current->insn_index, current->insn)
68
#define PARAM2 eval_operand(2, current->insn_index, current->insn)
69
 
70
#define INSTRUCTION(name) void name (struct iqueue_entry *current)
71
 
72
#endif  /* SIMPLE_EXECUTION */
73
 
74
 
75
/*! Current cpu state. Globally available. */
76
struct cpu_state  cpu_state;
77
 
78
/*! Temporary program counter. Globally available */
79
oraddr_t  pcnext;
80
 
81
/*! Num cycles waiting for stores to complete. Globally available */
82
int  sbuf_wait_cyc = 0;
83
 
84
/*! Number of total store cycles. Globally available */
85
int  sbuf_total_cyc = 0;
86
 
87
/*! Whether we are doing statistical analysis. Globally available */
88
int  do_stats = 0;
89
 
90
/*! History of execution. Globally available */
91
struct hist_exec *hist_exec_tail = NULL;
92
 
93
/* Benchmark multi issue execution. This file only */
94
static int  multissue[20];
95
static int  issued_per_cycle = 4;
96
 
97
/* Store buffer analysis - stores are accumulated and commited when IO is
98
   idle. This file only */
99
static int  sbuf_head              = 0;
100
static int  sbuf_tail              = 0;
101
static int  sbuf_count             = 0;
102
#if !(DYNAMIC_EXECUTION)
103
static int  sbuf_buf[MAX_SBUF_LEN] = { 0 };
104
#endif
105
 
106
static int sbuf_prev_cycles = 0;
107
 
108
/* Variables used throughout this file to share information */
109
static int  breakpoint;
110
static int  next_delay_insn;
111
 
112
/* Forward declaration of static functions */
113
#if !(DYNAMIC_EXECUTION)
114
static void decode_execute (struct iqueue_entry *current);
115
#endif
116
 
117
/*---------------------------------------------------------------------------*/
118
/*!Get an actual value of a specific register
119
 
120
   Implementation specific. Abort if we are given a duff register. Only used
121 82 jeremybenn
   externally to support simprintf(), which is now obsolete.
122 19 jeremybenn
 
123
   @param[in] regno  The register of interest
124
 
125
   @return  The value of the register                                        */
126
/*---------------------------------------------------------------------------*/
127
uorreg_t
128
evalsim_reg (unsigned int  regno)
129
{
130
  if (regno < MAX_GPRS)
131
    {
132
#if RAW_RANGE_STATS
133
      int delta = (runtime.sim.cycles - raw_stats.reg[regno]);
134
 
135
      if ((unsigned long) delta < (unsigned long) RAW_RANGE)
136
        {
137
          raw_stats.range[delta]++;
138
        }
139
#endif /* RAW_RANGE */
140
 
141
      return cpu_state.reg[regno];
142
    }
143
  else
144
    {
145
      PRINTF ("\nABORT: read out of registers\n");
146
      sim_done ();
147
      return 0;
148
    }
149
}       /* evalsim_reg() */
150
 
151
 
152
/*---------------------------------------------------------------------------*/
153
/*!Set a specific register with value
154
 
155
   Implementation specific. Abort if we are given a duff register.
156
 
157
   @param[in] regno  The register of interest
158
   @param[in] value  The value to be set                                     */
159
/*---------------------------------------------------------------------------*/
160
void
161
setsim_reg (unsigned int  regno,
162
            uorreg_t      value)
163
{
164
  if (regno == 0)                /* gpr0 is always zero */
165
    {
166
      value = 0;
167
    }
168
 
169
  if (regno < MAX_GPRS)
170
    {
171
      cpu_state.reg[regno] = value;
172
    }
173
  else
174
    {
175
      PRINTF ("\nABORT: write out of registers\n");
176
      sim_done ();
177
    }
178
 
179
#if RAW_RANGE_STATS
180
  raw_stats.reg[regno] = runtime.sim.cycles;
181
#endif /* RAW_RANGE */
182
 
183
}       /* setsim_reg() */
184
 
185
 
186
/*---------------------------------------------------------------------------*/
187
/*!Evaluates source operand operand
188
 
189
   Implementation specific. Declared global, although this is only actually
190
   required for DYNAMIC_EXECUTION,
191
 
192
   @param[in] insn  The instruction
193
   @param[in] opd   The operand
194
 
195
   @return  The value of the source operand                                  */
196
/*---------------------------------------------------------------------------*/
197
uorreg_t
198
eval_operand_val (uint32_t               insn,
199
                  struct insn_op_struct *opd)
200
{
201
  unsigned long  operand = 0;
202
  unsigned long  sbit;
203
  unsigned int   nbits = 0;
204
 
205
  while (1)
206
    {
207
      operand |=
208
        ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) <<
209
        nbits;
210
      nbits += opd->data;
211
 
212
      if (opd->type & OPTYPE_OP)
213
        {
214
          break;
215
        }
216
 
217
      opd++;
218
    }
219
 
220
  if (opd->type & OPTYPE_SIG)
221
    {
222
      sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
223
 
224
      if (operand & (1 << sbit))
225
        {
226
          operand |= ~REG_C (0) << sbit;
227
        }
228
    }
229
 
230
  return operand;
231
 
232
}       /* eval_operand_val() */
233
 
234
 
235
/*---------------------------------------------------------------------------*/
236
/*!Does source operand depend on computation of dest operand?
237
 
238
      Cycle t                 Cycle t+1
239
  dst: irrelevant         src: immediate                  always 0
240
  dst: reg1 direct        src: reg2 direct                0 if reg1 != reg2
241
  dst: reg1 disp          src: reg2 direct                always 0
242
  dst: reg1 direct        src: reg2 disp                  0 if reg1 != reg2
243
  dst: reg1 disp          src: reg2 disp                  always 1 (store must
244
                                                          finish before load)
245
  dst: flag               src: flag                       always 1
246
 
247
  @param[in] prev  Previous instruction
248
  @param[in] next  Next instruction
249
 
250
  @return  Non-zero if yes.                                                  */
251
/*---------------------------------------------------------------------------*/
252
static int
253
check_depend (struct iqueue_entry *prev,
254
              struct iqueue_entry *next)
255
{
256
  /* Find destination type. */
257
  unsigned long          type = 0;
258
  int                    prev_dis;
259
  int                    next_dis;
260
  orreg_t                prev_reg_val = 0;
261
  struct insn_op_struct *opd;
262
 
263 230 jeremybenn
  if (or1ksim_or32_opcodes[prev->insn_index].flags & OR32_W_FLAG
264
      && or1ksim_or32_opcodes[next->insn_index].flags & OR32_R_FLAG)
265 19 jeremybenn
    {
266
      return  1;
267
    }
268
 
269 230 jeremybenn
  opd      = or1ksim_op_start[prev->insn_index];
270 19 jeremybenn
  prev_dis = 0;
271
 
272
  while (1)
273
    {
274
      if (opd->type & OPTYPE_DIS)
275
        {
276
          prev_dis = 1;
277
        }
278
 
279
      if (opd->type & OPTYPE_DST)
280
        {
281
          type = opd->type;
282
 
283
          if (prev_dis)
284
            {
285
              type |= OPTYPE_DIS;
286
            }
287
 
288
          /* Destination is always a register */
289
          prev_reg_val = eval_operand_val (prev->insn, opd);
290
          break;
291
        }
292
 
293
      if (opd->type & OPTYPE_LAST)
294
        {
295
          return 0;              /* Doesn't have a destination operand */
296
        }
297
 
298
      if (opd->type & OPTYPE_OP)
299
        {
300
          prev_dis = 0;
301
        }
302
 
303
      opd++;
304
    }
305
 
306
  /* We search all source operands - if we find confict => return 1 */
307 230 jeremybenn
  opd      = or1ksim_op_start[next->insn_index];
308 19 jeremybenn
  next_dis = 0;
309
 
310
  while (1)
311
    {
312
      if (opd->type & OPTYPE_DIS)
313
        {
314
          next_dis = 1;
315
        }
316
 
317
      /* This instruction sequence also depends on order of execution:
318
           l.lw r1, k(r1)
319
           l.sw k(r1), r4
320
         Here r1 is a destination in l.sw */
321
 
322
      /* FIXME: This situation is not handeld here when r1 == r2:
323
           l.sw k(r1), r4
324
           l.lw r3, k(r2) */
325
      if (!(opd->type & OPTYPE_DST) || (next_dis && (opd->type & OPTYPE_DST)))
326
        {
327
          if (opd->type & OPTYPE_REG)
328
            {
329
              if (eval_operand_val (next->insn, opd) == prev_reg_val)
330
                {
331
                  return 1;
332
                }
333
            }
334
        }
335
 
336
      if (opd->type & OPTYPE_LAST)
337
        {
338
          break;
339
        }
340
 
341
      opd++;
342
    }
343
 
344
  return  0;
345
 
346
}       /* check_depend() */
347
 
348
 
349
/*---------------------------------------------------------------------------*/
350
/*!Should instruction NOT be executed?
351
 
352
   Modified by CZ 26/05/01 for new mode execution.
353
 
354
   @return  Nonzero if instruction should NOT be executed                    */
355
/*---------------------------------------------------------------------------*/
356
static int
357
fetch ()
358
{
359
  static int break_just_hit = 0;
360
 
361
  if (NULL != breakpoints)
362
    {
363
      /* MM: Check for breakpoint.  This has to be done in fetch cycle,
364
         because of peripheria.
365
         MM1709: if we cannot access the memory entry, we could not set the
366
         breakpoint earlier, so just check the breakpoint list.  */
367
      if (has_breakpoint (peek_into_itlb (cpu_state.pc)) && !break_just_hit)
368
        {
369
          break_just_hit = 1;
370
          return 1;             /* Breakpoint set. */
371
        }
372
      break_just_hit = 0;
373
    }
374
 
375
  breakpoint                 = 0;
376
  cpu_state.iqueue.insn_addr = cpu_state.pc;
377
  cpu_state.iqueue.insn      = eval_insn (cpu_state.pc, &breakpoint);
378
 
379
  /* Fetch instruction. */
380
  if (!except_pending)
381
    {
382
      runtime.cpu.instructions++;
383
    }
384
 
385
  /* update_pc will be called after execution */
386
  return 0;
387
 
388
}       /* fetch() */
389
 
390
 
391
/*---------------------------------------------------------------------------*/
392
/*!This code actually updates the PC value                                   */
393
/*---------------------------------------------------------------------------*/
394
static void
395
update_pc ()
396
{
397
  cpu_state.delay_insn    = next_delay_insn;
398
  cpu_state.sprs[SPR_PPC] = cpu_state.pc;       /* Store value for later */
399
  cpu_state.pc            = pcnext;
400
  pcnext                  = cpu_state.delay_insn ? cpu_state.pc_delay :
401
                                                   pcnext + 4;
402
}       /* update_pc() */
403
 
404
 
405
/*---------------------------------------------------------------------------*/
406
/*!Perform analysis of the instruction being executed
407
 
408
   This could be static for SIMPLE_EXECUTION, but made global for general use.
409
 
410
   @param[in] current  The instruction being executed                        */
411
/*---------------------------------------------------------------------------*/
412
void
413
analysis (struct iqueue_entry *current)
414
{
415
  if (config.cpu.dependstats)
416
    {
417
      /* Dynamic, dependency stats. */
418
      adddstats (cpu_state.icomplet.insn_index, current->insn_index, 1,
419
                 check_depend (&cpu_state.icomplet, current));
420
 
421
      /* Dynamic, functional units stats. */
422 230 jeremybenn
      addfstats (or1ksim_or32_opcodes[cpu_state.icomplet.insn_index].func_unit,
423
                 or1ksim_or32_opcodes[current->insn_index].func_unit, 1,
424 19 jeremybenn
                 check_depend (&cpu_state.icomplet, current));
425
 
426
      /* Dynamic, single stats. */
427
      addsstats (current->insn_index, 1);
428
    }
429
 
430
  if (config.cpu.superscalar)
431
    {
432 230 jeremybenn
      if ((or1ksim_or32_opcodes[current->insn_index].func_unit == it_branch) ||
433
          (or1ksim_or32_opcodes[current->insn_index].func_unit == it_jump))
434 19 jeremybenn
        runtime.sim.storecycles += 0;
435
 
436 230 jeremybenn
      if (or1ksim_or32_opcodes[current->insn_index].func_unit == it_store)
437 19 jeremybenn
        runtime.sim.storecycles += 1;
438
 
439 230 jeremybenn
      if (or1ksim_or32_opcodes[current->insn_index].func_unit == it_load)
440 19 jeremybenn
        runtime.sim.loadcycles += 1;
441
 
442
      /* Pseudo multiple issue benchmark */
443 230 jeremybenn
      if ((multissue[or1ksim_or32_opcodes[current->insn_index].func_unit] < 1) ||
444 19 jeremybenn
          (check_depend (&cpu_state.icomplet, current))
445
          || (issued_per_cycle < 1))
446
        {
447
          int i;
448
          for (i = 0; i < 20; i++)
449
            multissue[i] = 2;
450
          issued_per_cycle = 2;
451
          runtime.cpu.supercycles++;
452
          if (check_depend (&cpu_state.icomplet, current))
453
            runtime.cpu.hazardwait++;
454
          multissue[it_unknown] = 2;
455
          multissue[it_shift] = 2;
456
          multissue[it_compare] = 1;
457
          multissue[it_branch] = 1;
458
          multissue[it_jump] = 1;
459
          multissue[it_extend] = 2;
460
          multissue[it_nop] = 2;
461
          multissue[it_move] = 2;
462
          multissue[it_movimm] = 2;
463
          multissue[it_arith] = 2;
464
          multissue[it_store] = 2;
465
          multissue[it_load] = 2;
466
        }
467 230 jeremybenn
      multissue[or1ksim_or32_opcodes[current->insn_index].func_unit]--;
468 19 jeremybenn
      issued_per_cycle--;
469
    }
470
 
471
  if (config.cpu.dependstats)
472
    /* Instruction waits in completition buffer until retired. */
473
    memcpy (&cpu_state.icomplet, current, sizeof (struct iqueue_entry));
474
 
475
  if (config.sim.history)
476
    {
477
      /* History of execution */
478
      hist_exec_tail = hist_exec_tail->next;
479
      hist_exec_tail->addr = cpu_state.icomplet.insn_addr;
480
    }
481
 
482
  if (config.sim.exe_log)
483
    dump_exe_log ();
484
 
485 202 julius
  if (config.sim.exe_bin_insn_log)
486
    dump_exe_bin_insn_log (current);
487
 
488 19 jeremybenn
}       /* analysis() */
489
 
490
 
491
#if !(DYNAMIC_EXECUTION)
492
 
493
/*---------------------------------------------------------------------------*/
494
/*!Store buffer analysis for store instructions
495
 
496
   Stores are accumulated and commited when IO is idle
497
 
498
   @param[in] cyc  Number of cycles being analysed                           */
499
/*---------------------------------------------------------------------------*/
500
static void
501
sbuf_store (int cyc)
502
{
503
  int delta = runtime.sim.cycles - sbuf_prev_cycles;
504
 
505
  sbuf_total_cyc   += cyc;
506
  sbuf_prev_cycles  = runtime.sim.cycles;
507
 
508
  /* Take stores from buffer, that occured meanwhile */
509
  while (sbuf_count && delta >= sbuf_buf[sbuf_tail])
510
    {
511
      delta     -= sbuf_buf[sbuf_tail];
512
      sbuf_tail  = (sbuf_tail + 1) % MAX_SBUF_LEN;
513
      sbuf_count--;
514
    }
515
 
516
  if (sbuf_count)
517
    {
518
      sbuf_buf[sbuf_tail] -= delta;
519
    }
520
 
521
  /* Store buffer is full, take one out */
522
  if (sbuf_count >= config.cpu.sbuf_len)
523
    {
524
      sbuf_wait_cyc          += sbuf_buf[sbuf_tail];
525
      runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
526
      sbuf_prev_cycles       += sbuf_buf[sbuf_tail];
527
      sbuf_tail               = (sbuf_tail + 1) % MAX_SBUF_LEN;
528
      sbuf_count--;
529
    }
530
 
531
  /* Put newest store in the buffer */
532
  sbuf_buf[sbuf_head] = cyc;
533
  sbuf_head           = (sbuf_head + 1) % MAX_SBUF_LEN;
534
  sbuf_count++;
535
 
536
}       /* sbuf_store() */
537
 
538
 
539
/*---------------------------------------------------------------------------*/
540
/*!Store buffer analysis for load instructions
541
 
542
   Previous stores should commit, before any load                            */
543
/*---------------------------------------------------------------------------*/
544
static void
545
sbuf_load ()
546
{
547
  int delta = runtime.sim.cycles - sbuf_prev_cycles;
548
  sbuf_prev_cycles = runtime.sim.cycles;
549
 
550
  /* Take stores from buffer, that occured meanwhile */
551
  while (sbuf_count && delta >= sbuf_buf[sbuf_tail])
552
    {
553
      delta     -= sbuf_buf[sbuf_tail];
554
      sbuf_tail  = (sbuf_tail + 1) % MAX_SBUF_LEN;
555
      sbuf_count--;
556
    }
557
 
558
  if (sbuf_count)
559
    {
560
      sbuf_buf[sbuf_tail] -= delta;
561
    }
562
 
563
  /* Wait for all stores to complete */
564
  while (sbuf_count > 0)
565
    {
566
      sbuf_wait_cyc          += sbuf_buf[sbuf_tail];
567
      runtime.sim.mem_cycles += sbuf_buf[sbuf_tail];
568
      sbuf_prev_cycles       += sbuf_buf[sbuf_tail];
569
      sbuf_tail               = (sbuf_tail + 1) % MAX_SBUF_LEN;
570
      sbuf_count--;
571
    }
572
}       /* sbuf_load() */
573
 
574
#endif  /* !DYNAMIC_EXECUTION */
575
 
576
 
577
/*---------------------------------------------------------------------------*/
578
/*!Outputs dissasembled instruction                                          */
579
/*---------------------------------------------------------------------------*/
580
void
581
dump_exe_log ()
582
{
583
  oraddr_t      insn_addr = cpu_state.iqueue.insn_addr;
584
  unsigned int  i;
585
  unsigned int  j;
586
  uorreg_t      operand;
587
 
588
  if (insn_addr == 0xffffffff)
589
    {
590
      return;
591
    }
592
 
593
  if ((config.sim.exe_log_start <= runtime.cpu.instructions) &&
594
      ((config.sim.exe_log_end <= 0) ||
595
       (runtime.cpu.instructions <= config.sim.exe_log_end)))
596
    {
597
      struct label_entry *entry;
598
 
599
      if (config.sim.exe_log_marker &&
600
          !(runtime.cpu.instructions % config.sim.exe_log_marker))
601
        {
602
          fprintf (runtime.sim.fexe_log,
603
                   "--------------------- %8lli instruction "
604
                   "---------------------\n",
605
                   runtime.cpu.instructions);
606
        }
607
 
608
      switch (config.sim.exe_log_type)
609
        {
610
        case EXE_LOG_HARDWARE:
611
          fprintf (runtime.sim.fexe_log,
612
                   "\nEXECUTED(%11llu): %" PRIxADDR ":  ",
613
                   runtime.cpu.instructions, insn_addr);
614
          fprintf (runtime.sim.fexe_log, "%.2x%.2x",
615
                   eval_direct8 (insn_addr, 0, 0),
616
                   eval_direct8 (insn_addr + 1, 0, 0));
617
          fprintf (runtime.sim.fexe_log, "%.2x%.2x",
618
                   eval_direct8 (insn_addr + 2, 0, 0),
619
                   eval_direct8 (insn_addr + 3, 0, 0));
620
 
621
          for (i = 0; i < MAX_GPRS; i++)
622
            {
623
              if (i % 4 == 0)
624
                {
625
                  fprintf (runtime.sim.fexe_log, "\n");
626
                }
627
 
628
              fprintf (runtime.sim.fexe_log, "GPR%2u: %" PRIxREG "  ", i,
629
                       cpu_state.reg[i]);
630
            }
631
 
632
          fprintf (runtime.sim.fexe_log, "\n");
633
          fprintf (runtime.sim.fexe_log, "SR   : %.8" PRIx32 "  ",
634
                   cpu_state.sprs[SPR_SR]);
635
          fprintf (runtime.sim.fexe_log, "EPCR0: %" PRIxADDR "  ",
636
                   cpu_state.sprs[SPR_EPCR_BASE]);
637
          fprintf (runtime.sim.fexe_log, "EEAR0: %" PRIxADDR "  ",
638
                   cpu_state.sprs[SPR_EEAR_BASE]);
639
          fprintf (runtime.sim.fexe_log, "ESR0 : %.8" PRIx32 "\n",
640
                   cpu_state.sprs[SPR_ESR_BASE]);
641
          break;
642
 
643
        case EXE_LOG_SIMPLE:
644
        case EXE_LOG_SOFTWARE:
645 230 jeremybenn
          or1ksim_disassemble_index (cpu_state.iqueue.insn,
646 19 jeremybenn
                             cpu_state.iqueue.insn_index);
647
 
648
          entry = get_label (insn_addr);
649
          if (entry)
650
            {
651
              fprintf (runtime.sim.fexe_log, "%s:\n", entry->name);
652
            }
653
 
654
          if (config.sim.exe_log_type == EXE_LOG_SOFTWARE)
655
            {
656
              struct insn_op_struct *opd =
657 230 jeremybenn
                or1ksim_op_start[cpu_state.iqueue.insn_index];
658 19 jeremybenn
 
659
              j = 0;
660
              while (1)
661
                {
662
                  operand = eval_operand_val (cpu_state.iqueue.insn, opd);
663
                  while (!(opd->type & OPTYPE_OP))
664
                    {
665
                      opd++;
666
                    }
667
                  if (opd->type & OPTYPE_DIS)
668
                    {
669
                      fprintf (runtime.sim.fexe_log,
670
                               "EA =%" PRIxADDR " PA =%" PRIxADDR " ",
671
                               cpu_state.insn_ea,
672
                               peek_into_dtlb (cpu_state.insn_ea, 0, 0));
673
                      opd++;    /* Skip of register operand */
674
                      j++;
675
                    }
676
                  else if ((opd->type & OPTYPE_REG) && operand)
677
                    {
678
                      fprintf (runtime.sim.fexe_log, "r%-2i=%" PRIxREG " ",
679
                               (int) operand, evalsim_reg (operand));
680
                    }
681
                  else
682
                    {
683
                      fprintf (runtime.sim.fexe_log, "             ");
684
                    }
685
                  j++;
686
                  if (opd->type & OPTYPE_LAST)
687
                    {
688
                      break;
689
                    }
690
                  opd++;
691
                }
692 230 jeremybenn
              if (or1ksim_or32_opcodes[cpu_state.iqueue.insn_index].flags & OR32_R_FLAG)
693 19 jeremybenn
                {
694
                  fprintf (runtime.sim.fexe_log, "SR =%" PRIxREG " ",
695
                           cpu_state.sprs[SPR_SR]);
696
                  j++;
697
                }
698
              while (j < 3)
699
                {
700
                  fprintf (runtime.sim.fexe_log, "             ");
701
                  j++;
702
                }
703
            }
704
          fprintf (runtime.sim.fexe_log, "%" PRIxADDR " ", insn_addr);
705 230 jeremybenn
          fprintf (runtime.sim.fexe_log, "%s\n", or1ksim_disassembled);
706 19 jeremybenn
        }
707
    }
708
}       /* dump_exe_log() */
709
 
710
 
711 202 julius
 
712 19 jeremybenn
/*---------------------------------------------------------------------------*/
713 202 julius
/*!Outputs binary copy of instruction to a file                              */
714
/*---------------------------------------------------------------------------*/
715
void
716
dump_exe_bin_insn_log (struct iqueue_entry *current)
717
{
718
  // Do endian swap before spitting out (will be kept in LE on a LE machine)
719
  // but more useful to see it in big endian format.
720
  // Should probably host htonl().
721
  uint32_t insn = (((current->insn & 0xff)<<24) |
722
                   ((current->insn & 0xff00)<<8) |
723
                   ((current->insn & 0xff0000)>>8) |
724
                   ((current->insn & 0xff000000)>>24));
725
 
726
  //for(i=0;i<4;i++) tmp_insn[i] = eval_direct8 (insn_addr+i, 0, 0);
727
 
728
  // Dump it into binary log file
729
  fwrite((void*)&insn, 4, 1, runtime.sim.fexe_bin_insn_log);
730
 
731
 
732
}       /* dump_exe_bin_insn_log() */
733
 
734
 
735
/*---------------------------------------------------------------------------*/
736 19 jeremybenn
/*!Dump registers
737
 
738
   Supports the CLI 'r' and 't' commands                                     */
739
/*---------------------------------------------------------------------------*/
740
void
741
dumpreg ()
742
{
743
  int       i;
744
  oraddr_t  physical_pc;
745
 
746
  if ((physical_pc = peek_into_itlb (cpu_state.iqueue.insn_addr)))
747
    {
748
      disassemble_memory (physical_pc, physical_pc + 4, 0);
749
    }
750
  else
751
    {
752
      PRINTF ("INTERNAL SIMULATOR ERROR:\n");
753
      PRINTF ("no translation for currently executed instruction\n");
754
    }
755
 
756
  // generate_time_pretty (temp, runtime.sim.cycles * config.sim.clkcycle_ps);
757
  PRINTF (" (executed) [cycle %lld, #%lld]\n", runtime.sim.cycles,
758
          runtime.cpu.instructions);
759
  if (config.cpu.superscalar)
760
    {
761
      PRINTF ("Superscalar CYCLES: %u", runtime.cpu.supercycles);
762
    }
763
  if (config.cpu.hazards)
764
    {
765
      PRINTF ("  HAZARDWAIT: %u\n", runtime.cpu.hazardwait);
766
    }
767
  else if (config.cpu.superscalar)
768
    {
769
      PRINTF ("\n");
770
    }
771
 
772
  if ((physical_pc = peek_into_itlb (cpu_state.pc)))
773
    {
774
      disassemble_memory (physical_pc, physical_pc + 4, 0);
775
    }
776
  else
777
    {
778
      PRINTF ("%" PRIxADDR ": : xxxxxxxx  ITLB miss follows", cpu_state.pc);
779
    }
780
 
781
  PRINTF (" (next insn) %s", (cpu_state.delay_insn ? "(delay insn)" : ""));
782
 
783
  for (i = 0; i < MAX_GPRS; i++)
784
    {
785
      if (i % 4 == 0)
786
        {
787
          PRINTF ("\n");
788
        }
789
 
790
      PRINTF ("GPR%.2u: %" PRIxREG "  ", i, evalsim_reg (i));
791
    }
792
 
793
  PRINTF ("flag: %u\n", cpu_state.sprs[SPR_SR] & SPR_SR_F ? 1 : 0);
794
 
795
}       /* dumpreg() */
796
 
797
 
798
/*---------------------------------------------------------------------------*/
799
/*!Wrapper around real decode_execute function
800
 
801
   Some statistics here only
802
 
803
   @param[in] current  Instruction being executed                            */
804
/*---------------------------------------------------------------------------*/
805
static void
806
decode_execute_wrapper (struct iqueue_entry *current)
807
{
808
  breakpoint = 0;
809
 
810
#ifndef HAVE_EXECUTION
811
#error HAVE_EXECUTION has to be defined in order to execute programs.
812
#endif
813
 
814
  /* FIXME: Most of this file is not needed with DYNAMIC_EXECUTION */
815
#if !(DYNAMIC_EXECUTION)
816
  decode_execute (current);
817
#endif
818
 
819
  if (breakpoint)
820
    {
821
      except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
822
    }
823
}       /* decode_execute_wrapper() */
824
 
825
/*---------------------------------------------------------------------------*/
826
/*!Reset the CPU                                                             */
827
/*---------------------------------------------------------------------------*/
828
void
829
cpu_reset ()
830
{
831
  int               i;
832
  struct hist_exec *hist_exec_head = NULL;
833
  struct hist_exec *hist_exec_new;
834
 
835
  runtime.sim.cycles       = 0;
836
  runtime.sim.loadcycles   = 0;
837
  runtime.sim.storecycles  = 0;
838
  runtime.cpu.instructions = 0;
839
  runtime.cpu.supercycles  = 0;
840
  runtime.cpu.hazardwait   = 0;
841
 
842
  for (i = 0; i < MAX_GPRS; i++)
843
    {
844
      setsim_reg (i, 0);
845
    }
846
 
847
  memset (&cpu_state.iqueue,   0, sizeof (cpu_state.iqueue));
848
  memset (&cpu_state.icomplet, 0, sizeof (cpu_state.icomplet));
849
 
850
  sbuf_head        = 0;
851
  sbuf_tail        = 0;
852
  sbuf_count       = 0;
853
  sbuf_prev_cycles = 0;
854
 
855
  /* Initialise execution history circular buffer */
856
  for (i = 0; i < HISTEXEC_LEN; i++)
857
    {
858
      hist_exec_new = malloc (sizeof (struct hist_exec));
859
 
860
      if (!hist_exec_new)
861
        {
862
          fprintf (stderr, "Out-of-memory\n");
863
          exit (1);
864
        }
865
 
866
      if (!hist_exec_head)
867
        {
868
          hist_exec_head = hist_exec_new;
869
        }
870
      else
871
        {
872
          hist_exec_tail->next = hist_exec_new;
873
        }
874
 
875
      hist_exec_new->prev = hist_exec_tail;
876
      hist_exec_tail = hist_exec_new;
877
    }
878
 
879
  /* Make hist_exec_tail->next point to hist_exec_head */
880
  hist_exec_tail->next = hist_exec_head;
881
  hist_exec_head->prev = hist_exec_tail;
882
 
883
  /* MM1409: All progs should start at reset vector entry! This sorted out by
884
     setting the cpu_state.pc field below. Not clear this is very good code! */
885
 
886
  /* Patches suggested by Shinji Wakatsuki, so that the vector address takes
887
     notice of the Exception Prefix High bit of the Supervision register */
888
  pcnext = (cpu_state.sprs[SPR_SR] & SPR_SR_EPH ? 0xf0000000 : 0x00000000);
889
 
890
  if (config.sim.verbose)
891
    {
892
      PRINTF ("Starting at 0x%" PRIxADDR "\n", pcnext);
893
    }
894
 
895
  cpu_state.pc  = pcnext;
896
  pcnext       += 4;
897
 
898
  /* MM1409: All programs should set their stack pointer!  */
899
#if !(DYNAMIC_EXECUTION)
900
  except_handle (EXCEPT_RESET, 0);
901
  update_pc ();
902
#endif
903
 
904
  except_pending = 0;
905
  cpu_state.pc   = cpu_state.sprs[SPR_SR] & SPR_SR_EPH ?
906
    0xf0000000 + EXCEPT_RESET : EXCEPT_RESET;
907
 
908
}       /* cpu_reset() */
909
 
910
 
911
/*---------------------------------------------------------------------------*/
912
/*!Simulates one CPU clock cycle
913
 
914
  @return  non-zero if a breakpoint is hit, zero otherwise.                  */
915
/*---------------------------------------------------------------------------*/
916
int
917
cpu_clock ()
918
{
919
  except_pending  = 0;
920
  next_delay_insn = 0;
921
 
922
  if (fetch ())
923
    {
924
      PRINTF ("Breakpoint hit.\n");
925
      return  1;
926
    }
927
 
928
  if (except_pending)
929
    {
930
      update_pc ();
931
      except_pending = 0;
932
      return  0;
933
    }
934
 
935
  if (breakpoint)
936
    {
937
      except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
938
      update_pc ();
939
      except_pending = 0;
940
      return  0;
941
    }
942
 
943
  decode_execute_wrapper (&cpu_state.iqueue);
944
  update_pc ();
945
  return  0;
946
 
947
}       /* cpu_clock() */
948
 
949
 
950
/*---------------------------------------------------------------------------*/
951
/*!If decoding cannot be found, call this function                           */
952
/*---------------------------------------------------------------------------*/
953
#if SIMPLE_EXECUTION
954
void
955
l_invalid (struct iqueue_entry *current)
956
{
957
#else
958
void
959
l_invalid ()
960
{
961
#endif
962
  except_handle (EXCEPT_ILLEGAL, cpu_state.iqueue.insn_addr);
963
 
964
}       /* l_invalid() */
965
 
966
 
967
/*---------------------------------------------------------------------------*/
968
/*!The main execution loop                                                   */
969
/*---------------------------------------------------------------------------*/
970
void
971
exec_main ()
972
{
973
  long long time_start;
974
 
975
  while (1)
976
    {
977
      time_start = runtime.sim.cycles;
978
      if (config.debug.enabled)
979
        {
980
          while (runtime.cpu.stalled)
981
            {
982
              if (config.debug.rsp_enabled)
983
                {
984
                  handle_rsp ();
985
                }
986
              else if (config.debug.gdb_enabled)
987
                {
988
                  block_jtag ();
989
                  handle_server_socket (FALSE);
990
                }
991
              else
992
                {
993
                  fprintf (stderr, "ERROR: CPU stalled and GDB connection not "
994
                           "enabled: Invoking CLI and terminating.\n");
995
                  /* Dump the user into interactive mode.  From there he or
996
                     she can decide what to do. */
997
                  handle_sim_command ();
998
                  sim_done ();
999
                }
1000
              if (runtime.sim.iprompt)
1001
                handle_sim_command ();
1002
            }
1003
        }
1004
 
1005
      /* Each cycle has counter of mem_cycles; this value is joined with cycles
1006
         at the end of the cycle; no sim originated memory accesses should be
1007
         performed inbetween. */
1008
      runtime.sim.mem_cycles = 0;
1009
 
1010
      if (!config.pm.enabled ||
1011
          !(config.pm.enabled &
1012
            (cpu_state.sprs[SPR_PMR] & (SPR_PMR_DME | SPR_PMR_SME))))
1013
        {
1014
          if (cpu_clock ())
1015
            {
1016
              /* A breakpoint has been hit, drop to interactive mode */
1017
              handle_sim_command ();
1018
            }
1019
        }
1020
 
1021
      if (config.vapi.enabled && runtime.vapi.enabled)
1022
        {
1023
          vapi_check ();
1024
        }
1025
 
1026
      if (config.debug.gdb_enabled)
1027
        {
1028
          handle_server_socket (FALSE); /* block & check_stdin = false */
1029
        }
1030
 
1031
      if (config.debug.enabled)
1032
        {
1033
          if (cpu_state.sprs[SPR_DMR1] & SPR_DMR1_ST)
1034
            {
1035
              set_stall_state (1);
1036
 
1037
              if (config.debug.rsp_enabled)
1038
                {
1039
                  rsp_exception (EXCEPT_TRAP);
1040
                }
1041
            }
1042
        }
1043
 
1044
      runtime.sim.cycles        += runtime.sim.mem_cycles;
1045
      scheduler.job_queue->time -= runtime.sim.cycles - time_start;
1046
 
1047
      if (scheduler.job_queue->time <= 0)
1048
        {
1049
          do_scheduler ();
1050
        }
1051
    }
1052
}       /* exec_main() */
1053
 
1054 226 julius
/*---------------------------------------------------------------------------*/
1055 233 julius
/*!Update the rounding mode variable the softfloat library reads             */
1056 226 julius
/*---------------------------------------------------------------------------*/
1057 230 jeremybenn
static void
1058 233 julius
float_set_rm ()
1059
{
1060
  //
1061
  // float_rounding_mode is used by the softfloat library, it is declared in
1062
  // "softfloat.h"
1063
  //
1064
  switch(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_RM)
1065
    {
1066
    case FPCSR_RM_RN:
1067
      //printf("or1ksim <%s>: rounding mode RN\n",__FUNCTION__);
1068
      float_rounding_mode = float_round_nearest_even;
1069
      break;
1070
    case FPCSR_RM_RZ:
1071
      //printf("or1ksim <%s>: rounding mode RZ\n",__FUNCTION__);
1072
      float_rounding_mode = float_round_to_zero;
1073
      break;
1074
    case FPCSR_RM_RIP:
1075
      //printf("or1ksim <%s>: rounding mode R+\n",__FUNCTION__);
1076
      float_rounding_mode = float_round_up;
1077
      break;
1078
    case FPCSR_RM_RIN:
1079
      //printf("or1ksim <%s>: rounding mode R-\n",__FUNCTION__);
1080
      float_rounding_mode = float_round_down;
1081
      break;
1082
    }
1083
}
1084 226 julius
 
1085
/*---------------------------------------------------------------------------*/
1086 233 julius
/*!Update the OR1K's FPCSR after each floating point instruction             */
1087 226 julius
/*---------------------------------------------------------------------------*/
1088 230 jeremybenn
static void
1089 233 julius
float_set_flags ()
1090
{
1091
  // Get the flags from softfloat's variable and set the OR1K's FPCR values
1092
  // First clear all flags in OR1K FPCSR
1093
  cpu_state.sprs[SPR_FPCSR] &= ~SPR_FPCSR_ALLF;
1094
 
1095
  if (float_exception_flags & float_flag_invalid)
1096
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IVF;
1097
  if (float_exception_flags & float_flag_divbyzero)
1098
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_DZF;
1099
  if (float_exception_flags & float_flag_overflow)
1100
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_OVF;
1101
  if (float_exception_flags & float_flag_underflow)
1102
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_UNF;
1103
  if (float_exception_flags & float_flag_inexact)
1104
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IXF;
1105
  /*
1106
  printf("or1ksim: post-fp-op flags from softfloat: %x%x%x%x%x\n",
1107
         !!(float_exception_flags & float_flag_invalid),
1108
         !!(float_exception_flags & float_flag_divbyzero),
1109
         !!(float_exception_flags & float_flag_overflow),
1110
         !!(float_exception_flags & float_flag_underflow),
1111
         !!(float_exception_flags & float_flag_inexact));
1112
  */
1113
  // TODO: Call FP exception is FPEE set and any of the flags were set
1114
  /*
1115 226 julius
     if ((cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_FPEE) &
1116
     (|(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_ALLF)))
1117
     except_handle (EXCEPT_FPE, cpu_state.iqueue.insn_addr);
1118 233 julius
  */
1119
  // Now clear softfloat's flags:
1120
  float_exception_flags = 0;
1121
 
1122
}
1123 226 julius
 
1124 19 jeremybenn
#if COMPLEX_EXECUTION
1125
 
1126
/* Include generated/built in decode_execute function */
1127
#include "execgen.c"
1128
 
1129
#elif SIMPLE_EXECUTION
1130
 
1131
 
1132
/*---------------------------------------------------------------------------*/
1133
/*!Evaluates source operand
1134
 
1135
   Implementation specific.
1136
 
1137
   @param[in] op_no       The operand
1138
   @param[in] insn_index  Address of the instruction
1139
   @param[in] insn        The instruction
1140
 
1141
   @return  The value of the operand                                         */
1142
/*---------------------------------------------------------------------------*/
1143
static uorreg_t
1144
eval_operand (int            op_no,
1145
              unsigned long  insn_index,
1146
              uint32_t       insn)
1147
{
1148 230 jeremybenn
  struct insn_op_struct *opd = or1ksim_op_start[insn_index];
1149 19 jeremybenn
  uorreg_t               ret;
1150
 
1151
  while (op_no)
1152
    {
1153
      if (opd->type & OPTYPE_LAST)
1154
        {
1155
          fprintf (stderr,
1156
                   "Instruction requested more operands than it has\n");
1157
          exit (1);
1158
        }
1159
 
1160
      if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
1161
        {
1162
          op_no--;
1163
        }
1164
 
1165
      opd++;
1166
    }
1167
 
1168
  if (opd->type & OPTYPE_DIS)
1169
    {
1170
      ret = eval_operand_val (insn, opd);
1171
 
1172
      while (!(opd->type & OPTYPE_OP))
1173
        {
1174
          opd++;
1175
        }
1176
 
1177
      opd++;
1178
      ret               += evalsim_reg (eval_operand_val (insn, opd));
1179
      cpu_state.insn_ea  = ret;
1180
 
1181
      return  ret;
1182
    }
1183
 
1184
  if (opd->type & OPTYPE_REG)
1185
    {
1186
      return  evalsim_reg (eval_operand_val (insn, opd));
1187
    }
1188
 
1189
  return  eval_operand_val (insn, opd);
1190
 
1191
}       /* eval_operand() */
1192
 
1193
 
1194
/*---------------------------------------------------------------------------*/
1195
/*!Set destination operand (register direct) with value.
1196
 
1197
   Implementation specific.
1198
 
1199
   @param[in] op_no       The operand
1200
   @param[in] value       The value to set
1201
   @param[in] insn_index  Address of the instruction
1202
   @param[in] insn        The instruction                                    */
1203
/*---------------------------------------------------------------------------*/
1204
static void
1205
set_operand (int            op_no,
1206
             orreg_t        value,
1207
             unsigned long  insn_index,
1208
             uint32_t       insn)
1209
{
1210 230 jeremybenn
  struct insn_op_struct *opd = or1ksim_op_start[insn_index];
1211 19 jeremybenn
 
1212
  while (op_no)
1213
    {
1214
      if (opd->type & OPTYPE_LAST)
1215
        {
1216
          fprintf (stderr,
1217
                   "Instruction requested more operands than it has\n");
1218
          exit (1);
1219
        }
1220
 
1221
      if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
1222
        {
1223
          op_no--;
1224
        }
1225
 
1226
      opd++;
1227
    }
1228
 
1229
  if (!(opd->type & OPTYPE_REG))
1230
    {
1231
      fprintf (stderr, "Trying to set a non-register operand\n");
1232
      exit (1);
1233
    }
1234
 
1235
  setsim_reg (eval_operand_val (insn, opd), value);
1236
 
1237
}       /* set_operand() */
1238
 
1239
 
1240
/*---------------------------------------------------------------------------*/
1241
/*!Simple and rather slow decoding function
1242
 
1243
   Based on built automata.
1244
 
1245
   @param[in] current  The current instruction to execute                    */
1246
/*---------------------------------------------------------------------------*/
1247
static void
1248
decode_execute (struct iqueue_entry *current)
1249
{
1250
  int insn_index;
1251
 
1252 230 jeremybenn
  current->insn_index = insn_index = or1ksim_insn_decode (current->insn);
1253 19 jeremybenn
 
1254
  if (insn_index < 0)
1255
    {
1256
      l_invalid (current);
1257
    }
1258
  else
1259
    {
1260 230 jeremybenn
      or1ksim_or32_opcodes[insn_index].exec (current);
1261 19 jeremybenn
    }
1262
 
1263
  if (do_stats)
1264
    analysis (&cpu_state.iqueue);
1265
}
1266
 
1267
#include "insnset.c"
1268
 
1269
#elif defined(DYNAMIC_EXECUTION)
1270
 
1271
#else
1272
# error "Must define SIMPLE_EXECUTION, COMPLEX_EXECUTION or DYNAMIC_EXECUTION"
1273
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.