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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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