#ifndef _CAR_INCLUDE_DEFS_H #define _CAR_INCLUDE_DEFS_H #include #include #include #include //#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