aboutsummaryrefslogtreecommitdiff
path: root/hwacha/hwacha.cc
blob: b1cf7fc81ce159d67a85f633a335c43af8966939 (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
#include "hwacha.h"
#include "hwacha_xcpt.h"
#include "trap.h"

void ct_state_t::reset()
{
  vl = 0;
  maxvl = 32;
  nxpr = 32;
  nfpr = 32;

  vf_pc = -1;

  cause = 0;
  aux = 0;
}

void ut_state_t::reset()
{
  run = false;
  XPR.reset();
  FPR.reset();
}

void hwacha_t::reset()
{
  ct_state.reset();
  for (int i=0; i<max_uts; i++)
    ut_state[i].reset();
}

static reg_t custom(processor_t* p, insn_t insn, reg_t pc)
{
  hwacha_t* h = static_cast<hwacha_t*>(p->get_extension());
  bool matched = false;
  reg_t npc = -1;

  try
  {
    #define DECLARE_INSN(name, match, mask) \
      extern reg_t hwacha_##name(processor_t*, insn_t, reg_t); \
      if ((insn.bits() & mask) == match) { \
        npc = hwacha_##name(p, insn, pc); \
        matched = true; \
      }
    #include "opcodes_hwacha.h"
    #undef DECLARE_INSN
  }
  catch (trap_instruction_access_fault& t)
  {
    h->take_exception(HWACHA_CAUSE_VF_FAULT_FETCH, h->get_ct_state()->vf_pc);
  }
  catch (trap_load_address_misaligned& t)
  {
    h->take_exception(HWACHA_CAUSE_MISALIGNED_LOAD, t.get_badvaddr());
  }
  catch (trap_store_address_misaligned& t)
  {
    h->take_exception(HWACHA_CAUSE_MISALIGNED_STORE, t.get_badvaddr());
  }
  catch (trap_load_access_fault& t)
  {
    h->take_exception(HWACHA_CAUSE_FAULT_LOAD, t.get_badvaddr());
  }
  catch (trap_store_access_fault& t)
  {
    h->take_exception(HWACHA_CAUSE_FAULT_STORE, t.get_badvaddr());
  }

  if (!matched)
    h->take_exception(HWACHA_CAUSE_ILLEGAL_INSTRUCTION, insn.bits());

  return npc;
}

std::vector<insn_desc_t> hwacha_t::get_instructions()
{
  std::vector<insn_desc_t> insns;
  insns.push_back((insn_desc_t){0x0b, 0x7f, &::illegal_instruction, custom});
  insns.push_back((insn_desc_t){0x2b, 0x7f, &::illegal_instruction, custom});
  insns.push_back((insn_desc_t){0x5b, 0x7f, &::illegal_instruction, custom});
  insns.push_back((insn_desc_t){0x7b, 0x7f, &::illegal_instruction, custom});
  return insns;
}

bool hwacha_t::vf_active()
{
  for (uint32_t i=0; i<get_ct_state()->vl; i++) {
    if (get_ut_state(i)->run)
      return true;
  }
  return false;
}

void hwacha_t::take_exception(reg_t cause, reg_t aux)
{
  get_ct_state()->cause = cause;
  get_ct_state()->aux = aux;
  raise_interrupt();
  if (!(p->get_state()->sr & SR_EI))
    throw std::logic_error("hwacha exception posted, but SR_EI bit not set!");
  throw std::logic_error("hwacha exception posted, but IM[COP] bit not set!");
}