mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-18 01:30:56 +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;
|
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>
|
template <typename IntT>
|
||||||
void and_(IntT &destination, IntT source, Status &status) {
|
void and_(IntT &destination, IntT source, Status &status) {
|
||||||
/*
|
/*
|
||||||
@ -625,7 +647,7 @@ template <
|
|||||||
case Operation::CWD:
|
case Operation::CWD:
|
||||||
if constexpr (data_size == DataSize::Word) {
|
if constexpr (data_size == DataSize::Word) {
|
||||||
Primitive::cwd(registers.dx(), registers.ax());
|
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());
|
Primitive::cwd(registers.edx(), registers.eax());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -640,6 +662,15 @@ template <
|
|||||||
case Operation::ADD: Primitive::add(destination(), source(), status); break;
|
case Operation::ADD: Primitive::add(destination(), source(), status); break;
|
||||||
case Operation::SBB: Primitive::sbb(destination(), source(), status); break;
|
case Operation::SBB: Primitive::sbb(destination(), source(), status); break;
|
||||||
case Operation::SUB: Primitive::sub(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;
|
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);
|
perform<model, DataSize::Word>(instruction, status, flow_controller, registers, memory, io);
|
||||||
break;
|
break;
|
||||||
case DataSize::DWord:
|
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;
|
break;
|
||||||
case DataSize::None:
|
case DataSize::None:
|
||||||
perform<model, DataSize::None>(instruction, status, flow_controller, registers, memory, io);
|
perform<model, DataSize::None>(instruction, status, flow_controller, registers, memory, io);
|
||||||
|
@ -69,7 +69,7 @@ enum class Operation: uint8_t {
|
|||||||
SBB,
|
SBB,
|
||||||
/// Subtract; source, destination, operand and displacement will be populated appropriately.
|
/// Subtract; source, destination, operand and displacement will be populated appropriately.
|
||||||
SUB,
|
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,
|
MUL,
|
||||||
/// Single operand signed multiply; multiplies the source value by AX or AL, storing the result in DX:AX or AX.
|
/// Single operand signed multiply; multiplies the source value by AX or AL, storing the result in DX:AX or AX.
|
||||||
IMUL_1,
|
IMUL_1,
|
||||||
|
@ -25,7 +25,7 @@ namespace {
|
|||||||
|
|
||||||
// The tests themselves are not duplicated in this repository;
|
// The tests themselves are not duplicated in this repository;
|
||||||
// provide their real path here.
|
// 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;
|
using Status = InstructionSet::x86::Status;
|
||||||
struct Registers {
|
struct Registers {
|
||||||
@ -292,9 +292,8 @@ struct FailedExecution {
|
|||||||
// @"D8.json.gz", @"D9.json.gz", @"DA.json.gz", @"DB.json.gz",
|
// @"D8.json.gz", @"D9.json.gz", @"DA.json.gz", @"DB.json.gz",
|
||||||
// @"DC.json.gz", @"DD.json.gz", @"DE.json.gz", @"DE.json.gz",
|
// @"DC.json.gz", @"DD.json.gz", @"DE.json.gz", @"DE.json.gz",
|
||||||
//
|
//
|
||||||
// // NOP
|
// // Untested: HLT, WAIT
|
||||||
// @"90.json.gz",
|
////
|
||||||
//
|
|
||||||
// // ADC
|
// // ADC
|
||||||
// @"10.json.gz", @"11.json.gz", @"12.json.gz", @"13.json.gz", @"14.json.gz", @"15.json.gz",
|
// @"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",
|
// @"80.2.json.gz", @"81.2.json.gz", @"83.2.json.gz",
|
||||||
@ -302,14 +301,20 @@ struct FailedExecution {
|
|||||||
// // ADD
|
// // ADD
|
||||||
// @"00.json.gz", @"01.json.gz", @"02.json.gz", @"03.json.gz", @"04.json.gz", @"05.json.gz",
|
// @"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",
|
// @"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
|
// MUL
|
||||||
@"18.json.gz", @"19.json.gz", @"1A.json.gz", @"1B.json.gz", @"1C.json.gz", @"1D.json.gz",
|
@"F6.4.json.gz", @"F7.4.json.gz",
|
||||||
@"80.3.json.gz", @"81.3.json.gz", @"83.3.json.gz",
|
|
||||||
|
|
||||||
// SUB
|
// // NOP
|
||||||
@"28.json.gz", @"29.json.gz", @"2A.json.gz", @"2B.json.gz", @"2C.json.gz", @"2D.json.gz",
|
// @"90.json.gz",
|
||||||
@"80.5.json.gz", @"81.5.json.gz", @"83.5.json.gz",
|
|
||||||
|
|
||||||
// AND
|
// AND
|
||||||
// @"20.json.gz", @"21.json.gz", @"22.json.gz", @"23.json.gz", @"24.json.gz", @"25.json.gz",
|
// @"20.json.gz", @"21.json.gz", @"22.json.gz", @"23.json.gz", @"24.json.gz", @"25.json.gz",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user