mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-14 04:31:19 +00:00
Implement SAL, SAR.
This commit is contained in:
parent
f1cba4eb78
commit
e38fe7dffc
@ -1114,6 +1114,109 @@ inline void ror(IntT &destination, uint8_t count, Status &status) {
|
|||||||
(destination ^ (destination << 1)) & Numeric::top_bit<IntT>()
|
(destination ^ (destination << 1)) & Numeric::top_bit<IntT>()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
tempCOUNT ← (COUNT AND 1FH);
|
||||||
|
tempDEST ← DEST;
|
||||||
|
WHILE (tempCOUNT ≠ 0)
|
||||||
|
DO
|
||||||
|
IF instruction is SAL or SHL
|
||||||
|
THEN
|
||||||
|
CF ← MSB(DEST);
|
||||||
|
ELSE (* instruction is SAR or SHR *)
|
||||||
|
CF ← LSB(DEST);
|
||||||
|
FI;
|
||||||
|
IF instruction is SAL or SHL
|
||||||
|
THEN
|
||||||
|
DEST ← DEST ∗ 2;
|
||||||
|
ELSE
|
||||||
|
IF instruction is SAR
|
||||||
|
THEN
|
||||||
|
DEST ← DEST / 2 (*Signed divide, rounding toward negative infinity*);
|
||||||
|
ELSE (* instruction is SHR *)
|
||||||
|
DEST ← DEST / 2 ; (* Unsigned divide *);
|
||||||
|
FI;
|
||||||
|
FI;
|
||||||
|
tempCOUNT ← tempCOUNT – 1;
|
||||||
|
OD;
|
||||||
|
(* Determine overflow for the various instructions *)
|
||||||
|
IF COUNT = 1
|
||||||
|
THEN
|
||||||
|
IF instruction is SAL or SHL
|
||||||
|
THEN
|
||||||
|
OF ← MSB(DEST) XOR CF;
|
||||||
|
ELSE
|
||||||
|
IF instruction is SAR
|
||||||
|
THEN
|
||||||
|
OF ← 0;
|
||||||
|
ELSE (* instruction is SHR *)
|
||||||
|
OF ← MSB(tempDEST);
|
||||||
|
FI;
|
||||||
|
FI;
|
||||||
|
ELSE
|
||||||
|
IF COUNT = 0
|
||||||
|
THEN
|
||||||
|
All flags remain unchanged;
|
||||||
|
ELSE (* COUNT neither 1 or 0 *)
|
||||||
|
OF ← undefined;
|
||||||
|
FI;
|
||||||
|
FI;
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
The CF flag contains the value of the last bit shifted out of the destination operand;
|
||||||
|
it is undefined for SHL and SHR instructions where the count is greater than or equal to
|
||||||
|
the size (in bits) of the destination operand. The OF flag is affected only for 1-bit shifts
|
||||||
|
(see “Description” above); otherwise, it is undefined.
|
||||||
|
|
||||||
|
The SF, ZF, and PF flags are set according to the result. If the count is 0, the flags are not affected.
|
||||||
|
For a non-zero count, the AF flag is undefined.
|
||||||
|
*/
|
||||||
|
template <typename IntT>
|
||||||
|
inline void sal(IntT &destination, uint8_t count, Status &status) {
|
||||||
|
switch(count) {
|
||||||
|
case 0: return;
|
||||||
|
case Numeric::bit_size<IntT>():
|
||||||
|
status.set_from<Flag::Carry, Flag::Overflow>(destination & 1);
|
||||||
|
destination = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if(count > Numeric::bit_size<IntT>()) {
|
||||||
|
status.set_from<Flag::Carry, Flag::Overflow>(0);
|
||||||
|
destination = 0;
|
||||||
|
} else {
|
||||||
|
const auto mask = (Numeric::top_bit<IntT>() >> (count - 1));
|
||||||
|
status.set_from<Flag::Carry>(
|
||||||
|
destination & mask
|
||||||
|
);
|
||||||
|
status.set_from<Flag::Overflow>(
|
||||||
|
(destination ^ (destination << 1)) & mask
|
||||||
|
);
|
||||||
|
destination <<= count;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
status.set_from<IntT, Flag::Sign, Flag::Zero, Flag::ParityOdd>(destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename IntT>
|
||||||
|
inline void sar(IntT &destination, uint8_t count, Status &status) {
|
||||||
|
if(!count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const IntT sign = Numeric::top_bit<IntT>() & destination;
|
||||||
|
if(count >= Numeric::bit_size<IntT>()) {
|
||||||
|
destination = sign ? IntT(~0) : IntT(0);
|
||||||
|
status.set_from<Flag::Carry>(sign);
|
||||||
|
} else {
|
||||||
|
const IntT mask = 1 << (count - 1);
|
||||||
|
status.set_from<Flag::Carry>(destination & mask);
|
||||||
|
destination = (destination >> count) | (sign ? ~(IntT(~0) >> count) : 0);
|
||||||
|
}
|
||||||
|
status.set_from<Flag::Overflow>(0);
|
||||||
|
status.set_from<IntT, Flag::Sign, Flag::Zero, Flag::ParityOdd>(destination);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
@ -1279,6 +1382,8 @@ template <
|
|||||||
case Operation::RCR: Primitive::rcr(destination(), shift_count(), status); break;
|
case Operation::RCR: Primitive::rcr(destination(), shift_count(), status); break;
|
||||||
case Operation::ROL: Primitive::rol(destination(), shift_count(), status); break;
|
case Operation::ROL: Primitive::rol(destination(), shift_count(), status); break;
|
||||||
case Operation::ROR: Primitive::ror(destination(), shift_count(), status); break;
|
case Operation::ROR: Primitive::ror(destination(), shift_count(), status); break;
|
||||||
|
case Operation::SAL: Primitive::sal(destination(), shift_count(), status); break;
|
||||||
|
case Operation::SAR: Primitive::sar(destination(), shift_count(), status); break;
|
||||||
|
|
||||||
case Operation::CLC: Primitive::clc(status); return;
|
case Operation::CLC: Primitive::clc(status); return;
|
||||||
case Operation::CLD: Primitive::cld(status); return;
|
case Operation::CLD: Primitive::cld(status); return;
|
||||||
|
@ -415,7 +415,6 @@ struct FailedExecution {
|
|||||||
|
|
||||||
// NOP
|
// NOP
|
||||||
@"90.json.gz",
|
@"90.json.gz",
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: POP, POPF, PUSH, PUSHF
|
// TODO: POP, POPF, PUSH, PUSHF
|
||||||
// TODO: SAL, SAR, SHR
|
// TODO: SAL, SAR, SHR
|
||||||
@ -435,6 +434,15 @@ struct FailedExecution {
|
|||||||
// ROR
|
// ROR
|
||||||
@"D0.1.json.gz", @"D2.1.json.gz",
|
@"D0.1.json.gz", @"D2.1.json.gz",
|
||||||
@"D1.1.json.gz", @"D3.1.json.gz",
|
@"D1.1.json.gz", @"D3.1.json.gz",
|
||||||
|
*/
|
||||||
|
|
||||||
|
// SAL
|
||||||
|
// @"D0.4.json.gz", @"D2.4.json.gz",
|
||||||
|
// @"D1.4.json.gz", @"D3.4.json.gz",
|
||||||
|
|
||||||
|
// SAR
|
||||||
|
@"D0.7.json.gz", @"D2.7.json.gz",
|
||||||
|
@"D1.7.json.gz", @"D3.7.json.gz",
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@"F8.json.gz", // CLC
|
@"F8.json.gz", // CLC
|
||||||
|
Loading…
x
Reference in New Issue
Block a user