Files
CAR/operations.c

215 lines
3.9 KiB
C

/*
* Source file for register operations.
*
* CAR (Cool ARM Ripoff) copyright (c) 2026 David J Goeke. All rights reserved.
* Unauthorized (re)distribution is prohibited.
*/
#include "include/defs.h"
DEFINE_OP(add)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
state->gprs[dest] = state->gprs[src1] + state->gprs[src2];
OP_RETURN_NORMAL
}
DEFINE_OP(sub)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
state->gprs[dest] = state->gprs[src1] - state->gprs[src2];
OP_RETURN_NORMAL
}
DEFINE_OP(mul)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
state->gprs[dest] = state->gprs[src1] * state->gprs[src2];
OP_RETURN_NORMAL
}
DEFINE_OP(divide)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
if (src1 == 0 || src2 == 0)
{
state->flags |= FLAG_DIVISION_ERROR;
OP_RETURN_NORMAL
}
state->gprs[dest] = state->gprs[src1] / state->gprs[src2];
OP_RETURN_NORMAL
}
DEFINE_OP(modulus)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
if (src1 == 0 || src2 == 0)
{
state->flags |= FLAG_DIVISION_ERROR;
OP_RETURN_NORMAL
}
state->gprs[dest] = state->gprs[src1] % state->gprs[src2];
OP_RETURN_NORMAL
}
DEFINE_OP(shl)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
state->gprs[dest] = state->gprs[src1] << state->gprs[src2];
OP_RETURN_NORMAL
}
DEFINE_OP(shr)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
state->gprs[dest] = state->gprs[src1] >> state->gprs[src2];
OP_RETURN_NORMAL
}
DEFINE_OP(ahr)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
state->gprs[dest] = (uint32_t) ((int32_t) state->gprs[src1]) >> state->gprs[src2];
OP_RETURN_NORMAL
}
static uint32_t rotr32(uint32_t x, uint32_t n)
{
n &= 31; // Ensure 0 <= n < 32
return (x >> n) | (x << ((32 - n) & 31));
}
DEFINE_OP(ror)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
state->gprs[dest] = rotr32(state->gprs[src1], state->gprs[src2]);
OP_RETURN_NORMAL
}
DEFINE_OP(band)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
state->gprs[dest] = state->gprs[src1] & state->gprs[src2];
OP_RETURN_NORMAL
}
DEFINE_OP(bor)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
state->gprs[dest] = state->gprs[src1] | state->gprs[src2];
OP_RETURN_NORMAL
}
DEFINE_OP(bxor)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
state->gprs[dest] = state->gprs[src1] ^ state->gprs[src2];
OP_RETURN_NORMAL
}
DEFINE_OP(bnot)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t dest = i.dest;
uint8_t src1 = i.src1;
state->gprs[dest] = ~(state->gprs[src1]);
OP_RETURN_NORMAL
}
DEFINE_OP(xchg)
{
register_instruction_t i = convert_raw2register(ri);
uint8_t src1 = i.src1;
uint8_t src2 = i.src2;
// Truthfully we could use XORs here, but it's not really faster, so there is no real point,
// along with the fact that if both values are the same the result is zeroed out.
uint8_t temp = src1;
state->gprs[src1] = state->gprs[src2];
state->gprs[src2] = state->gprs[temp];
OP_RETURN_NORMAL
}