mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Implement MUL.
This commit is contained in:
parent
e46e42d896
commit
ff6573dd02
@ -474,6 +474,28 @@ void sub(IntT &destination, IntT source, Status &status) {
|
||||
destination = result;
|
||||
}
|
||||
|
||||
template <typename IntT>
|
||||
void mul(IntT &destination_high, IntT &destination_low, IntT source, Status &status) {
|
||||
/*
|
||||
IF byte operation
|
||||
THEN
|
||||
AX ← AL * SRC
|
||||
ELSE (* word or doubleword operation *)
|
||||
IF OperandSize = 16 THEN
|
||||
DX:AX ← AX * SRC
|
||||
ELSE (* OperandSize = 32 *)
|
||||
EDX:EAX ← EAX * SRC
|
||||
FI;
|
||||
*/
|
||||
/*
|
||||
The OF and CF flags are cleared to 0 if the upper half of the result is 0;
|
||||
otherwise, they are set to 1. The SF, ZF, AF, and PF flags are undefined.
|
||||
*/
|
||||
destination_high = (destination_low * source) >> (8 * sizeof(IntT));
|
||||
destination_low *= source;
|
||||
status.overflow = status.carry = destination_high;
|
||||
}
|
||||
|
||||
template <typename IntT>
|
||||
void and_(IntT &destination, IntT source, Status &status) {
|
||||
/*
|
||||
@ -625,7 +647,7 @@ template <
|
||||
case Operation::CWD:
|
||||
if constexpr (data_size == DataSize::Word) {
|
||||
Primitive::cwd(registers.dx(), registers.ax());
|
||||
} else if constexpr (is_32bit(model) && data_size == DataSize::DWord) {
|
||||
} else if constexpr (data_size == DataSize::DWord) {
|
||||
Primitive::cwd(registers.edx(), registers.eax());
|
||||
}
|
||||
return;
|
||||
@ -640,6 +662,15 @@ template <
|
||||
case Operation::ADD: Primitive::add(destination(), source(), status); break;
|
||||
case Operation::SBB: Primitive::sbb(destination(), source(), status); break;
|
||||
case Operation::SUB: Primitive::sub(destination(), source(), status); break;
|
||||
case Operation::MUL:
|
||||
if constexpr (data_size == DataSize::Byte) {
|
||||
Primitive::mul(registers.ah(), registers.al(), source(), status);
|
||||
} else if constexpr (data_size == DataSize::Word) {
|
||||
Primitive::mul(registers.dx(), registers.ax(), source(), status);
|
||||
} else if constexpr (data_size == DataSize::DWord) {
|
||||
Primitive::mul(registers.edx(), registers.eax(), source(), status);
|
||||
}
|
||||
return;
|
||||
|
||||
case Operation::AND: Primitive::and_(destination(), source(), status); break;
|
||||
|
||||
@ -689,7 +720,9 @@ template <
|
||||
perform<model, DataSize::Word>(instruction, status, flow_controller, registers, memory, io);
|
||||
break;
|
||||
case DataSize::DWord:
|
||||
perform<model, DataSize::DWord>(instruction, status, flow_controller, registers, memory, io);
|
||||
if constexpr (is_32bit(model)) {
|
||||
perform<model, DataSize::DWord>(instruction, status, flow_controller, registers, memory, io);
|
||||
}
|
||||
break;
|
||||
case DataSize::None:
|
||||
perform<model, DataSize::None>(instruction, status, flow_controller, registers, memory, io);
|
||||
|
@ -69,7 +69,7 @@ enum class Operation: uint8_t {
|
||||
SBB,
|
||||
/// Subtract; source, destination, operand and displacement will be populated appropriately.
|
||||
SUB,
|
||||
/// Unsigned multiply; multiplies the source value by AX or AL, storing the result in DX:AX or AX.
|
||||
/// Unsigned multiply; multiplies the source value by EAX, AX or AL, storing the result in EDX:EAX, DX:AX or AX.
|
||||
MUL,
|
||||
/// Single operand signed multiply; multiplies the source value by AX or AL, storing the result in DX:AX or AX.
|
||||
IMUL_1,
|
||||
|
@ -25,7 +25,7 @@ namespace {
|
||||
|
||||
// The tests themselves are not duplicated in this repository;
|
||||
// provide their real path here.
|
||||
constexpr char TestSuiteHome[] = "/Users/tharte/Projects/ProcessorTests/8088/v1";
|
||||
constexpr char TestSuiteHome[] = "/Users/thomasharte/Projects/ProcessorTests/8088/v1";
|
||||
|
||||
using Status = InstructionSet::x86::Status;
|
||||
struct Registers {
|
||||
@ -292,9 +292,8 @@ struct FailedExecution {
|
||||
// @"D8.json.gz", @"D9.json.gz", @"DA.json.gz", @"DB.json.gz",
|
||||
// @"DC.json.gz", @"DD.json.gz", @"DE.json.gz", @"DE.json.gz",
|
||||
//
|
||||
// // NOP
|
||||
// @"90.json.gz",
|
||||
//
|
||||
// // Untested: HLT, WAIT
|
||||
////
|
||||
// // ADC
|
||||
// @"10.json.gz", @"11.json.gz", @"12.json.gz", @"13.json.gz", @"14.json.gz", @"15.json.gz",
|
||||
// @"80.2.json.gz", @"81.2.json.gz", @"83.2.json.gz",
|
||||
@ -302,14 +301,20 @@ struct FailedExecution {
|
||||
// // ADD
|
||||
// @"00.json.gz", @"01.json.gz", @"02.json.gz", @"03.json.gz", @"04.json.gz", @"05.json.gz",
|
||||
// @"80.0.json.gz", @"81.0.json.gz", @"83.0.json.gz",
|
||||
//
|
||||
// // SBB
|
||||
// @"18.json.gz", @"19.json.gz", @"1A.json.gz", @"1B.json.gz", @"1C.json.gz", @"1D.json.gz",
|
||||
// @"80.3.json.gz", @"81.3.json.gz", @"83.3.json.gz",
|
||||
//
|
||||
// // SUB
|
||||
// @"28.json.gz", @"29.json.gz", @"2A.json.gz", @"2B.json.gz", @"2C.json.gz", @"2D.json.gz",
|
||||
// @"80.5.json.gz", @"81.5.json.gz", @"83.5.json.gz",
|
||||
|
||||
// SBB
|
||||
@"18.json.gz", @"19.json.gz", @"1A.json.gz", @"1B.json.gz", @"1C.json.gz", @"1D.json.gz",
|
||||
@"80.3.json.gz", @"81.3.json.gz", @"83.3.json.gz",
|
||||
// MUL
|
||||
@"F6.4.json.gz", @"F7.4.json.gz",
|
||||
|
||||
// SUB
|
||||
@"28.json.gz", @"29.json.gz", @"2A.json.gz", @"2B.json.gz", @"2C.json.gz", @"2D.json.gz",
|
||||
@"80.5.json.gz", @"81.5.json.gz", @"83.5.json.gz",
|
||||
// // NOP
|
||||
// @"90.json.gz",
|
||||
|
||||
// AND
|
||||
// @"20.json.gz", @"21.json.gz", @"22.json.gz", @"23.json.gz", @"24.json.gz", @"25.json.gz",
|
||||
|
Loading…
Reference in New Issue
Block a user