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

Subversion Repositories openrisc

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

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