mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Add missing shifts.
This commit is contained in:
parent
4255283e33
commit
09c1b2d7db
@ -26,12 +26,62 @@ void shift(uint32_t &source, uint32_t amount, uint32_t *carry = nullptr) {
|
|||||||
} else if(amount == 32) {
|
} else if(amount == 32) {
|
||||||
if constexpr (set_carry) *carry = source & 1;
|
if constexpr (set_carry) *carry = source & 1;
|
||||||
source = 0;
|
source = 0;
|
||||||
} else {
|
} else if(amount > 0) {
|
||||||
if constexpr (set_carry) *carry = source & (0x8000'0000 >> amount);
|
if constexpr (set_carry) *carry = source & (0x8000'0000 >> (amount - 1));
|
||||||
source <<= amount;
|
source <<= amount;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ShiftType::LogicalRight:
|
||||||
|
if(amount > 32) {
|
||||||
|
if constexpr (set_carry) *carry = 0;
|
||||||
|
source = 0;
|
||||||
|
} else if(amount == 32) {
|
||||||
|
if constexpr (set_carry) *carry = source & 0x8000'0000;
|
||||||
|
source = 0;
|
||||||
|
} else if(amount > 0) {
|
||||||
|
if constexpr (set_carry) *carry = source & (1 << (amount - 1));
|
||||||
|
source >>= amount;
|
||||||
|
} else {
|
||||||
|
// A logical shift right by '0' is treated as a shift by 32;
|
||||||
|
// assemblers are supposed to map LSR #0 to LSL #0.
|
||||||
|
if constexpr (set_carry) *carry = source & 0x8000'0000;
|
||||||
|
source = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ShiftType::ArithmeticRight: {
|
||||||
|
const uint32_t sign = (source & 0x8000'0000) ? 0xffff'ffff : 0x0000'0000;
|
||||||
|
|
||||||
|
if(amount >= 32) {
|
||||||
|
if constexpr (set_carry) *carry = sign;
|
||||||
|
source = sign;
|
||||||
|
} else if(amount > 0) {
|
||||||
|
if constexpr (set_carry) *carry = source & (1 << (amount - 1));
|
||||||
|
source = (source >> amount) | (sign << (32 - amount));
|
||||||
|
} else {
|
||||||
|
// As per logical right, an arithmetic shift of '0' is
|
||||||
|
// treated as a shift by 32.
|
||||||
|
if constexpr (set_carry) *carry = source & 0x8000'0000;
|
||||||
|
source = sign;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case ShiftType::RotateRight: {
|
||||||
|
if(amount == 32) {
|
||||||
|
if constexpr (set_carry) *carry = source & 0x8000'0000;
|
||||||
|
} else if(amount == 0) {
|
||||||
|
// Rotate right by 0 is treated as a rotate right by 1 through carry.
|
||||||
|
const uint32_t high = *carry << 31;
|
||||||
|
if constexpr (set_carry) *carry = source & 1;
|
||||||
|
source = (source >> 1) | high;
|
||||||
|
} else {
|
||||||
|
amount &= 31;
|
||||||
|
if constexpr (set_carry) *carry = source & (1 << (amount - 1));
|
||||||
|
source = (source >> amount) | (source << (32 - amount));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,7 +104,6 @@ void shift(ShiftType type, uint32_t &source, uint32_t amount, uint32_t *carry) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Scheduler {
|
struct Scheduler {
|
||||||
bool should_schedule(Condition condition) {
|
bool should_schedule(Condition condition) {
|
||||||
return status.test(condition);
|
return status.test(condition);
|
||||||
@ -67,7 +116,7 @@ struct Scheduler {
|
|||||||
auto &destination = registers_[fields.destination()];
|
auto &destination = registers_[fields.destination()];
|
||||||
const uint32_t operand1 = registers_[fields.operand1()];
|
const uint32_t operand1 = registers_[fields.operand1()];
|
||||||
uint32_t operand2;
|
uint32_t operand2;
|
||||||
uint32_t rotate_carry = 0;
|
uint32_t rotate_carry = status.c();
|
||||||
|
|
||||||
// Populate carry from the shift only if it'll be used.
|
// Populate carry from the shift only if it'll be used.
|
||||||
constexpr bool shift_sets_carry = is_logical(flags.operation()) && flags.set_condition_codes();
|
constexpr bool shift_sets_carry = is_logical(flags.operation()) && flags.set_condition_codes();
|
||||||
|
Loading…
Reference in New Issue
Block a user