mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-05 06:05:27 +00:00
Merge pull request #1122 from TomHarte/6809
Add experimental 6809 opcode decoder.
This commit is contained in:
commit
345e519e6a
245
InstructionSets/6809/OperationMapper.hpp
Normal file
245
InstructionSets/6809/OperationMapper.hpp
Normal file
@ -0,0 +1,245 @@
|
||||
//
|
||||
// OperationMapper.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 17/03/2023.
|
||||
// Copyright © 2023 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef InstructionSets_M6809_OperationMapper_hpp
|
||||
#define InstructionSets_M6809_OperationMapper_hpp
|
||||
|
||||
// Cf. https://techheap.packetizer.com/processors/6809/6809Instructions.html
|
||||
//
|
||||
// Subject to corrections:
|
||||
//
|
||||
// * CWAI and the pushes and pulls at 0x3x are immediate, not inherent.
|
||||
namespace InstructionSet {
|
||||
namespace M6809 {
|
||||
|
||||
enum class AddressingMode {
|
||||
Illegal,
|
||||
|
||||
Inherent,
|
||||
Immediate,
|
||||
Direct,
|
||||
Relative, // TODO: is it worth breaking this into 8- and 16-bit versions?
|
||||
Variant,
|
||||
Indexed,
|
||||
Extended,
|
||||
};
|
||||
|
||||
enum class Operation {
|
||||
None,
|
||||
|
||||
SUBB, CMPB, SBCB, ADDD, ANDB, BITB, LDB, STB,
|
||||
EORB, ADCB, ORB, ADDB, LDD, STD, LDU, STU,
|
||||
SUBA, CMPA, SBCA, SUBD, ANDA, BITA, LDA, STA,
|
||||
EORA, ADCA, ORA, ADDA, CMPX, JSR, LDX, STX,
|
||||
BSR,
|
||||
|
||||
NEG, COM, LSR, ROR, ASR,
|
||||
LSL, ROL, DEC, INC, TST, JMP, CLR,
|
||||
NEGA, COMA, LSRA, RORA, ASRA,
|
||||
LSLA, ROLA, DECA, INCA, TSTA, CLRA,
|
||||
NEGB, COMB, LSRB, RORB, ASRB,
|
||||
LSLB, ROLB, DECB, INCB, TSTB, CLRB,
|
||||
|
||||
LEAX, LEAY, LEAS, LEAU,
|
||||
PSHS, PULS, PSHU, PULU,
|
||||
RTS, ABX, RTI,
|
||||
CWAI, MUL, RESET, SWI,
|
||||
|
||||
BRA, BRN, BHI, BLS, BCC, BCS, BNE, BEQ,
|
||||
BVC, BVS, BPL, BMI, BGE, BLT, BGT, BLE,
|
||||
|
||||
Page1, Page2, NOP, SYNC, LBRA, LBSR,
|
||||
DAA, ORCC, ANDCC, SEX, EXG, TFR,
|
||||
|
||||
LBRN, LBHI, LBLS, LBCC, LBCS, LBNE, LBEQ,
|
||||
LBVC, LBVS, LBPL, LBMI, LBGE, LBLT, LBGT, LBLE,
|
||||
|
||||
SWI2, CMPD, CMPY, LDY, STY, LDS, STS,
|
||||
|
||||
SWI3, CMPU, CMPS,
|
||||
};
|
||||
|
||||
enum class Page {
|
||||
Page0, Page1, Page2,
|
||||
};
|
||||
|
||||
/*!
|
||||
Calls @c scheduler.schedule<Operation,AddressingMode> to describe the instruction
|
||||
defined by opcode @c i on page @c page.
|
||||
*/
|
||||
template <Page page> struct OperationMapper {
|
||||
template <int i, typename SchedulerT> void dispatch(SchedulerT &scheduler);
|
||||
};
|
||||
|
||||
template <>
|
||||
template <int i, typename SchedulerT> void OperationMapper<Page::Page0>::dispatch(SchedulerT &s) {
|
||||
using AM = AddressingMode;
|
||||
using O = Operation;
|
||||
|
||||
constexpr auto upper = (i >> 4) & 0xf;
|
||||
constexpr auto lower = (i >> 0) & 0xf;
|
||||
|
||||
constexpr AddressingMode modes[] = {
|
||||
AM::Immediate, AM::Direct, AM::Indexed, AM::Extended
|
||||
};
|
||||
constexpr AddressingMode mode = modes[(i >> 4) & 3];
|
||||
|
||||
switch(upper) {
|
||||
default: break;
|
||||
|
||||
case 0x1: {
|
||||
constexpr Operation operations[] = {
|
||||
O::Page1, O::Page2, O::NOP, O::SYNC, O::None, O::None, O::LBRA, O::LBSR,
|
||||
O::None, O::DAA, O::ORCC, O::None, O::ANDCC, O::SEX, O::EXG, O::TFR,
|
||||
};
|
||||
constexpr AddressingMode modes[] = {
|
||||
AM::Variant, AM::Variant, AM::Inherent, AM::Inherent,
|
||||
AM::Illegal, AM::Illegal, AM::Relative, AM::Relative,
|
||||
AM::Illegal, AM::Inherent, AM::Immediate, AM::Illegal,
|
||||
AM::Immediate, AM::Inherent, AM::Inherent, AM::Inherent,
|
||||
};
|
||||
s.template schedule<operations[lower], modes[lower]>();
|
||||
} break;
|
||||
case 0x2: {
|
||||
constexpr Operation operations[] = {
|
||||
O::BRA, O::BRN, O::BHI, O::BLS, O::BCC, O::BCS, O::BNE, O::BEQ,
|
||||
O::BVC, O::BVS, O::BPL, O::BMI, O::BGE, O::BLT, O::BGT, O::BLE,
|
||||
};
|
||||
s.template schedule<operations[lower], AM::Relative>();
|
||||
} break;
|
||||
case 0x3: {
|
||||
constexpr Operation operations[] = {
|
||||
O::LEAX, O::LEAY, O::LEAS, O::LEAU, O::PSHS, O::PULS, O::PSHU, O::PULU,
|
||||
O::None, O::RTS, O::ABX, O::RTI, O::CWAI, O::MUL, O::RESET, O::SWI,
|
||||
};
|
||||
constexpr auto op = operations[lower];
|
||||
switch(lower) {
|
||||
case 0x0: case 0x1: case 0x2: case 0x3:
|
||||
s.template schedule<op, AM::Indexed>();
|
||||
break;
|
||||
case 0x4: case 0x5: case 0x6: case 0x7: case 0xc:
|
||||
s.template schedule<op, AM::Immediate>();
|
||||
break;
|
||||
case 0x8:
|
||||
s.template schedule<op, AM::Illegal>();
|
||||
break;
|
||||
default:
|
||||
s.template schedule<op, AM::Inherent>();
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case 0x4: {
|
||||
constexpr Operation operations[] = {
|
||||
O::NEGA, O::None, O::None, O::COMA, O::LSRA, O::None, O::RORA, O::ASRA,
|
||||
O::LSLA, O::ROLA, O::DECA, O::None, O::INCA, O::TSTA, O::None, O::CLRA,
|
||||
};
|
||||
constexpr auto op = operations[lower];
|
||||
s.template schedule<op, op == O::None ? AM::Illegal : AM::Inherent>();
|
||||
} break;
|
||||
case 0x5: {
|
||||
constexpr Operation operations[] = {
|
||||
O::NEGB, O::None, O::None, O::COMB, O::LSRB, O::None, O::RORB, O::ASRB,
|
||||
O::LSLB, O::ROLB, O::DECB, O::None, O::INCB, O::TSTB, O::None, O::CLRB,
|
||||
};
|
||||
constexpr auto op = operations[lower];
|
||||
s.template schedule<op, op == O::None ? AM::Illegal : AM::Inherent>();
|
||||
} break;
|
||||
case 0x0: case 0x6: case 0x7: {
|
||||
constexpr Operation operations[] = {
|
||||
O::NEG, O::None, O::None, O::COM, O::LSR, O::None, O::ROR, O::ASR,
|
||||
O::LSL, O::ROL, O::DEC, O::None, O::INC, O::TST, O::JMP, O::CLR,
|
||||
};
|
||||
constexpr auto op = operations[lower];
|
||||
s.template schedule<op, op == O::None ? AM::Illegal : upper == 0 ? AM::Direct : mode>();
|
||||
} break;
|
||||
case 0x8: case 0x9: case 0xa: case 0xb: {
|
||||
constexpr Operation operations[] = {
|
||||
O::SUBA, O::CMPA, O::SBCA, O::SUBD, O::ANDA, O::BITA, O::LDA, O::STA,
|
||||
O::EORA, O::ADCA, O::ORA, O::ADDA, O::CMPX, O::JSR, O::LDX, O::STX,
|
||||
};
|
||||
if(i == 0x8d) s.template schedule<O::BSR, AM::Relative>();
|
||||
else s.template schedule<operations[lower], mode>();
|
||||
} break;
|
||||
case 0xc: case 0xd: case 0xe: case 0xf: {
|
||||
constexpr Operation operations[] = {
|
||||
O::SUBB, O::CMPB, O::SBCB, O::ADDD, O::ANDB, O::BITB, O::LDB, O::STB,
|
||||
O::EORB, O::ADCB, O::ORB, O::ADDB, O::LDD, O::STD, O::LDU, O::STU,
|
||||
};
|
||||
s.template schedule<operations[lower], mode>();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
template <int i, typename SchedulerT> void OperationMapper<Page::Page1>::dispatch(SchedulerT &s) {
|
||||
using AM = AddressingMode;
|
||||
using O = Operation;
|
||||
|
||||
constexpr AddressingMode modes[] = {
|
||||
AM::Immediate, AM::Direct, AM::Indexed, AM::Extended
|
||||
};
|
||||
constexpr auto mode = modes[(i >> 4) & 3];
|
||||
|
||||
if constexpr (i >= 0x21 && i < 0x30) {
|
||||
constexpr Operation operations[] = {
|
||||
O::LBRN, O::LBHI, O::LBLS, O::LBCC, O::LBCS, O::LBNE, O::LBEQ,
|
||||
O::LBVC, O::LBVS, O::LBPL, O::LBMI, O::LBGE, O::LBLT, O::LBGT, O::LBLE,
|
||||
};
|
||||
s.template schedule<operations[i - 0x21], AM::Relative>();
|
||||
} else switch(i) {
|
||||
default: s.template schedule<O::None, AM::Illegal>(); break;
|
||||
case 0x3f: s.template schedule<O::SWI2, AM::Inherent>(); break;
|
||||
|
||||
case 0x83: case 0x93: case 0xa3: case 0xb3:
|
||||
s.template schedule<O::CMPD, mode>();
|
||||
break;
|
||||
case 0x8c: case 0x9c: case 0xac: case 0xbc:
|
||||
s.template schedule<O::CMPY, mode>();
|
||||
break;
|
||||
case 0x8e: case 0x9e: case 0xae: case 0xbe:
|
||||
s.template schedule<O::LDY, mode>();
|
||||
break;
|
||||
case 0x9f: case 0xaf: case 0xbf:
|
||||
s.template schedule<O::STY, mode>();
|
||||
break;
|
||||
case 0xce: case 0xde: case 0xee: case 0xfe:
|
||||
s.template schedule<O::LDS, mode>();
|
||||
break;
|
||||
case 0xdf: case 0xef: case 0xff:
|
||||
s.template schedule<O::STS, mode>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
template <int i, typename SchedulerT> void OperationMapper<Page::Page2>::dispatch(SchedulerT &s) {
|
||||
using AM = AddressingMode;
|
||||
using O = Operation;
|
||||
|
||||
constexpr AddressingMode modes[] = {
|
||||
AM::Immediate, AM::Direct, AM::Indexed, AM::Extended
|
||||
};
|
||||
constexpr auto mode = modes[(i >> 4) & 3];
|
||||
|
||||
switch(i) {
|
||||
default: s.template schedule<O::None, AM::Illegal>(); break;
|
||||
case 0x3f: s.template schedule<O::SWI3, AM::Inherent>(); break;
|
||||
|
||||
case 0x83: case 0x93: case 0xa3: case 0xb3:
|
||||
s.template schedule<O::CMPU, mode>();
|
||||
break;
|
||||
case 0x8c: case 0x9c: case 0xac: case 0xbc:
|
||||
s.template schedule<O::CMPS, mode>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* InstructionSets_M6809_OperationMapper_hpp */
|
118
OSBindings/Mac/Clock SignalTests/6809OperationMapperTests.mm
Normal file
118
OSBindings/Mac/Clock SignalTests/6809OperationMapperTests.mm
Normal file
@ -0,0 +1,118 @@
|
||||
//
|
||||
// 68000BCDTests.m
|
||||
// Clock SignalTests
|
||||
//
|
||||
// Created by Thomas Harte on 29/06/2019.
|
||||
//
|
||||
// Largely ported from the tests of the Portable 68k Emulator.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "Dispatcher.hpp"
|
||||
#include "../../../InstructionSets/6809/OperationMapper.hpp"
|
||||
|
||||
using namespace InstructionSet::M6809;
|
||||
|
||||
namespace {
|
||||
|
||||
struct OperationCapture {
|
||||
template <Operation operation, AddressingMode mode> void schedule() {
|
||||
this->operation = operation;
|
||||
this->mode = mode;
|
||||
}
|
||||
Operation operation;
|
||||
AddressingMode mode;
|
||||
};
|
||||
|
||||
template <Page page> OperationCapture capture(uint8_t opcode) {
|
||||
OperationCapture catcher;
|
||||
OperationMapper<page> mapper;
|
||||
Reflection::dispatch(mapper, opcode, catcher);
|
||||
return catcher;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@interface M6809OperationMapperTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation M6809OperationMapperTests
|
||||
|
||||
- (void)testOpcode:(uint8_t)opcode page:(Page)page isOperation:(Operation)operation addressingMode:(AddressingMode)mode {
|
||||
OperationCapture catcher;
|
||||
|
||||
switch(page) {
|
||||
case Page::Page0: catcher = capture<Page::Page0>(opcode); break;
|
||||
case Page::Page1: catcher = capture<Page::Page1>(opcode); break;
|
||||
case Page::Page2: catcher = capture<Page::Page2>(opcode); break;
|
||||
}
|
||||
|
||||
XCTAssertEqual(catcher.operation, operation, "Operation didn't match for opcode 0x%02x in page %d", opcode, int(page));
|
||||
XCTAssertEqual(catcher.mode, mode, "Mode didn't match for opcode 0x%02x in page %d", opcode, int(page));
|
||||
}
|
||||
|
||||
- (void)testMap {
|
||||
// Spot tests only for now; will do for checking that code compiles and acts semi-reasonably, at least.
|
||||
[self testOpcode:0x3a page:Page::Page0 isOperation:Operation::ABX addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0xd9 page:Page::Page0 isOperation:Operation::ADCB addressingMode:AddressingMode::Direct];
|
||||
[self testOpcode:0xab page:Page::Page0 isOperation:Operation::ADDA addressingMode:AddressingMode::Indexed];
|
||||
[self testOpcode:0xf3 page:Page::Page0 isOperation:Operation::ADDD addressingMode:AddressingMode::Extended];
|
||||
[self testOpcode:0xc4 page:Page::Page0 isOperation:Operation::ANDB addressingMode:AddressingMode::Immediate];
|
||||
[self testOpcode:0x1c page:Page::Page0 isOperation:Operation::ANDCC addressingMode:AddressingMode::Immediate];
|
||||
[self testOpcode:0x08 page:Page::Page0 isOperation:Operation::LSL addressingMode:AddressingMode::Direct];
|
||||
[self testOpcode:0x57 page:Page::Page0 isOperation:Operation::ASRB addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x24 page:Page::Page0 isOperation:Operation::BCC addressingMode:AddressingMode::Relative];
|
||||
[self testOpcode:0xa5 page:Page::Page0 isOperation:Operation::BITA addressingMode:AddressingMode::Indexed];
|
||||
[self testOpcode:0x20 page:Page::Page0 isOperation:Operation::BRA addressingMode:AddressingMode::Relative];
|
||||
[self testOpcode:0x8d page:Page::Page0 isOperation:Operation::BSR addressingMode:AddressingMode::Relative];
|
||||
[self testOpcode:0x5f page:Page::Page0 isOperation:Operation::CLRB addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x7f page:Page::Page0 isOperation:Operation::CLR addressingMode:AddressingMode::Extended];
|
||||
[self testOpcode:0x81 page:Page::Page0 isOperation:Operation::CMPA addressingMode:AddressingMode::Immediate];
|
||||
[self testOpcode:0xa3 page:Page::Page1 isOperation:Operation::CMPD addressingMode:AddressingMode::Indexed];
|
||||
[self testOpcode:0xa3 page:Page::Page2 isOperation:Operation::CMPU addressingMode:AddressingMode::Indexed];
|
||||
[self testOpcode:0x53 page:Page::Page0 isOperation:Operation::COMB addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x73 page:Page::Page0 isOperation:Operation::COM addressingMode:AddressingMode::Extended];
|
||||
[self testOpcode:0x3c page:Page::Page0 isOperation:Operation::CWAI addressingMode:AddressingMode::Immediate];
|
||||
[self testOpcode:0x19 page:Page::Page0 isOperation:Operation::DAA addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x4a page:Page::Page0 isOperation:Operation::DECA addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x0a page:Page::Page0 isOperation:Operation::DEC addressingMode:AddressingMode::Direct];
|
||||
[self testOpcode:0xa8 page:Page::Page0 isOperation:Operation::EORA addressingMode:AddressingMode::Indexed];
|
||||
[self testOpcode:0xf8 page:Page::Page0 isOperation:Operation::EORB addressingMode:AddressingMode::Extended];
|
||||
[self testOpcode:0x4c page:Page::Page0 isOperation:Operation::INCA addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x0c page:Page::Page0 isOperation:Operation::INC addressingMode:AddressingMode::Direct];
|
||||
[self testOpcode:0x6e page:Page::Page0 isOperation:Operation::JMP addressingMode:AddressingMode::Indexed];
|
||||
[self testOpcode:0x9d page:Page::Page0 isOperation:Operation::JSR addressingMode:AddressingMode::Direct];
|
||||
[self testOpcode:0x24 page:Page::Page1 isOperation:Operation::LBCC addressingMode:AddressingMode::Relative];
|
||||
[self testOpcode:0xe6 page:Page::Page0 isOperation:Operation::LDB addressingMode:AddressingMode::Indexed];
|
||||
[self testOpcode:0x8e page:Page::Page1 isOperation:Operation::LDY addressingMode:AddressingMode::Immediate];
|
||||
[self testOpcode:0x32 page:Page::Page0 isOperation:Operation::LEAS addressingMode:AddressingMode::Indexed];
|
||||
[self testOpcode:0x74 page:Page::Page0 isOperation:Operation::LSR addressingMode:AddressingMode::Extended];
|
||||
[self testOpcode:0x3d page:Page::Page0 isOperation:Operation::MUL addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x40 page:Page::Page0 isOperation:Operation::NEGA addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x00 page:Page::Page0 isOperation:Operation::NEG addressingMode:AddressingMode::Direct];
|
||||
[self testOpcode:0x12 page:Page::Page0 isOperation:Operation::NOP addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x8a page:Page::Page0 isOperation:Operation::ORA addressingMode:AddressingMode::Immediate];
|
||||
[self testOpcode:0x1a page:Page::Page0 isOperation:Operation::ORCC addressingMode:AddressingMode::Immediate];
|
||||
[self testOpcode:0x34 page:Page::Page0 isOperation:Operation::PSHS addressingMode:AddressingMode::Immediate];
|
||||
[self testOpcode:0x36 page:Page::Page0 isOperation:Operation::PSHU addressingMode:AddressingMode::Immediate];
|
||||
[self testOpcode:0x37 page:Page::Page0 isOperation:Operation::PULU addressingMode:AddressingMode::Immediate];
|
||||
[self testOpcode:0x59 page:Page::Page0 isOperation:Operation::ROLB addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x69 page:Page::Page0 isOperation:Operation::ROL addressingMode:AddressingMode::Indexed];
|
||||
[self testOpcode:0x76 page:Page::Page0 isOperation:Operation::ROR addressingMode:AddressingMode::Extended];
|
||||
[self testOpcode:0x3b page:Page::Page0 isOperation:Operation::RTI addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x39 page:Page::Page0 isOperation:Operation::RTS addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0xc2 page:Page::Page0 isOperation:Operation::SBCB addressingMode:AddressingMode::Immediate];
|
||||
[self testOpcode:0x1d page:Page::Page0 isOperation:Operation::SEX addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0xe7 page:Page::Page0 isOperation:Operation::STB addressingMode:AddressingMode::Indexed];
|
||||
[self testOpcode:0xbf page:Page::Page1 isOperation:Operation::STY addressingMode:AddressingMode::Extended];
|
||||
[self testOpcode:0xe0 page:Page::Page0 isOperation:Operation::SUBB addressingMode:AddressingMode::Indexed];
|
||||
[self testOpcode:0x93 page:Page::Page0 isOperation:Operation::SUBD addressingMode:AddressingMode::Direct];
|
||||
[self testOpcode:0x3f page:Page::Page0 isOperation:Operation::SWI addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x3f page:Page::Page1 isOperation:Operation::SWI2 addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x3f page:Page::Page2 isOperation:Operation::SWI3 addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x13 page:Page::Page0 isOperation:Operation::SYNC addressingMode:AddressingMode::Inherent];
|
||||
[self testOpcode:0x4d page:Page::Page0 isOperation:Operation::TSTA addressingMode:AddressingMode::Inherent];
|
||||
}
|
||||
|
||||
@end
|
39
Reflection/Dispatcher.hpp
Normal file
39
Reflection/Dispatcher.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
//
|
||||
// Dispatcher.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 17/03/2023.
|
||||
// Copyright © 2023 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Dispatcher_hpp
|
||||
#define Dispatcher_hpp
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Reflection {
|
||||
|
||||
/*!
|
||||
Calls @c t.dispatch<c>(args...) as efficiently as possible.
|
||||
*/
|
||||
template <typename TargetT, typename... Args> void dispatch(TargetT &t, uint8_t c, Args &&... args) {
|
||||
#define Opt(x) case x: t.template dispatch<x>(std::forward<Args>(args)...); break
|
||||
#define Opt4(x) Opt(x + 0x00); Opt(x + 0x01); Opt(x + 0x02); Opt(x + 0x03)
|
||||
#define Opt16(x) Opt4(x + 0x00); Opt4(x + 0x04); Opt4(x + 0x08); Opt4(x + 0x0c)
|
||||
#define Opt64(x) Opt16(x + 0x00); Opt16(x + 0x10); Opt16(x + 0x20); Opt16(x + 0x30)
|
||||
#define Opt256(x) Opt64(x + 0x00); Opt64(x + 0x40); Opt64(x + 0x80); Opt64(x + 0xc0)
|
||||
|
||||
switch(c) {
|
||||
Opt256(0);
|
||||
}
|
||||
|
||||
#undef Opt256
|
||||
#undef Opt64
|
||||
#undef Opt16
|
||||
#undef Opt4
|
||||
#undef Opt
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* Dispatcher_hpp */
|
Loading…
Reference in New Issue
Block a user