Initial release of CAR
This commit is contained in:
209
include/defs.h
Normal file
209
include/defs.h
Normal file
@ -0,0 +1,209 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user