pvbemu/core/cpu.c

606 lines
18 KiB
C
Raw Normal View History

2021-09-06 00:09:15 +00:00
/* This file is included into vb.c and cannot be compiled on its own. */
#ifdef VBAPI
/********************************* Constants *********************************/
2024-10-10 23:35:16 +00:00
/* Operation IDs */
#define CPU_HALTING 0
#define CPU_FATAL 1
#define CPU_FETCH 2
#define CPU_ILLEGAL 3
#define CPU_BITSTRING 4
#define CPU_FLOATENDO 5
#define CPU_DOWN 6
#define CPU_BITWISE 7
#define CPU_UP 8
#define CPU_ADD 9
#define CPU_ADDF_S 10
#define CPU_ADDI 11
#define CPU_AND 12
#define CPU_ANDI 13
#define CPU_BCOND 14
#define CPU_CAXI 15
#define CPU_CLI 16
#define CPU_CMP 17
#define CPU_CMPF_S 18
#define CPU_CVT_SW 19
#define CPU_CVT_WS 20
#define CPU_DIV 21
#define CPU_DIVF_S 22
#define CPU_DIVU 23
#define CPU_HALT 24
#define CPU_IN_B 25
#define CPU_IN_H 26
#define CPU_IN_W 27
#define CPU_JAL 28
#define CPU_JMP 29
#define CPU_JR 30
#define CPU_LD_B 31
#define CPU_LD_H 32
#define CPU_LD_W 33
#define CPU_LDSR 34
#define CPU_MOV 35
#define CPU_MOVEA 36
#define CPU_MOVHI 37
#define CPU_MPYHW 38
#define CPU_MUL 39
#define CPU_MULF_S 40
#define CPU_MULU 41
#define CPU_NOT 42
#define CPU_OR 43
#define CPU_ORI 44
#define CPU_OUT_B 45
#define CPU_OUT_H 46
#define CPU_OUT_W 47
#define CPU_RETI 48
#define CPU_REV 49
#define CPU_SAR 50
#define CPU_SEI 51
#define CPU_SETF 52
#define CPU_SHL 53
#define CPU_SHR 54
#define CPU_ST_B 55
#define CPU_ST_H 56
#define CPU_ST_W 57
#define CPU_STSR 58
#define CPU_SUB 59
#define CPU_SUBF_S 60
#define CPU_TRAP 61
#define CPU_TRNC_SW 62
#define CPU_XB 63
#define CPU_XH 64
#define CPU_XOR 65
#define CPU_XORI 66
/* Abstract operand types */
#define CPU_IMP(x) -x-1
#define CPU_DISP9 1
#define CPU_DISP26 2
#define CPU_IMM16S 3
#define CPU_IMM16U 4
#define CPU_IMM5S 5
#define CPU_IMM5U 6
#define CPU_MEM 7
#define CPU_REG1 8
#define CPU_REG2 9
/* Functional operand types */
#define CPU_LITERAL 0
#define CPU_MEMORY 1
#define CPU_REGISTER 2
/* Bit string operations */
#define CPU_AND_BS 0
#define CPU_ANDN_BS 1
#define CPU_MOV_BS 2
#define CPU_NOT_BS 3
#define CPU_OR_BS 4
#define CPU_ORN_BS 5
#define CPU_XOR_BS 6
#define CPU_XORN_BS 7
/* Instruction code lengths by opcode */
static const uint8_t INST_LENGTHS[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2
};
2021-09-19 01:31:40 +00:00
2021-09-06 00:09:15 +00:00
2024-10-10 23:35:16 +00:00
/********************************** Macros ***********************************/
2021-09-06 00:09:15 +00:00
2024-10-10 23:35:16 +00:00
/* Master clocks per CPU cycles */
#define cpuClocks(x) x
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Shorthand */
#define auxData sim->cpu.aux.data
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/******************************** Lookup Data ********************************/
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Opdefs by opcode */
static const uint8_t OPDEFS[] = {
CPU_MOV , CPU_ADD , CPU_SUB , CPU_CMP , /* 000000 */
CPU_SHL , CPU_SHR , CPU_JMP , CPU_SAR ,
CPU_MUL , CPU_DIV , CPU_MULU , CPU_DIVU ,
CPU_OR , CPU_AND , CPU_XOR , CPU_NOT ,
CPU_MOV , CPU_ADD , CPU_SETF , CPU_CMP , /* 010000 */
CPU_SHL , CPU_SHR , CPU_CLI , CPU_SAR ,
CPU_TRAP , CPU_RETI , CPU_HALT , CPU_ILLEGAL ,
CPU_LDSR , CPU_STSR , CPU_SEI , CPU_BITSTRING,
CPU_BCOND, CPU_BCOND, CPU_BCOND , CPU_BCOND , /* 100000 */
CPU_BCOND, CPU_BCOND, CPU_BCOND , CPU_BCOND ,
CPU_MOVEA, CPU_ADDI , CPU_JR , CPU_JAL ,
CPU_ORI , CPU_ANDI , CPU_XORI , CPU_MOVHI ,
CPU_LD_B , CPU_LD_H , CPU_ILLEGAL , CPU_LD_W , /* 110000 */
CPU_ST_B , CPU_ST_H , CPU_ILLEGAL , CPU_ST_W ,
CPU_IN_B , CPU_IN_H , CPU_CAXI , CPU_IN_W ,
CPU_OUT_B, CPU_OUT_H, CPU_FLOATENDO, CPU_OUT_W
};
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Opdefs by bit string sub-opcode */
static const uint8_t OPDEFS_BITSTRING[] = {
CPU_UP , CPU_DOWN , CPU_UP , CPU_DOWN , /* 00000 */
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL,
CPU_BITWISE, CPU_BITWISE, CPU_BITWISE, CPU_BITWISE, /* 01000 */
CPU_BITWISE, CPU_BITWISE, CPU_BITWISE, CPU_BITWISE,
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, /* 10000 */
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL,
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, /* 11000 */
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL
};
2023-03-11 00:44:57 +00:00
2024-10-10 23:35:16 +00:00
/* Opdefs by floating-point/Nintendo sub-opcodes */
static const uint8_t OPDEFS_FLOATENDO[] = {
CPU_CMPF_S , CPU_ILLEGAL, CPU_CVT_WS , CPU_CVT_SW , /* 000000 */
CPU_ADDF_S , CPU_SUBF_S , CPU_MULF_S , CPU_DIVF_S ,
CPU_XB , CPU_XH , CPU_REV , CPU_TRNC_SW,
CPU_MPYHW , CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL,
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, /* 010000 */
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL,
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL,
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL,
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, /* 100000 */
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL,
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL,
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL,
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, /* 110000 */
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL,
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL,
CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL, CPU_ILLEGAL
};
2023-03-11 00:44:57 +00:00
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/***************************** Callback Handlers *****************************/
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Prepare to execute an instruction */
#ifndef VB_DIRECT_EXECUTE
#define VB_ON_EXECUTE sim->onExecute
#else
extern int vbxOnExecute(VB *, uint32_t, const uint16_t *, int);
#define VB_ON_EXECUTE vbxOnExecute
#endif
static int cpuExecute(VB *sim) {
return
sim->onExecute != NULL &&
VB_ON_EXECUTE(sim, sim->cpu.pc, sim->cpu.code, sim->cpu.length)
;
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
#undef VB_ON_EXECUTE
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Read a value from the memory bus */
#ifndef VB_DIRECT_READ
#define VB_ON_READ sim->onRead
#else
extern int vbxOnRead(VB *, uint32_t, int, int32_t *, uint32_t *);
#define VB_ON_READ vbxOnRead
#endif
2023-03-11 01:00:45 +00:00
static int cpuRead(VB *sim, uint32_t address, int type, int32_t *value) {
2024-10-10 23:35:16 +00:00
uint32_t cycles = 4; /* TODO: Research this */
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Retrieve the value from the simulation state directly */
busRead(sim, address, type, value);
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Invoke the callback if available */
if (
sim->onRead != NULL &&
VB_ON_READ(sim, address, type, value, &cycles)
) return 1;
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Update state */
sim->cpu.clocks += cpuClocks(cycles);
2021-09-19 01:31:40 +00:00
return 0;
}
2024-10-10 23:35:16 +00:00
#undef VB_ON_READ
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Fetch a code unit from the memory bus */
#ifndef VB_DIRECT_FETCH
#define VB_ON_FETCH sim->onFetch
#else
extern int vbxOnFetch(VB *, int, uint32_t, int32_t *, uint32_t *);
#define VB_ON_FETCH vbxOnFetch
#endif
static int cpuReadFetch(VB *sim, int fetch, uint32_t address, int32_t *value) {
uint32_t cycles = 0;
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Retrieve the value from the simulation state directly */
busRead(sim, address, VB_U16, value);
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Invoke the callback if available */
if (
sim->onFetch != NULL &&
VB_ON_FETCH(sim, fetch, address, value, &cycles)
) return 1;
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Update state */
sim->cpu.clocks += cpuClocks(cycles);
2023-03-11 00:44:57 +00:00
return 0;
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
#undef VB_ON_FETCH
/* Write a value to the memory bus */
#ifndef VB_DIRECT_WRITE
#define VB_ON_WRITE sim->onWrite
#else
extern int vbxOnWrite(VB *, uint32_t, int, int32_t *, uint32_t *, int *);
#define VB_ON_WRITE vbxOnWrite
#endif
static int cpuWrite(VB *sim, uint32_t address, int type, int32_t value) {
int cancel = 0;
uint32_t cycles = 3; /* TODO: Research this */
/* Invoke the callback if available */
if (
sim->onWrite != NULL &&
VB_ON_WRITE(sim, address, type, &value, &cycles, &cancel)
) return 1;
/* Write the value to the simulation state directly */
if (!cancel)
busWrite(sim, address, type, value, 0);
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Update state */
sim->cpu.clocks += cpuClocks(cycles);
return 0;
2023-03-11 00:44:57 +00:00
}
2024-10-10 23:35:16 +00:00
#undef VB_ON_WRITE
2021-09-20 21:29:00 +00:00
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/****************************** Pipeline Stages ******************************/
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Fetch the code bits for the next instruction */
static int cpuFetch(VB *sim) {
int32_t value;
switch (sim->cpu.step) {
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
case 0:
sim->cpu.pc = sim->cpu.nextPC;
/* Fallthrough */
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
case 1:
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Retrieve the first code unit */
if (cpuReadFetch(sim, 0, sim->cpu.pc, &value)) {
sim->cpu.step = 1;
return 1;
}
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Update state */
sim->cpu.code[0] = value;
sim->cpu.length = INST_LENGTHS[value >> 10 & 63];
sim->cpu.step = 3 - sim->cpu.length;
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Wait any clocks taken */
if (sim->cpu.clocks != 0)
return 0;
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Skip fetching a second code unit */
if (sim->cpu.length == 1)
goto Step3;
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Fallthrough */
case 2:
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Retrieve the second code unit */
if (cpuReadFetch(sim, 1, sim->cpu.pc + 2, &value))
return 1;
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Update state */
sim->cpu.code[1] = value;
sim->cpu.step = 3;
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Wait any clocks taken */
if (sim->cpu.clocks != 0)
return 0;
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Fallthrough */
case 3: Step3:
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Prepare to execute the instruction */
if (cpuExecute(sim))
return 1;
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Select operation definition */
sim->cpu.operation = OPDEFS[sim->cpu.code[0] >> 10];
switch (sim->cpu.operation) {
case CPU_BITSTRING:
sim->cpu.operation =
OPDEFS_BITSTRING[sim->cpu.code[0] & 31];
break;
case CPU_FLOATENDO:
sim->cpu.operation =
OPDEFS_FLOATENDO[sim->cpu.code[1] >> 10];
}
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Update state */
sim->cpu.step = 0;
2021-09-19 01:31:40 +00:00
2023-03-11 00:44:57 +00:00
}
return 0;
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/**************************** Instruction Helpers ****************************/
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Parse the immediate 16-bit sign-extended value */
static int32_t cpuGetImm16S(VB *sim) {
return SignExtend(sim->cpu.code[1], 16);
}
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Parse the immediate 16-bit zero-filled value */
static int32_t cpuGetImm16U(VB *sim) {
return sim->cpu.code[1];
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* Resolve the operand value for reg1 */
static int32_t cpuGetReg1(VB *sim) {
return sim->cpu.program[sim->cpu.code[0] & 31];
2023-03-11 00:44:57 +00:00
}
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Supply an operand value for reg2 */
static void cpuSetReg2(VB *sim, int32_t value) {
int reg2 = sim->cpu.code[0] >> 5 & 31;
if (reg2 != 0)
sim->cpu.program[reg2] = value;
2023-03-11 00:44:57 +00:00
}
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Memory access instruction */
static int cpuLD_IN(VB *sim, int type) {
switch (sim->cpu.step) {
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
case 0:
auxData.address = cpuGetReg1(sim) + cpuGetImm16S(sim);
/* Fallthrough */
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
case 1:
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Read the value from memory */
if (cpuRead(sim, auxData.address, type, &auxData.value)) {
sim->cpu.step = 1;
2023-03-11 00:44:57 +00:00
return 1;
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* Update state */
sim->cpu.clocks += cpuClocks(1);
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Wait for clocks taken */
sim->cpu.step = 2;
2021-09-19 01:31:40 +00:00
return 0;
2024-10-10 23:35:16 +00:00
case 2:
cpuSetReg2(sim, auxData.value);
sim->cpu.operation = CPU_FETCH;
sim->cpu.nextPC += sim->cpu.pc + 4;
sim->cpu.step = 0;
2023-03-11 00:44:57 +00:00
}
2021-09-19 01:31:40 +00:00
return 0;
}
2024-10-10 23:35:16 +00:00
/************************** Instruction Operations ***************************/
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* IN.B */
static int cpuIN_B(VB *sim) {
return cpuLD_IN(sim, VB_U8);
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* IN.H */
static int cpuIN_H(VB *sim) {
return cpuLD_IN(sim, VB_U16);
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* IN.W */
static int cpuIN_W(VB *sim) {
return cpuLD_IN(sim, VB_S32);
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* JMP */
static int cpuJMP(VB *sim) {
sim->cpu.nextPC = cpuGetReg1(sim) & 0xFFFFFFFE;
sim->cpu.clocks += cpuClocks(3);
sim->cpu.operation = CPU_FETCH;
/* TODO: Clear prefetch buffer */
2023-03-11 00:44:57 +00:00
return 0;
}
2021-09-19 19:36:30 +00:00
2024-10-10 23:35:16 +00:00
/* LD.B */
static int cpuLD_B(VB *sim) {
return cpuLD_IN(sim, VB_S8);
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* LD.H */
static int cpuLD_H(VB *sim) {
return cpuLD_IN(sim, VB_S16);
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* LD.W */
static int cpuLD_W(VB *sim) {
return cpuLD_IN(sim, VB_S32);
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* MOVEA */
static int cpuMOVEA(VB *sim) {
cpuSetReg2(sim, cpuGetReg1(sim) + cpuGetImm16S(sim));
sim->cpu.clocks += cpuClocks(1);
sim->cpu.operation = CPU_FETCH;
sim->cpu.nextPC = sim->cpu.pc + 4;
return 0;
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* MOVHI */
static int cpuMOVHI(VB *sim) {
cpuSetReg2(sim, cpuGetReg1(sim) + (cpuGetImm16U(sim) << 16));
sim->cpu.clocks += cpuClocks(1);
sim->cpu.operation = CPU_FETCH;
sim->cpu.nextPC = sim->cpu.pc + 4;
return 0;
2021-09-19 01:31:40 +00:00
}
2023-03-11 00:44:57 +00:00
2024-10-10 23:35:16 +00:00
/***************************** Library Functions *****************************/
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Process component */
static int cpuEmulate(VB *sim, uint32_t clocks) {
int brk;
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Process until there are clocks to wait */
for (;;) {
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* The next event is after the time remaining */
if (sim->cpu.clocks > clocks) {
sim->cpu.clocks -= clocks;
return 0;
2023-03-11 00:44:57 +00:00
}
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Advance forward the CPU's number of clocks */
if (sim->cpu.clocks != 0) {
clocks -= sim->cpu.clocks;
sim->cpu.clocks = 0;
2023-03-11 00:44:57 +00:00
}
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Processing by operation ID */
switch (sim->cpu.operation) {
case CPU_FETCH: brk = cpuFetch(sim); break;
case CPU_IN_B : brk = cpuIN_B (sim); break;
case CPU_IN_H : brk = cpuIN_H (sim); break;
case CPU_IN_W : brk = cpuIN_W (sim); break;
case CPU_JMP : brk = cpuJMP (sim); break;
case CPU_LD_B : brk = cpuLD_B (sim); break;
case CPU_LD_H : brk = cpuLD_H (sim); break;
case CPU_LD_W : brk = cpuLD_W (sim); break;
case CPU_MOVEA: brk = cpuMOVEA(sim); break;
case CPU_MOVHI: brk = cpuMOVHI(sim); break;
default: return -1; /* TODO: Temporary for debugging */
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* A callback requested a break */
if (brk)
2023-03-11 00:44:57 +00:00
return 1;
2021-09-19 01:31:40 +00:00
}
2023-03-11 00:44:57 +00:00
return 0;
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* Retrieve the value of a system register */
static uint32_t cpuGetSystemRegister(VB *sim, int index) {
switch (index) {
case VB_ADTRE: return sim->cpu.adtre;
case VB_CHCW : return sim->cpu.chcw.ice << 1;
case VB_ECR : return
(uint32_t) sim->cpu.ecr.fecc << 16 |
(uint32_t) sim->cpu.ecr.eicc;
case VB_EIPC : return sim->cpu.eipc;
case VB_EIPSW: return sim->cpu.eipsw;
case VB_FEPC : return sim->cpu.fepc;
case VB_FEPSW: return sim->cpu.fepsw;
case VB_PIR : return 0x00005346;
case VB_PSW : return
(uint32_t) sim->cpu.psw.i << 16 |
(uint32_t) sim->cpu.psw.np << 15 |
(uint32_t) sim->cpu.psw.ep << 14 |
(uint32_t) sim->cpu.psw.ae << 13 |
(uint32_t) sim->cpu.psw.id << 12 |
(uint32_t) sim->cpu.psw.fro << 9 |
(uint32_t) sim->cpu.psw.fiv << 8 |
(uint32_t) sim->cpu.psw.fzd << 7 |
(uint32_t) sim->cpu.psw.fov << 6 |
(uint32_t) sim->cpu.psw.fud << 5 |
(uint32_t) sim->cpu.psw.fpr << 4 |
(uint32_t) sim->cpu.psw.cy << 3 |
(uint32_t) sim->cpu.psw.ov << 2 |
(uint32_t) sim->cpu.psw.s << 1 |
(uint32_t) sim->cpu.psw.z;
case VB_TKCW : return 0x000000E0;
case 29 : return sim->cpu.sr29;
case 30 : return 0x00000004;
case 31 : return sim->cpu.sr31;
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
return 0x00000000; /* All others */
2023-03-11 00:44:57 +00:00
}
2021-09-19 01:31:40 +00:00
2024-10-10 23:35:16 +00:00
/* Specify a new value for a system register */
static uint32_t cpuSetSystemRegister(VB*sim,int index,uint32_t value,int debug){
switch (index) {
case VB_ADTRE: return sim->cpu.adtre = value & 0xFFFFFFFE;
case VB_CHCW :
/* TODO: Configure instruction cache */
sim->cpu.chcw.ice = value >> 1 & 1;
return value & 0x00000002;
case VB_ECR :
if (debug) {
sim->cpu.ecr.fecc = value >> 16;
sim->cpu.ecr.eicc = value;
}
return
(uint32_t) sim->cpu.ecr.fecc << 16 |
(uint32_t) sim->cpu.ecr.eicc;
case VB_EIPC : return sim->cpu.eipc = value & 0xFFFFFFFE;
case VB_EIPSW: return sim->cpu.eipsw = value & 0x000FF3FF;
case VB_FEPC : return sim->cpu.fepc = value & 0xFFFFFFFE;
case VB_FEPSW: return sim->cpu.fepsw = value & 0x000FF3FF;
case VB_PIR : return 0x00005346;
case VB_PSW :
sim->cpu.psw.i = value >> 16 & 0xF;
sim->cpu.psw.np = value >> 15 & 1;
sim->cpu.psw.ep = value >> 14 & 1;
sim->cpu.psw.ae = value >> 13 & 1;
sim->cpu.psw.id = value >> 12 & 1;
sim->cpu.psw.fro = value >> 9 & 1;
sim->cpu.psw.fiv = value >> 8 & 1;
sim->cpu.psw.fzd = value >> 7 & 1;
sim->cpu.psw.fov = value >> 6 & 1;
sim->cpu.psw.fud = value >> 5 & 1;
sim->cpu.psw.fpr = value >> 4 & 1;
sim->cpu.psw.cy = value >> 3 & 1;
sim->cpu.psw.ov = value >> 2 & 1;
sim->cpu.psw.s = value >> 1 & 1;
sim->cpu.psw.z = value & 1;
return value & 0x000FF3FF;
case VB_TKCW : return 0x000000E0;
case 29 : return sim->cpu.sr29 = value;
case 30 : return 0x00000004;
case 31 : return sim->cpu.sr31 = debug ? value :
*(int32_t *) &value < 0 ? (uint32_t) -*(int32_t *) &value : value;
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
return 0x00000000; /* All others */
2021-09-19 01:31:40 +00:00
}
2024-10-10 23:35:16 +00:00
/* Determine how many clocks are guaranteed to process */
static uint32_t cpuUntil(VB *sim, uint32_t clocks) {
return sim->cpu.clocks < clocks ? sim->cpu.clocks : clocks;
2023-03-11 00:44:57 +00:00
}
#endif /* VBAPI */