/* * 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 }