qemu-cr16/target/cr16c/cpu.h
2026-05-04 14:31:18 +02:00

137 lines
4 KiB
C

#ifndef QEMU_CR16C_CPU_H
#define QEMU_CR16C_CPU_H
#include "qemu/osdep.h"
#include "cpu-qom.h"
#include "exec/cpu-defs.h"
#include "hw/registerfields.h"
/* PSR define */
REG16(PSR, 0)
FIELD(PSR, C, 0, 1)
FIELD(PSR, T, 1, 1)
FIELD(PSR, L, 2, 1)
FIELD(PSR, U, 3, 1)
// bit 4 is reserved
FIELD(PSR, F, 5, 1)
FIELD(PSR, Z, 6, 1)
FIELD(PSR, N, 7, 1)
// bit 8 is reserved
FIELD(PSR, E, 9, 1)
FIELD(PSR, P, 10, 1)
FIELD(PSR, I, 11, 1)
// 12-15 are reserved as well
/* CFG define */
REG16(CFG, 0)
// bit 0, 1 are fixed 0
FIELD(CFG, DC, 2, 1)
FIELD(CFG, LDC, 3, 1)
FIELD(CFG, IC, 4, 1)
FIELD(CFG, LIC, 5, 1)
// bit 6, 7 are fixed 0
FIELD(CFG, ED, 8, 1)
FIELD(CFG, SR, 9, 1)
// bit 10-15 are reserved
#define CR16C_REG_COUNT 16
#define CR16C_FIRST_32B_REG 12
#define CR16C_REGNO_RA 14
#define CR16C_REGNO_SP 15
#define CPU_RESOLVING_TYPE TYPE_CR16C_CPU
// TODO: Interrupt mask?
// TODO: Instruction mask?
static const char cr16c_cpu_r_names[CR16C_REG_COUNT][8] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "ra", "sp"
};
typedef struct CPUArchState {
uint32_t pc;
uint32_t r[CR16C_REG_COUNT]; /* General purpose registers: 12x16-bit + 2x32-bit */
uint32_t psr_n; // Negative bit
uint32_t psr_z; // Zero bit
uint32_t psr_f; // Flag bit
uint32_t psr_l; // Low flag bit
uint32_t psr_c; // Carry bit
uint32_t psr_t; // Trace bit
uint32_t psr_u; // User mode bit
uint32_t psr_e; // local maskable interrupt Enable bit
uint32_t psr_p; // trace trap Pending bit
uint32_t psr_i; // global maskable Interrupt enable bit
uint32_t cfg_dc; // Data Cache bit
uint32_t cfg_ldc; // Lock Data Cache bit
uint32_t cfg_ic; // Instruction Cache bit
uint32_t cfg_lic; // Lock Instruction Cache bit
uint32_t cfg_ed; // Extended Dispatch bit
uint32_t cfg_sr; // Short Register bit
} CPUCR16CState;
struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
CPUCR16CState env;
};
int cr16c_print_insn(bfd_vma addr, disassemble_info *info);
static inline int cpu_interrupts_enabled(CPUCR16CState* env) {
return false; // TODO: Interrupts
}
void cr16c_translate_init(void);
bool cr16c_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr);
void cr16c_cpu_do_interrupt(CPUState *cpu);
void cr16c_cpu_setint(void *opaque, int irq, int level);
hwaddr cr16c_cpu_get_phys_page_debug(CPUState *cs, vaddr addr);
int cr16c_cpu_memory_rw_debug(CPUState *cs, vaddr addr, uint8_t *buf, int len, bool is_write);
void cr16c_debug_dump_state(CPUState *cs);
void cr16c_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb);
void cr16c_translate_code(CPUState *cs, TranslationBlock *tb,
int *max_insns, vaddr pc, void *host_pc);
void cr16c_restore_state_to_opc(CPUState *cpu, const TranslationBlock *tb,
const uint64_t *data);
static inline uint32_t cr16c_cpu_pack_psr(const CPUCR16CState *env)
{
uint32_t psr = 0;
psr = FIELD_DP32(psr, PSR, C, env->psr_c);
psr = FIELD_DP32(psr, PSR, T, env->psr_t);
psr = FIELD_DP32(psr, PSR, L, env->psr_l);
psr = FIELD_DP32(psr, PSR, U, env->psr_u);
psr = FIELD_DP32(psr, PSR, N, env->psr_n);
psr = FIELD_DP32(psr, PSR, Z, env->psr_z);
psr = FIELD_DP32(psr, PSR, F, env->psr_f);
psr = FIELD_DP32(psr, PSR, E, env->psr_e);
psr = FIELD_DP32(psr, PSR, P, env->psr_p);
psr = FIELD_DP32(psr, PSR, I, env->psr_i);
return psr;
}
static inline uint32_t cr16c_cpu_pack_cfg(const CPUCR16CState *env)
{
uint32_t cfg = 0;
cfg = FIELD_DP32(cfg, CFG, DC, env->cfg_dc);
cfg = FIELD_DP32(cfg, CFG, LDC, env->cfg_ldc);
cfg = FIELD_DP32(cfg, CFG, IC, env->cfg_ic);
cfg = FIELD_DP32(cfg, CFG, LIC, env->cfg_lic);
cfg = FIELD_DP32(cfg, CFG, ED, env->cfg_ed);
cfg = FIELD_DP32(cfg, CFG, SR, env->cfg_sr);
return cfg;
}
#endif // !QEMU_CR16C_CPU_H