Files
CAR/include/defs.h
2026-07-16 13:46:13 -05:00

210 lines
4.3 KiB
C

#ifndef _CAR_INCLUDE_DEFS_H
#define _CAR_INCLUDE_DEFS_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
//#define _DEBUG
typedef struct
{
uint32_t gprs[32]; // register 31 is the control register (change maybe?)
uint32_t flags;
uint32_t pc;
uint32_t sp;
uint32_t* memory;
size_t memory_size; // Never let addresses go past this, or we wil get a segsev
} pstate_t;
int processor_start(pstate_t* state);
void dump_regs(pstate_t* s);
#define FLAG_CARRY (1 << 0)
#define FLAG_SIGN (1 << 1)
#define FLAG_OVERFLOW (1 << 2)
#define FLAG_ZERO (1 << 3)
#define FLAG_INTERRUPTS (1 << 4)
#define FLAG_ERROR (1 << 5)
#define FLAG_DIRECTION_ERROR (1 << 6)
#define FLAG_DIVISION_ERROR (1 << 7)
typedef uint32_t raw_instruction_t;
/*
Instruction encoding for misc operations:
instruction group: bits 0 to 1 (2 bits) {NOTE: for misc operations, should be set to 0b00}
opcode: bits 2 to 7 (6 bits)
imm: bits 8 to 31 {NOTE: depending on the opcode, could be an address, or a register indirection}
Instruction encoding for register operations:
instruction group: bits 0 to 1 (2 bits) {NOTE: for register operations, should be set to 0b01}
opcode: bits 2 to 8 (7 bits)
dest: bits 9 to 14 (5 bits)
src1 bits 15 to 20 (5 bits)
src2 bits 21 to 26 (5 bits)
all other bits unused, however should be set to zero
Instruction encoding for load/store operations:
instruction group: bits 0 to 1 (2 bits) {NOTE: for load/store operations, should be set to 0b10}
opcode: bits 2 to 5 (4 bits)
register: bits 6 to 10 (5 bits)
imm: bits 11 to 31 {NOTE: depending on the opcode, could be an address, or register indirect, or an immediate}
is be one of:
A) signed 21-bit offset from PC
B) signed 21-bit offset from SP
C) base register (5 bits) and a 16-bit signed offset from PC
D) signed 21 bit immediate
*/
typedef struct
{
uint8_t opcode;
uint32_t imm;
} misc_instruction_t;
typedef struct
{
uint8_t opcode;
uint8_t dest;
uint8_t src1;
uint8_t src2;
} register_instruction_t;
typedef struct
{
uint8_t opcode;
uint8_t reg;
uint32_t imm;
} ls_instruction_t;
misc_instruction_t convert_raw2misc(raw_instruction_t* r);
register_instruction_t convert_raw2register(raw_instruction_t* r);
ls_instruction_t convert_raw2ls(raw_instruction_t* r);
static inline uint8_t get_instruction_group(raw_instruction_t* r)
{
return ((uint32_t) (*r)) >> 30;
}
#define get_reg_from_imm(x) ((x & 0x1F0000) >> 16)
#define get_imm_from_imm(x) (x & ~0x1F0000)
typedef struct
{
bool do_inc_pc;
bool exiting_error;
} op_return_t;
#define DEFINE_OP(name) \
op_return_t op_##name(raw_instruction_t* ri, \
pstate_t* state)
static const op_return_t _OP_RETV_NORMAL = { .do_inc_pc = true, .exiting_error = false };
static const op_return_t _OP_RETV_EXITING_ERROR = { .do_inc_pc = true, .exiting_error = true };
#define OP_RETURN_NORMAL return _OP_RETV_NORMAL;
#define OP_RETURN_EXITING_ERROR return _OP_RETV_EXITING_ERROR;
typedef op_return_t (*op)(raw_instruction_t*, pstate_t*);
static DEFINE_OP(nop)
{
OP_RETURN_NORMAL
}
static const op misc_ops[] =
{
op_nop,
};
static const size_t NUM_MISC_OPCODES = sizeof(misc_ops) / sizeof(misc_ops[0]);
DEFINE_OP(add);
DEFINE_OP(sub);
DEFINE_OP(mul);
DEFINE_OP(divide);
DEFINE_OP(modulus);
DEFINE_OP(shl);
DEFINE_OP(shr);
DEFINE_OP(ahr);
DEFINE_OP(ror);
DEFINE_OP(band);
DEFINE_OP(bor);
DEFINE_OP(bxor);
DEFINE_OP(bnot);
DEFINE_OP(xchg);
static const op reg_ops[] =
{
op_add,
op_sub,
op_mul,
op_divide,
op_modulus,
op_shl,
op_shr,
op_ahr, // Arithmetic sHift Right
op_ror,
op_band,
op_bor,
op_bxor,
op_bnot,
op_xchg,
};
static const size_t NUM_REG_OPCODES = sizeof(reg_ops) / sizeof(reg_ops[0]);
DEFINE_OP(ldr);
DEFINE_OP(lds);
DEFINE_OP(ldb);
DEFINE_OP(ldi);
DEFINE_OP(str);
DEFINE_OP(sts);
DEFINE_OP(stb);
DEFINE_OP(ldh);
DEFINE_OP(sti);
DEFINE_OP(stj);
static const op ls_ops[] =
{
op_ldr,
op_lds,
op_ldb,
op_ldi,
op_str,
op_sts,
op_stb,
op_ldh,
op_sti,
op_stj,
};
static const size_t NUM_LS_OPCODES = sizeof(ls_ops) / sizeof(ls_ops[0]);
#endif // _CAR_INCLUDE_DEFS_H