Skip to content

Instantly share code, notes, and snippets.

@BreadFish64
Created August 19, 2020 02:38
Show Gist options
  • Save BreadFish64/0fe98f90d5986fd843b19327a456d047 to your computer and use it in GitHub Desktop.
Save BreadFish64/0fe98f90d5986fd843b19327a456d047 to your computer and use it in GitHub Desktop.
ARMv4 Instruction Bitfield Prototype
#pragma once
#include <limits>
#include "types.hpp"
namespace GBA {
template <typename Storage, usize start, usize end, typename IO = Storage>
class BitField {
public:
static constexpr usize size = end - start + 1;
private:
static_assert(end < std::numeric_limits<Storage>::digits,
"BitField is out of bounds for Storage type");
static constexpr Storage mask = ((1 << size) - 1) << start;
Storage storage;
public:
BitField& operator=(IO x) {
storage = (storage & ~mask) | ((static_cast<Storage>(x) << start) & mask);
return *this;
};
operator IO() {
return static_cast<IO>((storage & mask) >> start);
}
};
} // namespace GBA
#pragma once
#include "bit_field.hpp"
namespace GBA {
enum class ShiftType : u8 {
LSL = 0,
LSR = 1,
ASR = 2,
ROR = 3,
};
enum class Opcode : u8 {
DataProcessing = 0,
MemoryAccess = 1,
Branch = 2,
};
enum class ConditionCode : u8 {
EQ = 0b0000,
NE = 0b0001,
CS = 0b0010,
HS = CS,
CC = 0b0011,
LO = CC,
MI = 0b0100,
PL = 0b0101,
VS = 0b0110,
VC = 0b0111,
HI = 0b1000,
LS = 0b1001,
GE = 0b1010,
LT = 0b1011,
GT = 0b1100,
LE = 0b1101,
AL = 0b1110,
UNUSED = 0b1111,
};
enum class DataProcessingCommand {
AND = 0x0,
EOR = 0x1,
SUB = 0x2,
RSB = 0x3,
ADD = 0x4,
ADC = 0x5,
SBC = 0x6,
RSC = 0x7,
TST = 0x8,
TEQ = 0x9,
CMP = 0xA,
CMN = 0xB,
ORR = 0xC,
MOV = 0xD,
BIC = 0xE,
MVN = 0xF,
};
using RMField = BitField<u32, 0, 3>;
using RSField = BitField<u32, 8, 11>;
using RDField = BitField<u32, 12, 15>;
using RNField = BitField<u32, 16, 19>;
using ShiftTypeField = BitField<u32, 5, 6, ShiftType>;
using ShiftAmountField = BitField<u32, 7, 11>;
using SField = BitField<u32, 20, 20, bool>;
using DataProcessingCommandField = BitField<u32, 21, 24, DataProcessingCommand>;
using IField = BitField<u32, 25, 25, bool>;
using OpcodeField = BitField<u32, 26, 27, Opcode>;
using ConditionCodeField = BitField<u32, 28, 31, ConditionCode>;
union DataProcessingRegisterInstruction {
u32 raw;
RMField rm;
BitField<u32, 4, 4, bool> shift_by_register; // false
ShiftTypeField shtype;
ShiftAmountField shamt;
RDField rd;
RNField rn;
SField s;
DataProcessingCommandField command;
IField i; // false
OpcodeField opcode; // DataProcessing
ConditionCodeField condition_code;
};
} // namespace GBA
#include "logger.hpp"
#include "opcode.hpp"
int main() {
GBA::DataProcessingRegisterInstruction instruction;
instruction.rm = 12;
instruction.shift_by_register = false;
instruction.shtype = GBA::ShiftType::ROR;
instruction.shamt = 0b10100;
instruction.rd = 4;
instruction.rn = 5;
instruction.s = true;
instruction.command = GBA::DataProcessingCommand::ADD;
instruction.i = false;
instruction.condition_code = GBA::ConditionCode::AL;
GBA::Log(GBA::LogLevel::Info, "ADDS r4, r5, r12 ROR #20 -> {:#08X}", instruction.raw);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment