mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-19 23:32:28 +00:00
Implement remaining rolls.
This commit is contained in:
parent
f45d8bcbdb
commit
f1cba4eb78
@ -1021,7 +1021,99 @@ inline void rcr(IntT &destination, uint8_t count, Status &status) {
|
|||||||
status.set_from<Flag::Carry>(carry);
|
status.set_from<Flag::Carry>(carry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename IntT>
|
||||||
|
inline void rol(IntT &destination, uint8_t count, Status &status) {
|
||||||
|
/*
|
||||||
|
(* ROL and ROR instructions *)
|
||||||
|
SIZE ← OperandSize
|
||||||
|
CASE (determine count) OF
|
||||||
|
SIZE = 8: tempCOUNT ← COUNT MOD 8;
|
||||||
|
SIZE = 16: tempCOUNT ← COUNT MOD 16;
|
||||||
|
SIZE = 32: tempCOUNT ← COUNT MOD 32;
|
||||||
|
ESAC;
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
(* ROL instruction operation *)
|
||||||
|
WHILE (tempCOUNT ≠ 0)
|
||||||
|
DO
|
||||||
|
tempCF ← MSB(DEST);
|
||||||
|
DEST ← (DEST * 2) + tempCF;
|
||||||
|
tempCOUNT ← tempCOUNT – 1;
|
||||||
|
OD;
|
||||||
|
ELIHW;
|
||||||
|
IF COUNT = 1
|
||||||
|
THEN OF ← MSB(DEST) XOR CF;
|
||||||
|
ELSE OF is undefined;
|
||||||
|
FI;
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
The CF flag contains the value of the bit shifted into it.
|
||||||
|
The OF flag is affected only for single- bit rotates (see “Description” above);
|
||||||
|
it is undefined for multi-bit rotates. The SF, ZF, AF, and PF flags are not affected.
|
||||||
|
*/
|
||||||
|
const auto temp_count = count & (Numeric::bit_size<IntT>() - 1);
|
||||||
|
if(!count) {
|
||||||
|
// TODO: is this 8086-specific? i.e. do the other x86s also exit without affecting flags when temp_count = 0?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(temp_count) {
|
||||||
|
destination =
|
||||||
|
(destination << temp_count) |
|
||||||
|
(destination >> (Numeric::bit_size<IntT>() - temp_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
status.set_from<Flag::Carry>(destination & 1);
|
||||||
|
status.set_from<Flag::Overflow>(
|
||||||
|
((destination >> (Numeric::bit_size<IntT>() - 1)) ^ destination) & 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename IntT>
|
||||||
|
inline void ror(IntT &destination, uint8_t count, Status &status) {
|
||||||
|
/*
|
||||||
|
(* ROL and ROR instructions *)
|
||||||
|
SIZE ← OperandSize
|
||||||
|
CASE (determine count) OF
|
||||||
|
SIZE = 8: tempCOUNT ← COUNT MOD 8;
|
||||||
|
SIZE = 16: tempCOUNT ← COUNT MOD 16;
|
||||||
|
SIZE = 32: tempCOUNT ← COUNT MOD 32;
|
||||||
|
ESAC;
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
(* ROR instruction operation *)
|
||||||
|
WHILE (tempCOUNT ≠ 0)
|
||||||
|
DO
|
||||||
|
tempCF ← LSB(DEST);
|
||||||
|
DEST ← (DEST / 2) + (tempCF * 2^SIZE);
|
||||||
|
tempCOUNT ← tempCOUNT – 1;
|
||||||
|
OD;
|
||||||
|
ELIHW;
|
||||||
|
IF COUNT = 1
|
||||||
|
THEN OF ← MSB(DEST) XOR MSB - 1 (DEST);
|
||||||
|
ELSE OF is undefined;
|
||||||
|
FI;
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
The CF flag contains the value of the bit shifted into it.
|
||||||
|
The OF flag is affected only for single- bit rotates (see “Description” above);
|
||||||
|
it is undefined for multi-bit rotates. The SF, ZF, AF, and PF flags are not affected.
|
||||||
|
*/
|
||||||
|
const auto temp_count = count & (Numeric::bit_size<IntT>() - 1);
|
||||||
|
if(!count) {
|
||||||
|
// TODO: is this 8086-specific? i.e. do the other x86s also exit without affecting flags when temp_count = 0?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(temp_count) {
|
||||||
|
destination =
|
||||||
|
(destination >> temp_count) |
|
||||||
|
(destination << (Numeric::bit_size<IntT>() - temp_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
status.set_from<Flag::Carry>(destination & Numeric::top_bit<IntT>());
|
||||||
|
status.set_from<Flag::Overflow>(
|
||||||
|
(destination ^ (destination << 1)) & Numeric::top_bit<IntT>()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
@ -1185,6 +1277,8 @@ template <
|
|||||||
|
|
||||||
case Operation::RCL: Primitive::rcl(destination(), shift_count(), status); break;
|
case Operation::RCL: Primitive::rcl(destination(), shift_count(), status); break;
|
||||||
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::ROR: Primitive::ror(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;
|
||||||
|
@ -418,16 +418,24 @@ struct FailedExecution {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: POP, POPF, PUSH, PUSHF
|
// TODO: POP, POPF, PUSH, PUSHF
|
||||||
// TODO: ROL, ROR, SAL, SAR, SHR
|
// TODO: SAL, SAR, SHR
|
||||||
|
|
||||||
// RCL
|
// RCL
|
||||||
// @"D0.2.json.gz", @"D2.2.json.gz",
|
@"D0.2.json.gz", @"D2.2.json.gz",
|
||||||
// @"D1.2.json.gz", @"D3.2.json.gz",
|
@"D1.2.json.gz", @"D3.2.json.gz",
|
||||||
|
|
||||||
// RCR
|
// RCR
|
||||||
@"D0.3.json.gz", @"D2.3.json.gz",
|
@"D0.3.json.gz", @"D2.3.json.gz",
|
||||||
@"D1.3.json.gz", @"D3.3.json.gz",
|
@"D1.3.json.gz", @"D3.3.json.gz",
|
||||||
|
|
||||||
|
// ROL
|
||||||
|
@"D0.0.json.gz", @"D2.0.json.gz",
|
||||||
|
@"D1.0.json.gz", @"D3.0.json.gz",
|
||||||
|
|
||||||
|
// ROR
|
||||||
|
@"D0.1.json.gz", @"D2.1.json.gz",
|
||||||
|
@"D1.1.json.gz", @"D3.1.json.gz",
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@"F8.json.gz", // CLC
|
@"F8.json.gz", // CLC
|
||||||
@"FC.json.gz", // CLD
|
@"FC.json.gz", // CLD
|
||||||
@ -636,6 +644,10 @@ struct FailedExecution {
|
|||||||
execution_support.status = initial_status;
|
execution_support.status = initial_status;
|
||||||
execution_support.registers = initial_registers;
|
execution_support.registers = initial_registers;
|
||||||
|
|
||||||
|
if([test[@"name"] isEqual:@"rol byte ss:[bp+si+CF11h], cl"]) {
|
||||||
|
printf("");
|
||||||
|
}
|
||||||
|
|
||||||
// Execute instruction.
|
// Execute instruction.
|
||||||
execution_support.registers.ip_ += decoded.first;
|
execution_support.registers.ip_ += decoded.first;
|
||||||
InstructionSet::x86::perform<InstructionSet::x86::Model::i8086>(
|
InstructionSet::x86::perform<InstructionSet::x86::Model::i8086>(
|
||||||
|
Loading…
Reference in New Issue
Block a user