16template <
typename T>
class Alu {
19 std::is_same<T, u32>::value ||
20 std::is_same<T, u16>::value ||
21 std::is_same<T, u8>::value,
22 "Alu only works for u32, u16 and u8");
36 static_assert(std::is_same<T, u32>::value || std::is_same<T, u16>::value ||
37 std::is_same<T, u8>::value,
38 "AddWithCarry only works for u32, u16, and u8");
42 next_bigger_type_t<T>;
45 U unsigned_sum =
static_cast<U
>(x) +
static_cast<U
>(y) +
static_cast<U
>(carry_in);
48 T result =
static_cast<T
>(unsigned_sum);
51 bool carry_out = unsigned_sum > std::numeric_limits<T>::max();
54 bool overflow = (((x ^ result) & (y ^ result)) >> (
sizeof(T) * 8 - 1)) & 1;
60 static constexpr T OR(
const T &x,
const T &y) {
return x | y; }
61 static constexpr T EOR(
const T &x,
const T &y) {
return x ^ y; }
62 static constexpr T AND(
const T &x,
const T &y) {
return x & y; }
63 static T LSR(
const T &x, u32 shift) {
70 static T ASR(
const T &x, i32 shift) {
73 return static_cast<T
>(
static_cast<make_signed_type<T>
>(x) >> shift);
84 using Ts = make_signed_type_t<T>;
86 const Ts extended_x =
static_cast<Ts
>(x);
87 const T result =
static_cast<T
>(extended_x >> shift);
89 const bool carry_out = ((extended_x >> (shift - 1U)) & 0x1U) == 1U;
94 static T LSL(
const T &x, i32 shift) {
109 using U = next_bigger_type_t<T>;
112 const T result =
static_cast<T
>(
115 const bool carry_out =
131 using U = next_bigger_type_t<T>;
132 const U extended_x = (
static_cast<U
>(x) << shift);
136 const bool carry_out =
142 static T ROR(
const T &x, i32 shift) {
146 return ROR_C(x, shift).result;
159 const auto m = shift % N;
160 const T result = LSR(x, m) | LSL(x, N - m);
174 const T carry_in_t = carry_in ?
static_cast<T
>(0x1U) : static_cast<T>(0x0U);
175 const T result = (x >> 1U) | (carry_in_t << (N - 1U));
180 static T RXR(
const T &x,
bool carry_in) {
return RXR_C(x, carry_in).result; }
181 static ImmShiftResults DecodeImmShift(uint8_t type, uint8_t imm5) {
182 switch (type & 0x3U) {
184 return ImmShiftResults{SRType::SRType_LSL, imm5};
188 return ImmShiftResults{SRType::SRType_LSR, 32U};
190 return ImmShiftResults{SRType::SRType_LSR, imm5};
195 return ImmShiftResults{SRType::SRType_ASR, 32U};
197 return ImmShiftResults{SRType::SRType_ASR, imm5};
202 return ImmShiftResults{SRType::SRType_RRX, 1U};
204 return ImmShiftResults{SRType::SRType_ROR, imm5};
212 return ImmShiftResults{SRType::SRType_None, 0U};
214 static T Shift(T value, SRType type, T amount,
bool carry_in) {
215 const auto result = Shift_C(value, type, amount, carry_in);
216 return result.result;
222 static ShiftCRes Shift_C(T value, SRType type, T amount,
bool carry_in) {
228 case SRType::SRType_LSL: {
229 const auto res = LSL_C(value, amount);
230 return ShiftCRes{res.result, res.carry_out};
232 case SRType::SRType_LSR: {
233 const auto res = LSR_C(value, amount);
234 return ShiftCRes{res.result, res.carry_out};
236 case SRType::SRType_ASR: {
237 const auto res = ASR_C(value, amount);
238 return ShiftCRes{res.result, res.carry_out};
240 case SRType::SRType_ROR: {
241 const auto res = ROR_C(value, amount);
242 return ShiftCRes{res.result, res.carry_out};
244 case SRType::SRType_RRX: {
245 const auto res = RXR_C(value, carry_in);
246 return ShiftCRes{res.result, res.carry_out};
273 Alu(
const Alu &r_src) =
delete;
279 Alu &operator=(
const Alu &r_src) =
delete;
285 Alu(Alu &&r_src) =
delete;
291 Alu &operator=(Alu &&r_src) =
delete;