Implement instructions 0x024-0x03B
This commit is contained in:
452
Instr_020-03F.cpp
Normal file
452
Instr_020-03F.cpp
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
/**
|
||||||
|
* @brief AUTO-GENERATED by pygen.ipynb BUT editable by hand!
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <spider/runtime/cpu/CPU.hpp>
|
||||||
|
|
||||||
|
namespace spider {
|
||||||
|
|
||||||
|
void CPU::STB() {
|
||||||
|
// TODO: Implement STB
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size){
|
||||||
|
case 0b00: //byte
|
||||||
|
_dst->_u8 |= (1 << _src->_u8);
|
||||||
|
case 0b01: //short
|
||||||
|
_dst->_u16 |= (1 << _src->_u16);
|
||||||
|
case 0b10: //int
|
||||||
|
_dst->_u32 |= (1 << _src->_u32);
|
||||||
|
case 0b11: //long
|
||||||
|
_dst->_u64 |= (1 << _src->_u64);
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::CRB() {
|
||||||
|
// TODO: Implement CRB
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size){
|
||||||
|
case 0b00: //byte
|
||||||
|
_dst->_u8 &= ~(1 << _src->_u8);
|
||||||
|
case 0b01: //short
|
||||||
|
_dst->_u16 &= ~(1 << _src->_u16);
|
||||||
|
case 0b10: //int
|
||||||
|
_dst->_u32 &= ~(1 << _src->_u32);
|
||||||
|
case 0b11: //long
|
||||||
|
_dst->_u64 &= ~(1 << _src->_u64);
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::TSB() {
|
||||||
|
// TODO: Implement TSB
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size){
|
||||||
|
case 0b00: //byte
|
||||||
|
switch (((RF >> _src->_u8) & 1) != ((_dst->_u8 >> _src->_u8) & 1)){
|
||||||
|
case 1:
|
||||||
|
RF |= (1 << _src->_u8);
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
RF &= ~(1 << _src->_u8);
|
||||||
|
}
|
||||||
|
case 0b01: //short
|
||||||
|
switch (((RF >> _src->_u16) & 1) != ((_dst->_u16 >> _src->_u16) & 1)){
|
||||||
|
case 1:
|
||||||
|
RF |= (1 << _src->_u16);
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
RF &= ~(1 << _src->_u16);
|
||||||
|
}
|
||||||
|
case 0b10: //int
|
||||||
|
switch (((RF >> _src->_u32) & 1) != ((_dst->_u32 >> _src->_u32) & 1)){
|
||||||
|
case 1:
|
||||||
|
RF |= (1 << _src->_u32);
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
RF &= ~(1 << _src->_u32);
|
||||||
|
}
|
||||||
|
case 0b11: //long
|
||||||
|
switch (((RF >> _src->_u64) & 1) != ((_dst->_u64 >> _src->_u64) & 1)){
|
||||||
|
case 1:
|
||||||
|
RF |= (1 << _src->_u64);
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
RF &= ~(1 << _src->_u64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::BOOL() {
|
||||||
|
// TODO: Implement BOOL
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size){
|
||||||
|
case 0b00: //byte
|
||||||
|
_dst->_u8 = _dst != 0;
|
||||||
|
case 0b01: //short
|
||||||
|
_dst->_u16 = _dst != 0;
|
||||||
|
case 0b10: //int
|
||||||
|
_dst->_u32 = _dst != 0;
|
||||||
|
case 0b11: //long
|
||||||
|
_dst->_u64 = _dst != 0;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x024 — NOT: Tests Dst == 0, updates Equal Flag ──
|
||||||
|
void CPU::NOT() {
|
||||||
|
fetchOperDst();
|
||||||
|
bool isZero = false;
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: isZero = (_dst->_u8 == 0); break;
|
||||||
|
case 0b01: isZero = (_dst->_u16 == 0); break;
|
||||||
|
case 0b10: isZero = (_dst->_u32 == 0); break;
|
||||||
|
case 0b11: isZero = (_dst->_u64 == 0); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isZero) {
|
||||||
|
RF |= CPU::FLAG_EQUAL; // Si es 0, el resultado de !0 es true (1), actualizamos bandera
|
||||||
|
// Dependiendo de la implementación de BOOL, podrías querer guardar el resultado en Dst
|
||||||
|
_dst->_u64 = 1;
|
||||||
|
} else {
|
||||||
|
RF &= ~CPU::FLAG_EQUAL;
|
||||||
|
_dst->_u64 = 0;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x025 — AND
|
||||||
|
void CPU::AND() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: _dst->_u8 &= _src->_u8; break;
|
||||||
|
case 0b01: _dst->_u16 &= _src->_u16; break;
|
||||||
|
case 0b10: _dst->_u32 &= _src->_u32; break;
|
||||||
|
case 0b11: _dst->_u64 &= _src->_u64; break;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x026 — OR
|
||||||
|
void CPU::OR() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: _dst->_u8 |= _src->_u8; break;
|
||||||
|
case 0b01: _dst->_u16 |= _src->_u16; break;
|
||||||
|
case 0b10: _dst->_u32 |= _src->_u32; break;
|
||||||
|
case 0b11: _dst->_u64 |= _src->_u64; break;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x027 — XOR
|
||||||
|
void CPU::XOR() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: _dst->_u8 ^= _src->_u8; break;
|
||||||
|
case 0b01: _dst->_u16 ^= _src->_u16; break;
|
||||||
|
case 0b10: _dst->_u32 ^= _src->_u32; break;
|
||||||
|
case 0b11: _dst->_u64 ^= _src->_u64; break;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x028 — SHL
|
||||||
|
void CPU::SHL() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: _dst->_u8 <<= _src->_u8; break;
|
||||||
|
case 0b01: _dst->_u16 <<= _src->_u16; break;
|
||||||
|
case 0b10: _dst->_u32 <<= _src->_u32; break;
|
||||||
|
case 0b11: _dst->_u64 <<= _src->_u64; break;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x029 — SHR
|
||||||
|
void CPU::SHR() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: _dst->_u8 >>= _src->_u8; break;
|
||||||
|
case 0b01: _dst->_u16 >>= _src->_u16; break;
|
||||||
|
case 0b10: _dst->_u32 >>= _src->_u32; break;
|
||||||
|
case 0b11: _dst->_u64 >>= _src->_u64; break;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x02A — SSR
|
||||||
|
void CPU::SSR() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: _dst->_i8 >>= _src->_u8; break;
|
||||||
|
case 0b01: _dst->_i16 >>= _src->_u8; break;
|
||||||
|
case 0b10: _dst->_i32 >>= _src->_u8; break;
|
||||||
|
case 0b11: _dst->_i64 >>= _src->_u8; break;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x02B — ROL: Rotate Left ──
|
||||||
|
void CPU::ROL() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: _dst->_u8 = (_dst->_u8 << _src->_u8) | (_dst->_u8 >> (8 - _src->_u8)); break;
|
||||||
|
case 0b01: _dst->_u16 = (_dst->_u16 << _src->_u8) | (_dst->_u16 >> (16 - _src->_u8)); break;
|
||||||
|
case 0b10: _dst->_u32 = (_dst->_u32 << _src->_u8) | (_dst->_u32 >> (32 - _src->_u8)); break;
|
||||||
|
case 0b11: _dst->_u64 = (_dst->_u64 << _src->_u8) | (_dst->_u64 >> (64 - _src->_u8)); break;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x02C — ROR: Rotate Right ──
|
||||||
|
void CPU::ROR() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: _dst->_u8 = (_dst->_u8 >> _src->_u8) | (_dst->_u8 << (8 - _src->_u8)); break;
|
||||||
|
case 0b01: _dst->_u16 = (_dst->_u16 >> _src->_u8) | (_dst->_u16 << (16 - _src->_u8)); break;
|
||||||
|
case 0b10: _dst->_u32 = (_dst->_u32 >> _src->_u8) | (_dst->_u32 << (32 - _src->_u8)); break;
|
||||||
|
case 0b11: _dst->_u64 = (_dst->_u64 >> _src->_u8) | (_dst->_u64 << (64 - _src->_u8)); break;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x02D — CNT: Counts bits (# of 1's into Dst) ──
|
||||||
|
void CPU::CNT() {
|
||||||
|
fetchOperDst();
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: _dst->_u8 = __builtin_popcount(_dst->_u8); break;
|
||||||
|
case 0b01: _dst->_u16 = __builtin_popcount(_dst->_u16); break;
|
||||||
|
case 0b10: _dst->_u32 = __builtin_popcount(_dst->_u32); break;
|
||||||
|
case 0b11: _dst->_u64 = __builtin_popcountll(_dst->_u64); break;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x030 — EQ: Dst == Src into Dst ──
|
||||||
|
void CPU::EQ() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
bool res = false;
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: res = (_dst->_u8 == _src->_u8); break;
|
||||||
|
case 0b01: res = (_dst->_u16 == _src->_u16); break;
|
||||||
|
case 0b10: res = (_dst->_u32 == _src->_u32); break;
|
||||||
|
case 0b11: res = (_dst->_u64 == _src->_u64); break;
|
||||||
|
}
|
||||||
|
_dst->_u64 = res ? 1 : 0;
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x031 — NE: Dst != Src into Dst ──
|
||||||
|
void CPU::NE() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
bool res = false;
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: res = (_dst->_u8 != _src->_u8); break;
|
||||||
|
case 0b01: res = (_dst->_u16 != _src->_u16); break;
|
||||||
|
case 0b10: res = (_dst->_u32 != _src->_u32); break;
|
||||||
|
case 0b11: res = (_dst->_u64 != _src->_u64); break;
|
||||||
|
}
|
||||||
|
_dst->_u64 = res ? 1 : 0;
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x032 — GT: Dst > Src into Dst ──
|
||||||
|
void CPU::GT() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
bool res = false;
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: res = (_dst->_i8 > _src->_i8); break;
|
||||||
|
case 0b01: res = (_dst->_i16 > _src->_i16); break;
|
||||||
|
case 0b10: res = (_dst->_i32 > _src->_i32); break;
|
||||||
|
case 0b11: res = (_dst->_i64 > _src->_i64); break;
|
||||||
|
}
|
||||||
|
_dst->_u64 = res ? 1 : 0;
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x033 — GE: Dst >= Src into Dst ──
|
||||||
|
void CPU::GE() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
bool res = false;
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: res = (_dst->_i8 >= _src->_i8); break;
|
||||||
|
case 0b01: res = (_dst->_i16 >= _src->_i16); break;
|
||||||
|
case 0b10: res = (_dst->_i32 >= _src->_i32); break;
|
||||||
|
case 0b11: res = (_dst->_i64 >= _src->_i64); break;
|
||||||
|
}
|
||||||
|
_dst->_u64 = res ? 1 : 0;
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x034 — LT: Dst < Src into Dst ──
|
||||||
|
void CPU::LT() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
bool res = false;
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: res = (_dst->_i8 < _src->_i8); break;
|
||||||
|
case 0b01: res = (_dst->_i16 < _src->_i16); break;
|
||||||
|
case 0b10: res = (_dst->_i32 < _src->_i32); break;
|
||||||
|
case 0b11: res = (_dst->_i64 < _src->_i64); break;
|
||||||
|
}
|
||||||
|
_dst->_u64 = res ? 1 : 0;
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x035 — LE: Dst <= Src into Dst ──
|
||||||
|
void CPU::LE() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
bool res = false;
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: res = (_dst->_i8 <= _src->_i8); break;
|
||||||
|
case 0b01: res = (_dst->_i16 <= _src->_i16); break;
|
||||||
|
case 0b10: res = (_dst->_i32 <= _src->_i32); break;
|
||||||
|
case 0b11: res = (_dst->_i64 <= _src->_i64); break;
|
||||||
|
}
|
||||||
|
_dst->_u64 = res ? 1 : 0;
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x038 — JMP: Dst -> Instruction Register (PC) ──
|
||||||
|
// The IR adds 1 at the end, so we subtract 1 to compensate.
|
||||||
|
void CPU::JMP() {
|
||||||
|
fetchOperDst();
|
||||||
|
u64 target;
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: target = static_cast<u64>(_dst->_u8); break;
|
||||||
|
case 0b01: target = static_cast<u64>(_dst->_u16); break;
|
||||||
|
case 0b10: target = static_cast<u64>(_dst->_u32); break;
|
||||||
|
case 0b11: target = _dst->_u64; break;
|
||||||
|
}
|
||||||
|
RI = target - 1;
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x039 — JEQ: Jump if EQ flag is set ──
|
||||||
|
void CPU::JEQ() {
|
||||||
|
fetchOperDst();
|
||||||
|
if (RF & CPU::FLAG_EQUAL) {
|
||||||
|
u64 target;
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: target = static_cast<u64>(_dst->_u8); break;
|
||||||
|
case 0b01: target = static_cast<u64>(_dst->_u16); break;
|
||||||
|
case 0b10: target = static_cast<u64>(_dst->_u32); break;
|
||||||
|
case 0b11: target = _dst->_u64; break;
|
||||||
|
}
|
||||||
|
RI = target - 1;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x03A — JNE: Jumps if EQ flag is cleared ──
|
||||||
|
void CPU::JNE() {
|
||||||
|
fetchOperDst();
|
||||||
|
if (!(RF & CPU::FLAG_EQUAL)) {
|
||||||
|
u64 target;
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: target = static_cast<u64>(_dst->_u8); break;
|
||||||
|
case 0b01: target = static_cast<u64>(_dst->_u16); break;
|
||||||
|
case 0b10: target = static_cast<u64>(_dst->_u32); break;
|
||||||
|
case 0b11: target = _dst->_u64; break;
|
||||||
|
}
|
||||||
|
RI = target - 1;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x03B — JIF: Jumps if Src is booleanly true ──
|
||||||
|
void CPU::JIF() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
if (_src->_u64 != 0) {
|
||||||
|
u64 target;
|
||||||
|
switch(_size) {
|
||||||
|
case 0b00: target = static_cast<u64>(_dst->_u8); break;
|
||||||
|
case 0b01: target = static_cast<u64>(_dst->_u16); break;
|
||||||
|
case 0b10: target = static_cast<u64>(_dst->_u32); break;
|
||||||
|
case 0b11: target = _dst->_u64; break;
|
||||||
|
}
|
||||||
|
RI = target - 1;
|
||||||
|
}
|
||||||
|
(this->*_post)();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x03C — JMR: Dst + Instruction Register -> Instruction Register ──
|
||||||
|
void CPU::JMR() {
|
||||||
|
fetchOperDst();
|
||||||
|
i64 offset;
|
||||||
|
switch (_size) {
|
||||||
|
case 0b00: offset = static_cast<i64>(_dst->_i8); break; // 1 byte
|
||||||
|
case 0b01: offset = static_cast<i64>(_dst->_i16); break; // 2 bytes
|
||||||
|
case 0b10: offset = static_cast<i64>(_dst->_i32); break; // 4 bytes
|
||||||
|
case 0b11: offset = _dst->_i64; break; // 8 bytes
|
||||||
|
}
|
||||||
|
RI = static_cast<u64>(static_cast<i64>(RI) + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x03D — JER: Dst + Instruction Register -> Instruction Register IF Flags.EQ ──
|
||||||
|
void CPU::JER() {
|
||||||
|
fetchOperDst();
|
||||||
|
if (RF & CPU::FLAG_EQUAL) {
|
||||||
|
i64 offset;
|
||||||
|
switch (_size) {
|
||||||
|
case 0b00: offset = static_cast<i64>(_dst->_i8); break;
|
||||||
|
case 0b01: offset = static_cast<i64>(_dst->_i16); break;
|
||||||
|
case 0b10: offset = static_cast<i64>(_dst->_i32); break;
|
||||||
|
case 0b11: offset = _dst->_i64; break;
|
||||||
|
}
|
||||||
|
RI = static_cast<u64>(static_cast<i64>(RI) + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x03E — JNR: Dst + Instruction Register -> Instruction Register IF NOT Flags.EQ ──
|
||||||
|
void CPU::JNR() {
|
||||||
|
fetchOperDst();
|
||||||
|
if (!(RF & CPU::FLAG_EQUAL)) {
|
||||||
|
i64 offset;
|
||||||
|
switch (_size) {
|
||||||
|
case 0b00: offset = static_cast<i64>(_dst->_i8); break;
|
||||||
|
case 0b01: offset = static_cast<i64>(_dst->_i16); break;
|
||||||
|
case 0b10: offset = static_cast<i64>(_dst->_i32); break;
|
||||||
|
case 0b11: offset = _dst->_i64; break;
|
||||||
|
}
|
||||||
|
RI = static_cast<u64>(static_cast<i64>(RI) + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 0x03F — JIR: Dst + Instruction Register -> Instruction Register IF Src ──
|
||||||
|
void CPU::JIR() {
|
||||||
|
fetchOperSrc();
|
||||||
|
fetchOperDst();
|
||||||
|
if (_src->_u64 != 0) {
|
||||||
|
i64 offset;
|
||||||
|
switch (_size) {
|
||||||
|
case 0b00: offset = static_cast<i64>(_dst->_i8); break;
|
||||||
|
case 0b01: offset = static_cast<i64>(_dst->_i16); break;
|
||||||
|
case 0b10: offset = static_cast<i64>(_dst->_i32); break;
|
||||||
|
case 0b11: offset = _dst->_i64; break;
|
||||||
|
}
|
||||||
|
RI = static_cast<u64>(static_cast<i64>(RI) + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user