1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 08:49:37 +00:00

Implement MUL.

This commit is contained in:
Thomas Harte 2023-10-09 21:50:17 -04:00
parent e46e42d896
commit ff6573dd02
3 changed files with 51 additions and 13 deletions

View File

@ -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:
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);

View File

@ -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,

View File

@ -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",