1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-21 08:29:06 +00:00
CLK/OSBindings/Mac/Clock SignalTests/DingusdevPowerPCTests.mm
2022-03-25 06:25:06 -04:00

144 lines
4.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// DingusdevPowerPCTests.mm
// Clock Signal
//
// Created by Thomas Harte on 18/03/2022.
// Copyright 2022 Thomas Harte. All rights reserved.
//
#import <XCTest/XCTest.h>
#include <cstdlib>
#include "../../../InstructionSets/PowerPC/Decoder.hpp"
using namespace InstructionSet::PowerPC;
@interface DingusdevPowerPCTests : XCTestCase
@end
@implementation DingusdevPowerPCTests
- (void)testDecoding {
NSData *const testData =
[NSData dataWithContentsOfURL:
[[NSBundle bundleForClass:[self class]]
URLForResource:@"ppcdisasmtest"
withExtension:@"csv"
subdirectory:@"dingusdev PowerPC tests"]];
NSString *const wholeFile = [[NSString alloc] initWithData:testData encoding:NSUTF8StringEncoding];
NSArray<NSString *> *const lines = [wholeFile componentsSeparatedByString:@"\n"];
InstructionSet::PowerPC::Decoder decoder(InstructionSet::PowerPC::Model::MPC601);
for(NSString *const line in lines) {
// Ignore empty lines and comments.
if([line length] == 0) {
continue;
}
if([line characterAtIndex:0] == '#') {
continue;
}
NSArray<NSString *> *const columns = [line componentsSeparatedByString:@","];
// Columns are 1: address; 2: opcode; 3: specific to the instruction.
const uint32_t address = uint32_t(std::strtol([columns[0] UTF8String], 0, 16));
const uint32_t opcode = uint32_t(std::strtol([columns[1] UTF8String], 0, 16));
NSString *const operation = columns[2];
const auto instruction = decoder.decode(opcode);
switch(instruction.operation) {
default:
NSAssert(FALSE, @"Didn't handle %@", line);
break;
case Operation::bclrx:
case Operation::bcctrx: {
NSString *baseOperation = nil;
switch(instruction.branch_options()) {
case BranchOptions::Always: baseOperation = @"b"; break;
case BranchOptions::Clear:
switch(Condition(instruction.bi() & 3)) {
default: break;
case Condition::Negative: baseOperation = @"bge"; break;
case Condition::Positive: baseOperation = @"ble"; break;
case Condition::Zero: baseOperation = @"bne"; break;
case Condition::SummaryOverflow:
baseOperation = @"bns";
break;
}
break;
case BranchOptions::Set:
switch(Condition(instruction.bi() & 3)) {
default: break;
case Condition::Negative: baseOperation = @"blt"; break;
case Condition::Positive: baseOperation = @"bgt"; break;
case Condition::Zero: baseOperation = @"beq"; break;
case Condition::SummaryOverflow:
baseOperation = @"bso";
break;
}
break;
default: break;
}
if(instruction.operation == Operation::bcctrx) {
baseOperation = [baseOperation stringByAppendingString:@"ctr"];
} else {
baseOperation = [baseOperation stringByAppendingString:@"lr"];
}
if(!baseOperation) {
NSAssert(FALSE, @"Didn't handle bi %d for bo %d, %@", instruction.bi() & 3, instruction.bo(), line);
} else {
if(instruction.lk()) {
baseOperation = [baseOperation stringByAppendingString:@"l"];
}
if(instruction.branch_prediction_hint()) {
baseOperation = [baseOperation stringByAppendingString:@"+"];
}
XCTAssertEqualObjects(operation, baseOperation);
}
if(instruction.bi() & ~3) {
NSString *const expectedCR = [NSString stringWithFormat:@"cr%d", instruction.bi() >> 2];
XCTAssertEqualObjects(columns[3], expectedCR);
}
} break;
case Operation::bcx: {
switch(instruction.branch_options()) {
case BranchOptions::Always:
XCTAssertEqualObjects(operation, @"b");
break;
default:
NSLog(@"No opcode tested for bcx with bo %02x", instruction.bo());
break;
}
const uint32_t destination = uint32_t(std::strtol([columns[3] UTF8String], 0, 16));
const uint32_t decoded_destination = instruction.bd() + address;
XCTAssertEqual(decoded_destination, destination);
} break;
case Operation::bx: {
switch((instruction.aa() ? 2 : 0) | (instruction.lk() ? 1 : 0)) {
case 0: XCTAssertEqualObjects(operation, @"b"); break;
case 1: XCTAssertEqualObjects(operation, @"bl"); break;
case 2: XCTAssertEqualObjects(operation, @"ba"); break;
case 3: XCTAssertEqualObjects(operation, @"bla"); break;
}
const uint32_t destination = uint32_t(std::strtol([columns[3] UTF8String], 0, 16));
const uint32_t decoded_destination =
instruction.li() + (instruction.aa() ? 0 : address);
XCTAssertEqual(decoded_destination, destination);
} break;
}
}
}
@end