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:
parent
ff6573dd02
commit
5e830781cc
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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:@"."];
|
||||
|
Loading…
Reference in New Issue
Block a user