aboutsummaryrefslogtreecommitdiff
path: root/riscv/processor.cc
blob: 5751c70006e2f2dc02d62857ea4bdbf12b14caff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <bfd.h>
#include <dis-asm.h>
#include <cstdlib>
#include <iostream>
#include "processor.h"
#include "common.h"
#include "config.h"
#include "sim.h"

processor_t::processor_t(sim_t* _sim, char* _mem, size_t _memsz)
  : sim(_sim), mmu(_mem,_memsz)
{
  memset(R,0,sizeof(R));
  memset(FR,0,sizeof(FR));
  pc = 0;
  ebase = 0;
  epc = 0;
  badvaddr = 0;
  set_sr(SR_S);

  memset(counters,0,sizeof(counters));

  // a few assumptions about endianness, including freg_t union
  static_assert(BYTE_ORDER == LITTLE_ENDIAN);
  static_assert(sizeof(freg_t) == 8);
  static_assert(sizeof(reg_t) == 8);

  static_assert(sizeof(insn_t) == 4);
  static_assert(sizeof(uint128_t) == 16 && sizeof(int128_t) == 16);
}

void processor_t::init(uint32_t _id)
{
  id = _id;
}

void processor_t::set_sr(uint32_t val)
{
  sr = val & ~SR_ZERO;
  if(support_64bit)
    sr |= SR_KX;
  else
    sr &= ~(SR_KX | SR_UX);

  gprlen = ((sr & SR_S) ? (sr & SR_KX) : (sr & SR_UX)) ? 64 : 32;
}

void processor_t::step(size_t n, bool noisy)
{
  size_t i = 0;
  while(1) try
  {
    for( ; i < n; i++)
    {
      insn_t insn = mmu.load_insn(pc);
  
      reg_t npc = pc+sizeof(insn);

      if(noisy)
        disasm(insn,pc);

      #include "execute.h"
  
      pc = npc;
      R[0] = 0;

      counters[0]++;
    }
    return;
  }
  catch(trap_t t)
  {
    i++;
    take_trap(t);
  }
}

void processor_t::take_trap(trap_t t)
{
  demand(t < NUM_TRAPS, "internal error: bad trap number %d", int(t));
  demand(sr & SR_ET, "error mode on core %d!\ntrap %s, pc 0x%016llx",
         id, trap_name(t), (unsigned long long)pc);

  set_sr((((sr & ~SR_ET) | SR_S) & ~SR_PS) | ((sr & SR_S) ? SR_PS : 0));
  epc = pc;
  pc = ebase + t*128;
  badvaddr = mmu.get_badvaddr();
}

void processor_t::disasm(insn_t insn, reg_t pc)
{
  printf("core %3d: 0x%016llx (0x%08x) ",id,(unsigned long long)pc,insn.bits);

  #ifdef RISCV_HAVE_LIBOPCODES
  disassemble_info info;
  INIT_DISASSEMBLE_INFO(info, stdout, fprintf);
  info.flavour = bfd_target_unknown_flavour;
  info.arch = bfd_arch_mips;
  info.mach = 101; // XXX bfd_mach_mips_riscv requires modified bfd.h
  info.endian = BFD_ENDIAN_LITTLE;
  info.buffer = (bfd_byte*)&insn;
  info.buffer_length = sizeof(insn);
  info.buffer_vma = pc;

  demand(print_insn_little_mips(pc, &info) == sizeof(insn), "disasm bug!");
  #else
  printf("unknown");
  #endif
  printf("\n");
}