File: algorithms.cpp

package info (click to toggle)
higan 094-5
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 9,780 kB
  • ctags: 15,643
  • sloc: cpp: 103,963; ansic: 659; makefile: 531; sh: 25
file content (98 lines) | stat: -rwxr-xr-x 3,338 bytes parent folder | download | duplicates (2)
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
bool ARM::condition(uint4 condition) {
  switch(condition) {
  case  0: return cpsr().z == 1;                          //EQ (equal)
  case  1: return cpsr().z == 0;                          //NE (not equal)
  case  2: return cpsr().c == 1;                          //CS (carry set)
  case  3: return cpsr().c == 0;                          //CC (carry clear)
  case  4: return cpsr().n == 1;                          //MI (negative)
  case  5: return cpsr().n == 0;                          //PL (positive)
  case  6: return cpsr().v == 1;                          //VS (overflow)
  case  7: return cpsr().v == 0;                          //VC (no overflow)
  case  8: return cpsr().c == 1 && cpsr().z == 0;         //HI (unsigned higher)
  case  9: return cpsr().c == 0 || cpsr().z == 1;         //LS (unsigned lower or same)
  case 10: return cpsr().n == cpsr().v;                   //GE (signed greater than or equal)
  case 11: return cpsr().n != cpsr().v;                   //LT (signed less than)
  case 12: return cpsr().z == 0 && cpsr().n == cpsr().v;  //GT (signed greater than)
  case 13: return cpsr().z == 1 || cpsr().n != cpsr().v;  //LE (signed less than or equal)
  case 14: return true;                                   //AL (always)
  case 15: return false;                                  //NV (never)
  }
}

uint32 ARM::bit(uint32 result) {
  if(cpsr().t || instruction() & (1 << 20)) {
    cpsr().n = result >> 31;
    cpsr().z = result == 0;
    cpsr().c = carryout();
  }
  return result;
}

uint32 ARM::add(uint32 source, uint32 modify, bool carry) {
  uint32 result = source + modify + carry;
  if(cpsr().t || instruction() & (1 << 20)) {
    uint32 overflow = ~(source ^ modify) & (source ^ result);
    cpsr().n = result >> 31;
    cpsr().z = result == 0;
    cpsr().c = (1u << 31) & (overflow ^ source ^ modify ^ result);
    cpsr().v = (1u << 31) & (overflow);
  }
  return result;
}

uint32 ARM::sub(uint32 source, uint32 modify, bool carry) {
  return add(source, ~modify, carry);
}

uint32 ARM::mul(uint32 product, uint32 multiplicand, uint32 multiplier) {
  product += multiplicand * multiplier;

  if(cpsr().t || instruction() & (1 << 20)) {
    cpsr().n = product >> 31;
    cpsr().z = product == 0;
  }

  return product;
}

uint32 ARM::lsl(uint32 source, uint8 shift) {
  carryout() = cpsr().c;
  if(shift == 0) return source;

  carryout() = shift > 32 ? 0 : source & (1 << 32 - shift);
  source     = shift > 31 ? 0 : source << shift;
  return source;
}

uint32 ARM::lsr(uint32 source, uint8 shift) {
  carryout() = cpsr().c;
  if(shift == 0) return source;

  carryout() = shift > 32 ? 0 : source & (1 << shift - 1);
  source     = shift > 31 ? 0 : source >> shift;
  return source;
}

uint32 ARM::asr(uint32 source, uint8 shift) {
  carryout() = cpsr().c;
  if(shift == 0) return source;

  carryout() = shift > 32 ? source & (1 << 31) : source & (1 << shift - 1);
  source     = shift > 31 ? (int32)source >> 31 : (int32)source >> shift;
  return source;
}

uint32 ARM::ror(uint32 source, uint8 shift) {
  carryout() = cpsr().c;
  if(shift == 0) return source;

  if(shift &= 31)
  source     = source << 32 - shift | source >> shift;
  carryout() = source & (1 << 31);
  return source;
}

uint32 ARM::rrx(uint32 source) {
  carryout() = source & 1;
  return (cpsr().c << 31) | (source >> 1);
}