Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement some FP32 instructions (fadd.s, fsub.s, flw, fsw) #134

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions src/machine/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ static InstructionFlags unsupported_inst_flags_to_check(Xlen xlen,
flags_to_check |= IMF_AMO;
if (!isa_word.contains('M'))
flags_to_check |= IMF_MUL;
if(!isa_word.contains('F'))
flags_to_check |= (IMF_ALU_REQ_RD_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RT_F);
return InstructionFlags(flags_to_check);
}

Expand Down Expand Up @@ -325,8 +327,9 @@ DecodeState Core::decode(const FetchInterstage &dt) {
// When instruction does not specify register, it is set to x0 as operations on x0 have no
// side effects (not even visualization).
RegisterValue val_rs
= (flags & IMF_ALU_RS_ID) ? uint64_t(size_t(num_rs)) : regs->read_gp(num_rs);
RegisterValue val_rt = regs->read_gp(num_rt);
= (flags & IMF_ALU_RS_ID) ? uint64_t(size_t(num_rs)) : (flags & IMF_ALU_REQ_RS_F) ? regs->read_fp(num_rs) : regs->read_gp(num_rs);
RegisterValue val_rt
= (flags & IMF_ALU_REQ_RT_F) ? regs->read_fp(num_rt) : regs->read_gp(num_rt);
RegisterValue immediate_val = dt.inst.immediate();
const bool regwrite = flags & IMF_REGWRITE;

Expand Down Expand Up @@ -367,7 +370,9 @@ DecodeState Core::decode(const FetchInterstage &dt) {
.ff_rs = FORWARD_NONE,
.ff_rt = FORWARD_NONE,
.alu_component = (flags & IMF_AMO) ? AluComponent::PASS :
(flags & IMF_MUL) ? AluComponent::MUL : AluComponent::ALU,
(flags & IMF_MUL) ? AluComponent::MUL :
// AluComponent::ALU,
(flags & (IMF_ALU_REQ_RD_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RT_F)) == (IMF_ALU_REQ_RD_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RT_F) ? AluComponent::FALU : AluComponent::ALU,
.aluop = alu_op,
.memctl = mem_ctl,
.num_rs = num_rs,
Expand All @@ -377,8 +382,10 @@ DecodeState Core::decode(const FetchInterstage &dt) {
.memwrite = bool(flags & IMF_MEMWRITE),
.alusrc = bool(flags & IMF_ALUSRC),
.regwrite = regwrite,
.regwrite_fp = bool(flags & IMF_ALU_REQ_RD_F),
.alu_req_rs = bool(flags & IMF_ALU_REQ_RS),
.alu_req_rt = bool(flags & IMF_ALU_REQ_RT),
.alu_fp = bool(flags & (IMF_ALU_REQ_RD_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RT_F)), // maybe not correct
.branch_bxx = bool(flags & IMF_BRANCH),
.branch_jal = bool(flags & IMF_JUMP),
.branch_val = bool(flags & IMF_BJ_NOT),
Expand Down Expand Up @@ -452,6 +459,8 @@ ExecuteState Core::execute(const DecodeInterstage &dt) {
.memread = dt.memread,
.memwrite = dt.memwrite,
.regwrite = dt.regwrite,
.regwrite_fp = dt.regwrite_fp,
.alu_fp = dt.alu_fp,
.is_valid = dt.is_valid,
.branch_bxx = dt.branch_bxx,
.branch_jal = dt.branch_jal,
Expand Down Expand Up @@ -568,13 +577,14 @@ MemoryState Core::memory(const ExecuteInterstage &dt) {
.num_rd = dt.num_rd,
.memtoreg = memread,
.regwrite = regwrite,
.regwrite_fp = dt.regwrite_fp,
.is_valid = dt.is_valid,
.csr_written = csr_written,
} };
}

WritebackState Core::writeback(const MemoryInterstage &dt) {
if (dt.regwrite) { regs->write_gp(dt.num_rd, dt.towrite_val); }
if (dt.regwrite) { (dt.regwrite_fp) ? regs->write_fp(dt.num_rd, dt.towrite_val) : regs->write_gp(dt.num_rd, dt.towrite_val); }

return WritebackState { WritebackInternalState {
.inst = (dt.excause == EXCAUSE_NONE)? dt.inst: Instruction::NOP,
Expand Down
14 changes: 14 additions & 0 deletions src/machine/execute/alu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ RegisterValue alu_combined_operate(
: alu64_operate(op.alu_op, modified, a, b);
case AluComponent::MUL:
return (w_operation) ? mul32_operate(op.mul_op, a, b) : mul64_operate(op.mul_op, a, b);
case AluComponent::FALU:
// return (w_operation) ? alu32f_operate(op.alu_op, modified, a, b) : alu64f_operate(op.alu_op, modified, a, b);
return alu32f_operate(op.alu_op, modified, a, b);
case AluComponent::PASS:
return a;
default: qDebug("ERROR, unknown alu component: %hhx", uint8_t(component)); return 0;
Expand Down Expand Up @@ -74,6 +77,17 @@ int32_t alu32_operate(AluOp op, bool modified, RegisterValue a, RegisterValue b)
}
}

int32_t alu32f_operate(AluOp op, bool modified, RegisterValue a, RegisterValue b) {
return alu32_operate(op, modified, a, b);
// switch (op) {
// case AluOp::ADD: {
// float result = (a.as_f32()) + ((modified) ? - (b.as_f32()) : (b.as_f32()));
// return *reinterpret_cast<int32_t*>(&result);
// }
// default: qDebug("ERROR, unknown alu operation: %hhx", uint8_t(op)); return 0;
// }
}

int64_t mul64_operate(MulOp op, RegisterValue a, RegisterValue b) {
switch (op) {
case MulOp::MUL: return a.as_u64() * b.as_u64();
Expand Down
17 changes: 17 additions & 0 deletions src/machine/execute/alu.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace machine {
enum class AluComponent {
ALU, //> RV32/64I
MUL, //> RV32/64M
FALU, //> RV32/64F
PASS, //> Pass operand A without change (used for AMO)
};

Expand Down Expand Up @@ -74,6 +75,22 @@ union AluCombinedOp {
*/
[[gnu::const]] int32_t alu32_operate(AluOp op, bool modified, RegisterValue a, RegisterValue b);

/**
* RV32F for OP and OP-IMM instructions and RV64F OP-32 and OP-IMM-32
*
* ALU conforming to Base Integer Instruction Set, Version 2.0.
*
* @param op operation specifier (funct3 in instruction)
* @param modified modifies behavior of ADD (to SUB) and SRL (to SRA)
* encoded by bit 30 if applicable
* @param a operand 1
* @param b operand 2
* @return result of specified ALU operation (always, no traps)
* integer type is returned to ensure correct signe extension
* to arbitrary implementation of RegisterValue
*/
[[gnu::const]] int32_t alu32f_operate(AluOp op, bool modified, RegisterValue a, RegisterValue b);

/**
* RV64 "M" for OP instructions
*
Expand Down
110 changes: 103 additions & 7 deletions src/machine/instruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ static const ArgumentDesc arg_desc_list[] = {
ArgumentDesc('s', 'g', 0, 0x1f, { { { 5, 15 } }, 0 }),
// Source register 2 (rs2/rt)
ArgumentDesc('t', 'g', 0, 0x1f, { { { 5, 20 } }, 0 }),
// Float destination register (rd)
ArgumentDesc('D', 'f', 0, 0x1f, { { { 5, 7 } }, 0 }),
// Float source register 1 (rs1/rs)
ArgumentDesc('S', 'f', 0, 0x1f, { { { 5, 15 } }, 0 }),
// Float source register 1 (rs1/rs)
ArgumentDesc('T', 'f', 0, 0x1f, { { { 5, 20 } }, 0 }),
// I-type immediate for arithmetic instructions (12bits)
ArgumentDesc('j', 'n', -0x800, 0x7ff, { { { 12, 20 } }, 0 }),
// Shift for bit shift instructions (5bits)
Expand Down Expand Up @@ -369,6 +375,13 @@ static const struct InstructionMap LOAD_map[] = {
IM_UNKNOWN,
};

static const struct InstructionMap F_LOAD_map[] = {
IM_UNKNOWN,
IM_UNKNOWN,
{"flw", IT_I, { .alu_op=AluOp::ADD }, AC_I32, nullptr, {"D", "o(s)"}, 0x2007, 0x707f, { .flags = FLAGS_ALU_I_LOAD | IMF_ALU_REQ_RD_F }, nullptr},
{"fld", IT_I, { .alu_op=AluOp::ADD }, AC_I64, nullptr, {"D", "o(s)"}, 0x3007, 0x707f, { .flags = FLAGS_ALU_I_LOAD | IMF_ALU_REQ_RD_F }, nullptr},
};

static const struct InstructionMap SRI_map[] = { // 0xfe00707f mask changed to 0xfc00707f to support RV64I
{"srli", IT_I, { .alu_op=AluOp::SR }, NOMEM, nullptr, {"d", "s", ">"}, 0x00005013,0xfc00707f, { .flags = FLAGS_ALU_I }, nullptr}, // SRLI
{"srai", IT_I, { .alu_op=AluOp::SR }, NOMEM, nullptr, {"d", "s", ">"}, 0x40005013,0xfc00707f, { .flags = (FLAGS_ALU_I | IMF_ALU_MOD) }, nullptr}, // SRAI
Expand Down Expand Up @@ -396,6 +409,13 @@ static const struct InstructionMap STORE_map[] = {
IM_UNKNOWN,
};

static const struct InstructionMap F_STORE_map[] = {
IM_UNKNOWN,
IM_UNKNOWN,
{"fsw", IT_I, { .alu_op=AluOp::ADD }, AC_U32, nullptr, {"T", "q(s)"}, 0x2027, 0x707f, { .flags = FLAGS_ALU_I_STORE | IMF_ALU_REQ_RT_F }, nullptr}, // FSW
{"fsd", IT_I, { .alu_op=AluOp::ADD }, AC_U64, nullptr, {"T", "q(s)"}, 0x3027, 0x707f, { .flags = FLAGS_ALU_I_STORE | IMF_ALU_REQ_RT_F }, nullptr}, // FSD
};

static const struct InstructionMap ADD_map[] = {
{"add", IT_R, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"d", "s", "t"}, 0x00000033, 0xfe00707f, { .flags = FLAGS_ALU_T_R_STD }, nullptr},
{"sub", IT_R, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"d", "s", "t"}, 0x40000033, 0xfe00707f, { .flags = FLAGS_ALU_T_R_STD | IMF_ALU_MOD }, inst_aliases_sub},
Expand Down Expand Up @@ -579,28 +599,96 @@ static const struct InstructionMap OP_32_map[] = {

// Full, uncomprese, instructions top level map

static const struct InstructionMap F_sgnj_map[] = {
{"fsgnj.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x20000053, 0xfe00707f, {}, nullptr},
{"fsgnjn.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x20001053, 0xfe00707f, {}, nullptr},
{"fsgnjx.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x20002053, 0xfe00707f, {}, nullptr},
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
};

static const struct InstructionMap F_ex_map[] = {
{"fmin.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x28000053, 0xfe00707f, {}, nullptr},
{"fmax.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x28001053, 0xfe00707f, {}, nullptr},
};

static const struct InstructionMap F_cvt_w_s_map[] = {
{"fcvt.w.s",IT_I, NOALU, NOMEM, nullptr, {}, 0xc0000053, 0xfff0007f, {}, nullptr},
{"fcvt.wu.s",IT_I, NOALU, NOMEM, nullptr, {}, 0xc0100053, 0xfff0007f, {}, nullptr},
};

static const struct InstructionMap F_cp_map[] = {
{"fle.s",IT_I, NOALU, NOMEM, nullptr, {}, 0xa0002053, 0xfe00707f, {}, nullptr},
{"flt.s",IT_I, NOALU, NOMEM, nullptr, {}, 0xa0001053, 0xfe00707f, {}, nullptr},
{"feq.s",IT_I, NOALU, NOMEM, nullptr, {}, 0xa0000053, 0xfe00707f, {}, nullptr},
IM_UNKNOWN,
};

static const struct InstructionMap F_cvt_s_w_map[] = {
{"fcvt.s.w",IT_I, NOALU, NOMEM, nullptr, {}, 0xd0000053, 0xfff0007f, {}, nullptr},
{"fcvt.s.wu",IT_I, NOALU, NOMEM, nullptr, {}, 0xd0100053, 0xfff0007f, {}, nullptr},
};

static const struct InstructionMap F_inst_map[] = {
{"fadd.s",IT_I, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"D", "S", "T"}, 0x53, 0xfe00007f, { .flags = FLAGS_ALU_T_R_STD | IMF_ALU_REQ_RT_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RD_F }, nullptr},
{"fsub.s",IT_I, NOALU, NOMEM, nullptr, {"D", "S", "T"}, 0x8000053, 0xfe00007f, { .flags = FLAGS_ALU_T_R_STD | IMF_ALU_REQ_RT_F | IMF_ALU_REQ_RS_F | IMF_ALU_REQ_RD_F | IMF_ALU_MOD}, nullptr},
{"fmul.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x10000053, 0xfe00007f, {}, nullptr},
{"fdiv.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x18000053, 0xfe00007f, {}, nullptr},
{"fsgnj",IT_I, NOALU, NOMEM, F_sgnj_map, {}, 0x20000053, 0xfe00007f, { .subfield = {3, 12} }, nullptr},
{"f-ex.s",IT_I, NOALU, NOMEM, F_ex_map, {}, 0x28000053, 0xfe00007f, { .subfield = {1, 12} }, nullptr},
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
{"fsqrt.s",IT_I, NOALU, NOMEM, nullptr, {}, 0x58000053, 0xfe00007f, {}, nullptr},
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
{"f-cp",IT_I, NOALU, NOMEM, F_cp_map, {}, 0xa0000053, 0xfe00007f, { .subfield = {2, 12} }, nullptr},
IM_UNKNOWN,
IM_UNKNOWN,
IM_UNKNOWN,
{"fcvt-w-s",IT_I, NOALU, NOMEM, F_cvt_w_s_map, {}, 0xc0000053, 0xfe00007f, { .subfield = {1, 20} }, nullptr},
IM_UNKNOWN,
{"fcvt-s-w",IT_I, NOALU, NOMEM, F_cvt_s_w_map, {}, 0xd0000053, 0xfe00007f, { .subfield = {1, 20} }, nullptr},
IM_UNKNOWN,
{"fmv.x.w",IT_I, { .alu_op=AluOp::ADD }, AC_I32, nullptr, {"d", "S"}, 0xe0000053, 0xfe00007f, {}, nullptr},
IM_UNKNOWN,
{"fmv.w.x",IT_I, { .alu_op=AluOp::ADD }, AC_I32, nullptr, {"D", "s"}, 0xf0000053, 0xfe00007f, {}, nullptr},
IM_UNKNOWN,
};

static const struct InstructionMap I_inst_map[] = {
{"load", IT_I, NOALU, NOMEM, LOAD_map, {}, 0x03, 0x7f, { .subfield = {3, 12} }, nullptr}, // LOAD
IM_UNKNOWN, // LOAD-FP
{"load-fp", IT_I, NOALU, NOMEM, F_LOAD_map, {}, 0x07, 0x7f, { .subfield = {2, 12} }, nullptr}, // LOAD-FP
IM_UNKNOWN, // custom-0
{"misc-mem", IT_I, NOALU, NOMEM, MISC_MEM_map, {}, 0x0f, 0x7f, { .subfield = {3, 12} }, nullptr}, // MISC-MEM
{"op-imm", IT_I, NOALU, NOMEM, OP_IMM_map, {}, 0x13, 0x7f, { .subfield = {3, 12} }, nullptr}, // OP-IMM
{"auipc", IT_U, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"d", "u"}, 0x17, 0x7f, { .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE | IMF_PC_TO_ALU }, nullptr}, // AUIPC
{"op-imm-32", IT_I, NOALU, NOMEM, OP_IMM_32_map, {}, 0x1b, 0x7f, { .subfield = {3, 12} }, nullptr}, // OP-IMM-32 IM_UNKNOWN, // OP-IMM-32
IM_UNKNOWN, // 48b
{"store", IT_I, NOALU, NOMEM, STORE_map, {}, 0x23, 0x7f, { .subfield = {3, 12} }, nullptr}, // STORE
IM_UNKNOWN, // STORE-FP
{"store-fp", IT_I, NOALU, NOMEM, F_STORE_map, {}, 0x27, 0x7f, { .subfield = {2, 12} }, nullptr}, // STORE-FP
IM_UNKNOWN, // custom-1
{"amo", IT_R, NOALU, NOMEM, AMO_map, {}, 0x2f, 0x7f, { .subfield = {3, 12} }, nullptr}, // OP-32
{"op", IT_R, NOALU, NOMEM, OP_map, {}, 0x33, 0x7f, { .subfield = {1, 25} }, nullptr}, // OP
{"lui", IT_U, { .alu_op=AluOp::ADD }, NOMEM, nullptr, {"d", "u"}, 0x37, 0x7f, { .flags = IMF_SUPPORTED | IMF_ALUSRC | IMF_REGWRITE }, nullptr}, // LUI
{"op-32", IT_R, NOALU, NOMEM, OP_32_map, {}, 0x3b, 0x7f, { .subfield = {1, 25} }, nullptr}, // OP-32
IM_UNKNOWN, // 64b
IM_UNKNOWN, // MADD
IM_UNKNOWN, // MSUB
IM_UNKNOWN, // NMSUB
IM_UNKNOWN, // NMADD
IM_UNKNOWN, // OP-FP
{"fmadd.s", IT_I, NOALU, NOMEM, nullptr, {}, 0x43, 0x7f, {}, nullptr}, // FMADD.S
{"fmsub.s", IT_I, NOALU, NOMEM, nullptr, {}, 0x47, 0x7f, {}, nullptr}, // FMSUB.S
{"fnmsub.s", IT_I, NOALU, NOMEM, nullptr, {}, 0x4b, 0x7f, {}, nullptr}, // FNMSUB.S
{"fnmadd.s", IT_I, NOALU, NOMEM, nullptr, {}, 0x4f, 0x7f, {}, nullptr}, // FNMADD.S
{"op-fp",IT_I, NOALU, NOMEM, F_inst_map, {}, 0x600007f, 0x7f, { .subfield={5,27} }, nullptr}, // OP-FP
IM_UNKNOWN, // reserved
IM_UNKNOWN, // custom-2/rv128
IM_UNKNOWN, // 48b
Expand Down Expand Up @@ -805,6 +893,14 @@ QString Instruction::to_str(Address inst_addr) const {
}
break;
}
case 'f': {
if (symbolic_registers_enabled) {
res += QString(Rv_regnames[field]);
} else {
res += "f" + QString::number(field);
}
break;
}
case 'p':
case 'a': {
field += (int32_t)inst_addr.get_raw();
Expand Down
5 changes: 5 additions & 0 deletions src/machine/instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ enum InstructionFlags : unsigned {
// TODO do we want to add those signals to the visualization?

IMF_RV64 = 1L << 24, /**< Mark instructions which are available in 64-bit mode only. */

// RV64/32F
IMF_ALU_REQ_RS_F = 1L << 25, /** < Execution phase/ALU/mem requires RS value in Float Reg*/
IMF_ALU_REQ_RT_F = 1L << 26, /**< Execution phase/ALU/mem requires RT value in Float Reg*/
IMF_ALU_REQ_RD_F = 1L << 27, /**< Execution phase/ALU/mem requires RD value in Float Reg*/
};

/**
Expand Down
2 changes: 1 addition & 1 deletion src/machine/machineconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ enum ConfigPresets {
};

constexpr ConfigIsaWord config_isa_word_default = ConfigIsaWord::byChar('E') | ConfigIsaWord::byChar('I') |
ConfigIsaWord::byChar('A') |ConfigIsaWord::byChar('M');
ConfigIsaWord::byChar('A') | ConfigIsaWord::byChar('M') | ConfigIsaWord::byChar('F');

constexpr ConfigIsaWord config_isa_word_fixed = ConfigIsaWord::byChar('E') | ConfigIsaWord::byChar('I');

Expand Down
5 changes: 5 additions & 0 deletions src/machine/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,10 @@ struct DecodeInterstage {
bool memwrite = false; // If memory should write input
bool alusrc = false; // If second value to alu is immediate value (rt used otherwise)
bool regwrite = false; // If output should be written back to register
bool regwrite_fp = false; // If output should be written back to floating point register
bool alu_req_rs = false; // requires rs value for ALU
bool alu_req_rt = false; // requires rt value for ALU or SW
bool alu_fp = false; // ALU operation is floating point
bool branch_bxx = false; // branch instruction
bool branch_jal = false; // jump
bool branch_val = false; // negate branch condition
Expand Down Expand Up @@ -170,6 +172,8 @@ struct ExecuteInterstage {
bool memread = false;
bool memwrite = false;
bool regwrite = false;
bool regwrite_fp = false;
bool alu_fp = false;
bool is_valid = false;
bool branch_bxx = false;
bool branch_jal = false;
Expand Down Expand Up @@ -243,6 +247,7 @@ struct MemoryInterstage {
RegisterId num_rd = 0;
bool memtoreg = false;
bool regwrite = false;
bool regwrite_fp = false;
bool is_valid = false;
bool csr_written = false;

Expand Down
6 changes: 5 additions & 1 deletion src/machine/register_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ class RegisterValue {

[[nodiscard]] constexpr inline int32_t as_i32() const { return (int32_t)data; };

[[nodiscard]] constexpr inline uint32_t as_u32() const { return (uint32_t)data; };
[[nodiscard]] constexpr inline uint32_t as_u32() const { return (uint32_t)data; };

[[nodiscard]] constexpr inline float as_f32() const { union { uint32_t u; float f; } u = {(uint32_t)data}; return u.f; };

[[nodiscard]] constexpr inline int64_t as_i64() const { return (int64_t)data; };

Expand All @@ -97,6 +99,8 @@ class RegisterValue {

constexpr explicit operator uint32_t() const { return as_u32(); };

constexpr explicit operator float() const { return as_f32(); };

constexpr explicit operator int64_t() const { return as_i64(); };

constexpr explicit operator uint64_t() const { return as_u64(); };
Expand Down
15 changes: 15 additions & 0 deletions src/machine/registers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Registers::Registers() : QObject() {
Registers::Registers(const Registers &orig) : QObject() {
this->pc = orig.read_pc();
this->gp = orig.gp;
this->fp = orig.fp;
}

Address Registers::read_pc() const {
Expand Down Expand Up @@ -54,6 +55,17 @@ void Registers::write_gp(RegisterId reg, RegisterValue value) {
emit gp_update(reg, value);
}

RegisterValue Registers::read_fp(RegisterId reg) const {
RegisterValue value = this->fp.at(reg);
emit gp_read(reg, value);
return value;
}

void Registers::write_fp(RegisterId reg, RegisterValue value) {
this->fp.at(reg) = value;
emit fp_update(reg, value);
}

bool Registers::operator==(const Registers &c) const {
if (read_pc() != c.read_pc()) { return false; }
if (this->gp != c.gp) { return false; }
Expand All @@ -69,6 +81,9 @@ void Registers::reset() {
for (int i = 1; i < 32; i++) {
write_gp(i, 0);
}
for (int i = 1; i < 32; i++) {
write_fp(i, 0);
}
write_gp(2_reg, SP_INIT.get_raw()); // initialize to safe RAM area -
// corresponds to Linux
}
Loading