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

Subversion Repositories openrisc

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

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 420 jeremybenn
/*!Trace an instruction
799
 
800
   Supports GDB tracing                                                      */
801
/*---------------------------------------------------------------------------*/
802
void
803
trace_instr ()
804
{
805
  oraddr_t  physical_pc;
806
 
807
  if ((physical_pc = peek_into_itlb (cpu_state.iqueue.insn_addr)))
808
    {
809
      disassemble_instr (physical_pc);
810
    }
811
  else
812
    {
813
      PRINTF ("INTERNAL SIMULATOR ERROR: no trace available\n");
814
    }
815
}       /* trace_instr () */
816
 
817
 
818
/*---------------------------------------------------------------------------*/
819 19 jeremybenn
/*!Wrapper around real decode_execute function
820
 
821
   Some statistics here only
822
 
823
   @param[in] current  Instruction being executed                            */
824
/*---------------------------------------------------------------------------*/
825
static void
826
decode_execute_wrapper (struct iqueue_entry *current)
827
{
828
  breakpoint = 0;
829
 
830
#ifndef HAVE_EXECUTION
831
#error HAVE_EXECUTION has to be defined in order to execute programs.
832
#endif
833
 
834
  /* FIXME: Most of this file is not needed with DYNAMIC_EXECUTION */
835
#if !(DYNAMIC_EXECUTION)
836
  decode_execute (current);
837
#endif
838
 
839
  if (breakpoint)
840
    {
841
      except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
842
    }
843
}       /* decode_execute_wrapper() */
844
 
845
/*---------------------------------------------------------------------------*/
846
/*!Reset the CPU                                                             */
847
/*---------------------------------------------------------------------------*/
848
void
849
cpu_reset ()
850
{
851
  int               i;
852
  struct hist_exec *hist_exec_head = NULL;
853
  struct hist_exec *hist_exec_new;
854
 
855
  runtime.sim.cycles       = 0;
856
  runtime.sim.loadcycles   = 0;
857
  runtime.sim.storecycles  = 0;
858
  runtime.cpu.instructions = 0;
859
  runtime.cpu.supercycles  = 0;
860
  runtime.cpu.hazardwait   = 0;
861
 
862
  for (i = 0; i < MAX_GPRS; i++)
863
    {
864
      setsim_reg (i, 0);
865
    }
866
 
867
  memset (&cpu_state.iqueue,   0, sizeof (cpu_state.iqueue));
868
  memset (&cpu_state.icomplet, 0, sizeof (cpu_state.icomplet));
869
 
870
  sbuf_head        = 0;
871
  sbuf_tail        = 0;
872
  sbuf_count       = 0;
873
  sbuf_prev_cycles = 0;
874
 
875
  /* Initialise execution history circular buffer */
876
  for (i = 0; i < HISTEXEC_LEN; i++)
877
    {
878
      hist_exec_new = malloc (sizeof (struct hist_exec));
879
 
880
      if (!hist_exec_new)
881
        {
882
          fprintf (stderr, "Out-of-memory\n");
883
          exit (1);
884
        }
885
 
886
      if (!hist_exec_head)
887
        {
888
          hist_exec_head = hist_exec_new;
889
        }
890
      else
891
        {
892
          hist_exec_tail->next = hist_exec_new;
893
        }
894
 
895
      hist_exec_new->prev = hist_exec_tail;
896
      hist_exec_tail = hist_exec_new;
897
    }
898
 
899
  /* Make hist_exec_tail->next point to hist_exec_head */
900
  hist_exec_tail->next = hist_exec_head;
901
  hist_exec_head->prev = hist_exec_tail;
902
 
903
  /* MM1409: All progs should start at reset vector entry! This sorted out by
904
     setting the cpu_state.pc field below. Not clear this is very good code! */
905
 
906
  /* Patches suggested by Shinji Wakatsuki, so that the vector address takes
907
     notice of the Exception Prefix High bit of the Supervision register */
908
  pcnext = (cpu_state.sprs[SPR_SR] & SPR_SR_EPH ? 0xf0000000 : 0x00000000);
909
 
910
  if (config.sim.verbose)
911
    {
912
      PRINTF ("Starting at 0x%" PRIxADDR "\n", pcnext);
913
    }
914
 
915
  cpu_state.pc  = pcnext;
916
  pcnext       += 4;
917
 
918
  /* MM1409: All programs should set their stack pointer!  */
919
#if !(DYNAMIC_EXECUTION)
920
  except_handle (EXCEPT_RESET, 0);
921
  update_pc ();
922
#endif
923
 
924
  except_pending = 0;
925
  cpu_state.pc   = cpu_state.sprs[SPR_SR] & SPR_SR_EPH ?
926
    0xf0000000 + EXCEPT_RESET : EXCEPT_RESET;
927
 
928
}       /* cpu_reset() */
929
 
930
 
931
/*---------------------------------------------------------------------------*/
932
/*!Simulates one CPU clock cycle
933
 
934
  @return  non-zero if a breakpoint is hit, zero otherwise.                  */
935
/*---------------------------------------------------------------------------*/
936
int
937
cpu_clock ()
938
{
939
  except_pending  = 0;
940
  next_delay_insn = 0;
941
 
942
  if (fetch ())
943
    {
944
      PRINTF ("Breakpoint hit.\n");
945
      return  1;
946
    }
947
 
948
  if (except_pending)
949
    {
950
      update_pc ();
951
      except_pending = 0;
952
      return  0;
953
    }
954
 
955
  if (breakpoint)
956
    {
957
      except_handle (EXCEPT_TRAP, cpu_state.sprs[SPR_EEAR_BASE]);
958
      update_pc ();
959
      except_pending = 0;
960
      return  0;
961
    }
962
 
963
  decode_execute_wrapper (&cpu_state.iqueue);
964
  update_pc ();
965
  return  0;
966
 
967
}       /* cpu_clock() */
968
 
969
 
970
/*---------------------------------------------------------------------------*/
971
/*!If decoding cannot be found, call this function                           */
972
/*---------------------------------------------------------------------------*/
973
#if SIMPLE_EXECUTION
974
void
975
l_invalid (struct iqueue_entry *current)
976
{
977
#else
978
void
979
l_invalid ()
980
{
981
#endif
982
  except_handle (EXCEPT_ILLEGAL, cpu_state.iqueue.insn_addr);
983
 
984
}       /* l_invalid() */
985
 
986
 
987
/*---------------------------------------------------------------------------*/
988
/*!The main execution loop                                                   */
989
/*---------------------------------------------------------------------------*/
990
void
991
exec_main ()
992
{
993
  long long time_start;
994
 
995
  while (1)
996
    {
997
      time_start = runtime.sim.cycles;
998
      if (config.debug.enabled)
999
        {
1000
          while (runtime.cpu.stalled)
1001
            {
1002
              if (config.debug.rsp_enabled)
1003
                {
1004
                  handle_rsp ();
1005
                }
1006
              else
1007
                {
1008
                  fprintf (stderr, "ERROR: CPU stalled and GDB connection not "
1009
                           "enabled: Invoking CLI and terminating.\n");
1010
                  /* Dump the user into interactive mode.  From there he or
1011
                     she can decide what to do. */
1012
                  handle_sim_command ();
1013
                  sim_done ();
1014
                }
1015
              if (runtime.sim.iprompt)
1016
                handle_sim_command ();
1017
            }
1018
        }
1019
 
1020
      /* Each cycle has counter of mem_cycles; this value is joined with cycles
1021
         at the end of the cycle; no sim originated memory accesses should be
1022
         performed inbetween. */
1023
      runtime.sim.mem_cycles = 0;
1024
 
1025
      if (!config.pm.enabled ||
1026
          !(config.pm.enabled &
1027
            (cpu_state.sprs[SPR_PMR] & (SPR_PMR_DME | SPR_PMR_SME))))
1028
        {
1029
          if (cpu_clock ())
1030
            {
1031
              /* A breakpoint has been hit, drop to interactive mode */
1032
              handle_sim_command ();
1033
            }
1034
        }
1035
 
1036 385 jeremybenn
      /* If we are tracing, dump after each instruction. */
1037
      if (!runtime.sim.hush)
1038
        {
1039 420 jeremybenn
          trace_instr ();
1040 385 jeremybenn
        }
1041
 
1042 19 jeremybenn
      if (config.vapi.enabled && runtime.vapi.enabled)
1043
        {
1044
          vapi_check ();
1045
        }
1046
 
1047
      if (config.debug.enabled)
1048
        {
1049
          if (cpu_state.sprs[SPR_DMR1] & SPR_DMR1_ST)
1050
            {
1051
              set_stall_state (1);
1052
 
1053
              if (config.debug.rsp_enabled)
1054
                {
1055
                  rsp_exception (EXCEPT_TRAP);
1056
                }
1057
            }
1058
        }
1059
 
1060
      runtime.sim.cycles        += runtime.sim.mem_cycles;
1061
      scheduler.job_queue->time -= runtime.sim.cycles - time_start;
1062
 
1063
      if (scheduler.job_queue->time <= 0)
1064
        {
1065
          do_scheduler ();
1066
        }
1067
    }
1068
}       /* exec_main() */
1069
 
1070 226 julius
/*---------------------------------------------------------------------------*/
1071 233 julius
/*!Update the rounding mode variable the softfloat library reads             */
1072 226 julius
/*---------------------------------------------------------------------------*/
1073 230 jeremybenn
static void
1074 233 julius
float_set_rm ()
1075
{
1076
  //
1077
  // float_rounding_mode is used by the softfloat library, it is declared in
1078
  // "softfloat.h"
1079
  //
1080
  switch(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_RM)
1081
    {
1082
    case FPCSR_RM_RN:
1083
      //printf("or1ksim <%s>: rounding mode RN\n",__FUNCTION__);
1084
      float_rounding_mode = float_round_nearest_even;
1085
      break;
1086
    case FPCSR_RM_RZ:
1087
      //printf("or1ksim <%s>: rounding mode RZ\n",__FUNCTION__);
1088
      float_rounding_mode = float_round_to_zero;
1089
      break;
1090
    case FPCSR_RM_RIP:
1091
      //printf("or1ksim <%s>: rounding mode R+\n",__FUNCTION__);
1092
      float_rounding_mode = float_round_up;
1093
      break;
1094
    case FPCSR_RM_RIN:
1095
      //printf("or1ksim <%s>: rounding mode R-\n",__FUNCTION__);
1096
      float_rounding_mode = float_round_down;
1097
      break;
1098
    }
1099
}
1100 226 julius
 
1101
/*---------------------------------------------------------------------------*/
1102 233 julius
/*!Update the OR1K's FPCSR after each floating point instruction             */
1103 226 julius
/*---------------------------------------------------------------------------*/
1104 230 jeremybenn
static void
1105 233 julius
float_set_flags ()
1106
{
1107
  // Get the flags from softfloat's variable and set the OR1K's FPCR values
1108
  // First clear all flags in OR1K FPCSR
1109
  cpu_state.sprs[SPR_FPCSR] &= ~SPR_FPCSR_ALLF;
1110
 
1111
  if (float_exception_flags & float_flag_invalid)
1112
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IVF;
1113
  if (float_exception_flags & float_flag_divbyzero)
1114
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_DZF;
1115
  if (float_exception_flags & float_flag_overflow)
1116
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_OVF;
1117
  if (float_exception_flags & float_flag_underflow)
1118
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_UNF;
1119
  if (float_exception_flags & float_flag_inexact)
1120
    cpu_state.sprs[SPR_FPCSR] |= SPR_FPCSR_IXF;
1121
  /*
1122
  printf("or1ksim: post-fp-op flags from softfloat: %x%x%x%x%x\n",
1123
         !!(float_exception_flags & float_flag_invalid),
1124
         !!(float_exception_flags & float_flag_divbyzero),
1125
         !!(float_exception_flags & float_flag_overflow),
1126
         !!(float_exception_flags & float_flag_underflow),
1127
         !!(float_exception_flags & float_flag_inexact));
1128
  */
1129
  // TODO: Call FP exception is FPEE set and any of the flags were set
1130
  /*
1131 226 julius
     if ((cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_FPEE) &
1132
     (|(cpu_state.sprs[SPR_FPCSR] & SPR_FPCSR_ALLF)))
1133
     except_handle (EXCEPT_FPE, cpu_state.iqueue.insn_addr);
1134 233 julius
  */
1135
  // Now clear softfloat's flags:
1136
  float_exception_flags = 0;
1137
 
1138
}
1139 226 julius
 
1140 19 jeremybenn
#if COMPLEX_EXECUTION
1141
 
1142
/* Include generated/built in decode_execute function */
1143
#include "execgen.c"
1144
 
1145
#elif SIMPLE_EXECUTION
1146
 
1147
 
1148
/*---------------------------------------------------------------------------*/
1149
/*!Evaluates source operand
1150
 
1151
   Implementation specific.
1152
 
1153
   @param[in] op_no       The operand
1154
   @param[in] insn_index  Address of the instruction
1155
   @param[in] insn        The instruction
1156
 
1157
   @return  The value of the operand                                         */
1158
/*---------------------------------------------------------------------------*/
1159
static uorreg_t
1160
eval_operand (int            op_no,
1161
              unsigned long  insn_index,
1162
              uint32_t       insn)
1163
{
1164 230 jeremybenn
  struct insn_op_struct *opd = or1ksim_op_start[insn_index];
1165 19 jeremybenn
  uorreg_t               ret;
1166
 
1167
  while (op_no)
1168
    {
1169
      if (opd->type & OPTYPE_LAST)
1170
        {
1171
          fprintf (stderr,
1172
                   "Instruction requested more operands than it has\n");
1173
          exit (1);
1174
        }
1175
 
1176
      if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
1177
        {
1178
          op_no--;
1179
        }
1180
 
1181
      opd++;
1182
    }
1183
 
1184
  if (opd->type & OPTYPE_DIS)
1185
    {
1186
      ret = eval_operand_val (insn, opd);
1187
 
1188
      while (!(opd->type & OPTYPE_OP))
1189
        {
1190
          opd++;
1191
        }
1192
 
1193
      opd++;
1194
      ret               += evalsim_reg (eval_operand_val (insn, opd));
1195
      cpu_state.insn_ea  = ret;
1196
 
1197
      return  ret;
1198
    }
1199
 
1200
  if (opd->type & OPTYPE_REG)
1201
    {
1202
      return  evalsim_reg (eval_operand_val (insn, opd));
1203
    }
1204
 
1205
  return  eval_operand_val (insn, opd);
1206
 
1207
}       /* eval_operand() */
1208
 
1209
 
1210
/*---------------------------------------------------------------------------*/
1211
/*!Set destination operand (register direct) with value.
1212
 
1213
   Implementation specific.
1214
 
1215
   @param[in] op_no       The operand
1216
   @param[in] value       The value to set
1217
   @param[in] insn_index  Address of the instruction
1218
   @param[in] insn        The instruction                                    */
1219
/*---------------------------------------------------------------------------*/
1220
static void
1221
set_operand (int            op_no,
1222
             orreg_t        value,
1223
             unsigned long  insn_index,
1224
             uint32_t       insn)
1225
{
1226 230 jeremybenn
  struct insn_op_struct *opd = or1ksim_op_start[insn_index];
1227 19 jeremybenn
 
1228
  while (op_no)
1229
    {
1230
      if (opd->type & OPTYPE_LAST)
1231
        {
1232
          fprintf (stderr,
1233
                   "Instruction requested more operands than it has\n");
1234
          exit (1);
1235
        }
1236
 
1237
      if ((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS))
1238
        {
1239
          op_no--;
1240
        }
1241
 
1242
      opd++;
1243
    }
1244
 
1245
  if (!(opd->type & OPTYPE_REG))
1246
    {
1247
      fprintf (stderr, "Trying to set a non-register operand\n");
1248
      exit (1);
1249
    }
1250
 
1251
  setsim_reg (eval_operand_val (insn, opd), value);
1252
 
1253
}       /* set_operand() */
1254
 
1255
 
1256
/*---------------------------------------------------------------------------*/
1257
/*!Simple and rather slow decoding function
1258
 
1259
   Based on built automata.
1260
 
1261
   @param[in] current  The current instruction to execute                    */
1262
/*---------------------------------------------------------------------------*/
1263
static void
1264
decode_execute (struct iqueue_entry *current)
1265
{
1266
  int insn_index;
1267
 
1268 230 jeremybenn
  current->insn_index = insn_index = or1ksim_insn_decode (current->insn);
1269 19 jeremybenn
 
1270
  if (insn_index < 0)
1271
    {
1272
      l_invalid (current);
1273
    }
1274
  else
1275
    {
1276 230 jeremybenn
      or1ksim_or32_opcodes[insn_index].exec (current);
1277 19 jeremybenn
    }
1278
 
1279
  if (do_stats)
1280
    analysis (&cpu_state.iqueue);
1281
}
1282
 
1283
#include "insnset.c"
1284
 
1285
#elif defined(DYNAMIC_EXECUTION)
1286
 
1287
#else
1288
# error "Must define SIMPLE_EXECUTION, COMPLEX_EXECUTION or DYNAMIC_EXECUTION"
1289
#endif

powered by: WebSVN 2.1.0

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