1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-22 12:33:29 +00:00

Implement IMUL, improve test memory footprint.

This commit is contained in:
Thomas Harte 2023-10-09 22:12:15 -04:00
parent ff6573dd02
commit 5e830781cc
3 changed files with 94 additions and 47 deletions

View File

@ -496,6 +496,41 @@ void mul(IntT &destination_high, IntT &destination_low, IntT source, Status &sta
status.overflow = status.carry = destination_high;
}
template <typename IntT>
void imul(IntT &destination_high, IntT &destination_low, IntT source, Status &status) {
/*
(as modified by https://www.felixcloutier.com/x86/daa ...)
IF (OperandSize = 8)
THEN
AX AL SRC (* signed multiplication *)
IF (AX = SignExtend(AL))
THEN CF = 0; OF = 0;
ELSE CF = 1; OF = 1;
FI;
ELSE IF OperandSize = 16
THEN
DX:AX AX SRC (* signed multiplication *)
IF (DX:AX = SignExtend(AX))
THEN CF = 0; OF = 0;
ELSE CF = 1; OF = 1;
FI;
ELSE (* OperandSize = 32 *)
EDX:EAX EAX SRC (* signed multiplication *)
IF (EDX:EAX = SignExtend(EAX))
THEN CF = 0; OF = 0;
ELSE CF = 1; OF = 1;
FI;
FI;
*/
using sIntT = typename std::make_signed<IntT>::type;
destination_high = (sIntT(destination_low) * sIntT(source)) >> (8 * sizeof(IntT));
destination_low = IntT(sIntT(destination_low) * sIntT(source));
const auto sign_extension = (destination_low & top_bit<IntT>()) ? IntT(~0) : 0;
status.overflow = status.carry = destination_high != sign_extension;
}
template <typename IntT>
void and_(IntT &destination, IntT source, Status &status) {
/*
@ -671,6 +706,15 @@ template <
Primitive::mul(registers.edx(), registers.eax(), source(), status);
}
return;
case Operation::IMUL_1:
if constexpr (data_size == DataSize::Byte) {
Primitive::imul(registers.ah(), registers.al(), source(), status);
} else if constexpr (data_size == DataSize::Word) {
Primitive::imul(registers.dx(), registers.ax(), source(), status);
} else if constexpr (data_size == DataSize::DWord) {
Primitive::imul(registers.edx(), registers.eax(), source(), status);
}
return;
case Operation::AND: Primitive::and_(destination(), source(), status); break;

View File

@ -71,7 +71,7 @@ enum class Operation: uint8_t {
SUB,
/// 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.
/// Single operand signed multiply; multiplies the source value by EAX, AX or AL, storing the result in EDX:EAX, DX:AX or AX.
IMUL_1,
/// Unsigned divide; divide the source value by AX or AL, storing the quotient in AL and the remainder in AH.
DIV,

View File

@ -278,56 +278,59 @@ struct FailedExecution {
- (NSArray<NSString *> *)testFiles {
NSString *path = [NSString stringWithUTF8String:TestSuiteHome];
NSSet *allowList = [NSSet setWithArray:@[
// @"37.json.gz", // AAA
// @"3F.json.gz", // AAS
// @"D4.json.gz", // AAM
// @"D5.json.gz", // AAD
// @"27.json.gz", // DAA
// @"2F.json.gz", // DAS
//
// @"98.json.gz", // CBW
// @"99.json.gz", // CWD
//
// // ESC
// @"D8.json.gz", @"D9.json.gz", @"DA.json.gz", @"DB.json.gz",
// @"DC.json.gz", @"DD.json.gz", @"DE.json.gz", @"DE.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",
//
// // 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",
@"37.json.gz", // AAA
@"3F.json.gz", // AAS
@"D4.json.gz", // AAM
@"D5.json.gz", // AAD
@"27.json.gz", // DAA
@"2F.json.gz", // DAS
@"98.json.gz", // CBW
@"99.json.gz", // CWD
// ESC
@"D8.json.gz", @"D9.json.gz", @"DA.json.gz", @"DB.json.gz",
@"DC.json.gz", @"DD.json.gz", @"DE.json.gz", @"DE.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",
// 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",
// MUL
@"F6.4.json.gz", @"F7.4.json.gz",
// // NOP
// @"90.json.gz",
// IMUL_1
@"F6.5.json.gz", @"F7.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",
// @"80.4.json.gz", @"81.4.json.gz", @"83.4.json.gz",
//
// // CALL
// @"E8.json.gz", @"FF.2.json.gz",
// @"9A.json.gz", @"FF.3.json.gz",
//
// @"F8.json.gz", // CLC
// @"FC.json.gz", // CLD
// @"FA.json.gz", // CLI
// @"F5.json.gz", // CMC
@"20.json.gz", @"21.json.gz", @"22.json.gz", @"23.json.gz", @"24.json.gz", @"25.json.gz",
@"80.4.json.gz", @"81.4.json.gz", @"83.4.json.gz",
// CALL
@"E8.json.gz", @"FF.2.json.gz",
@"9A.json.gz", @"FF.3.json.gz",
@"F8.json.gz", // CLC
@"FC.json.gz", // CLD
@"FA.json.gz", // CLI
@"F5.json.gz", // CMC
]];
NSSet *ignoreList = nil;
@ -585,7 +588,7 @@ struct FailedExecution {
- (void)testDecoding {
NSMutableArray<NSString *> *failures = [[NSMutableArray alloc] init];
for(NSString *file in [self testFiles]) {
for(NSString *file in [self testFiles]) @autoreleasepool {
for(NSDictionary *test in [self testsInFile:file]) {
// A single failure per instruction is fine.
if(![self applyDecodingTest:test file:file assert:YES]) {
@ -604,7 +607,7 @@ struct FailedExecution {
- (void)testExecution {
NSDictionary *metadata = [self metadata];
for(NSString *file in [self testFiles]) {
for(NSString *file in [self testFiles]) @autoreleasepool {
// Determine the metadata key.
NSString *const name = [file lastPathComponent];
NSRange first_dot = [name rangeOfString:@"."];