Introduce pseudo-halt
This commit is contained in:
		
							parent
							
								
									8f9950f39e
								
							
						
					
					
						commit
						226da7a5b3
					
				
							
								
								
									
										228
									
								
								core/cpu.c
								
								
								
								
							
							
						
						
									
										228
									
								
								core/cpu.c
								
								
								
								
							| 
						 | 
				
			
			@ -10,97 +10,86 @@
 | 
			
		|||
#define CPU_HALTING   1
 | 
			
		||||
#define CPU_FATAL     2
 | 
			
		||||
#define CPU_FETCH     3
 | 
			
		||||
#define CPU_ILLEGAL   4
 | 
			
		||||
#define CPU_BITSTRING 5
 | 
			
		||||
#define CPU_FLOATENDO 6
 | 
			
		||||
#define CPU_ADD_IMM   7
 | 
			
		||||
#define CPU_ADD_REG   8
 | 
			
		||||
#define CPU_ADDF_S    9
 | 
			
		||||
#define CPU_ADDI     10
 | 
			
		||||
#define CPU_AND      11
 | 
			
		||||
#define CPU_ANDI     12
 | 
			
		||||
#define CPU_BCOND    13
 | 
			
		||||
#define CPU_CAXI     14
 | 
			
		||||
#define CPU_CLI      15
 | 
			
		||||
#define CPU_CMP_IMM  16
 | 
			
		||||
#define CPU_CMP_REG  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_IMM  35
 | 
			
		||||
#define CPU_MOV_REG  36
 | 
			
		||||
#define CPU_MOVEA    37
 | 
			
		||||
#define CPU_MOVHI    38
 | 
			
		||||
#define CPU_MPYHW    39
 | 
			
		||||
#define CPU_MUL      40
 | 
			
		||||
#define CPU_MULF_S   41
 | 
			
		||||
#define CPU_MULU     42
 | 
			
		||||
#define CPU_NOT      43
 | 
			
		||||
#define CPU_OR       44
 | 
			
		||||
#define CPU_ORI      45
 | 
			
		||||
#define CPU_OUT_B    46
 | 
			
		||||
#define CPU_OUT_H    47
 | 
			
		||||
#define CPU_OUT_W    48
 | 
			
		||||
#define CPU_RETI     49
 | 
			
		||||
#define CPU_REV      50
 | 
			
		||||
#define CPU_SAR_IMM  51
 | 
			
		||||
#define CPU_SAR_REG  52
 | 
			
		||||
#define CPU_SCH0BSD  53
 | 
			
		||||
#define CPU_SCH0BSU  54
 | 
			
		||||
#define CPU_SCH1BSD  55
 | 
			
		||||
#define CPU_SCH1BSU  56
 | 
			
		||||
#define CPU_SEI      57
 | 
			
		||||
#define CPU_SETF     58
 | 
			
		||||
#define CPU_SHL_IMM  59
 | 
			
		||||
#define CPU_SHL_REG  60
 | 
			
		||||
#define CPU_SHR_IMM  61
 | 
			
		||||
#define CPU_SHR_REG  62
 | 
			
		||||
#define CPU_ST_B     63
 | 
			
		||||
#define CPU_ST_H     64
 | 
			
		||||
#define CPU_ST_W     65
 | 
			
		||||
#define CPU_STSR     66
 | 
			
		||||
#define CPU_SUB      67
 | 
			
		||||
#define CPU_SUBF_S   68
 | 
			
		||||
#define CPU_TRAP     69
 | 
			
		||||
#define CPU_TRNC_SW  70
 | 
			
		||||
#define CPU_XB       71
 | 
			
		||||
#define CPU_XH       72
 | 
			
		||||
#define CPU_XOR      73
 | 
			
		||||
#define CPU_XORI     74
 | 
			
		||||
#define CPU_ANDBSU   75 /* Keep bit string ALU commands sequential */
 | 
			
		||||
#define CPU_ANDNBSU  76
 | 
			
		||||
#define CPU_MOVBSU   77
 | 
			
		||||
#define CPU_NOTBSU   78
 | 
			
		||||
#define CPU_ORBSU    79
 | 
			
		||||
#define CPU_ORNBSU   80
 | 
			
		||||
#define CPU_XORBSU   81
 | 
			
		||||
#define CPU_XORNBSU  82
 | 
			
		||||
 | 
			
		||||
/* 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
 | 
			
		||||
#define CPU_PHALT     4
 | 
			
		||||
#define CPU_ILLEGAL   5
 | 
			
		||||
#define CPU_BITSTRING 6
 | 
			
		||||
#define CPU_FLOATENDO 7
 | 
			
		||||
#define CPU_ADD_IMM   8
 | 
			
		||||
#define CPU_ADD_REG   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_IMM  17
 | 
			
		||||
#define CPU_CMP_REG  18
 | 
			
		||||
#define CPU_CMPF_S   19
 | 
			
		||||
#define CPU_CVT_SW   20
 | 
			
		||||
#define CPU_CVT_WS   21
 | 
			
		||||
#define CPU_DIV      22
 | 
			
		||||
#define CPU_DIVF_S   23
 | 
			
		||||
#define CPU_DIVU     24
 | 
			
		||||
#define CPU_HALT     25
 | 
			
		||||
#define CPU_IN_B     26
 | 
			
		||||
#define CPU_IN_H     27
 | 
			
		||||
#define CPU_IN_W     28
 | 
			
		||||
#define CPU_JAL      29
 | 
			
		||||
#define CPU_JMP      30
 | 
			
		||||
#define CPU_JR       31
 | 
			
		||||
#define CPU_LD_B     32
 | 
			
		||||
#define CPU_LD_H     33
 | 
			
		||||
#define CPU_LD_W     34
 | 
			
		||||
#define CPU_LDSR     35
 | 
			
		||||
#define CPU_MOV_IMM  36
 | 
			
		||||
#define CPU_MOV_REG  37
 | 
			
		||||
#define CPU_MOVEA    38
 | 
			
		||||
#define CPU_MOVHI    39
 | 
			
		||||
#define CPU_MPYHW    40
 | 
			
		||||
#define CPU_MUL      41
 | 
			
		||||
#define CPU_MULF_S   42
 | 
			
		||||
#define CPU_MULU     43
 | 
			
		||||
#define CPU_NOT      44
 | 
			
		||||
#define CPU_OR       45
 | 
			
		||||
#define CPU_ORI      46
 | 
			
		||||
#define CPU_OUT_B    47
 | 
			
		||||
#define CPU_OUT_H    48
 | 
			
		||||
#define CPU_OUT_W    49
 | 
			
		||||
#define CPU_RETI     50
 | 
			
		||||
#define CPU_REV      51
 | 
			
		||||
#define CPU_SAR_IMM  52
 | 
			
		||||
#define CPU_SAR_REG  53
 | 
			
		||||
#define CPU_SCH0BSD  54
 | 
			
		||||
#define CPU_SCH0BSU  55
 | 
			
		||||
#define CPU_SCH1BSD  56
 | 
			
		||||
#define CPU_SCH1BSU  57
 | 
			
		||||
#define CPU_SEI      58
 | 
			
		||||
#define CPU_SETF     59
 | 
			
		||||
#define CPU_SHL_IMM  60
 | 
			
		||||
#define CPU_SHL_REG  61
 | 
			
		||||
#define CPU_SHR_IMM  62
 | 
			
		||||
#define CPU_SHR_REG  63
 | 
			
		||||
#define CPU_ST_B     64
 | 
			
		||||
#define CPU_ST_H     65
 | 
			
		||||
#define CPU_ST_W     66
 | 
			
		||||
#define CPU_STSR     67
 | 
			
		||||
#define CPU_SUB      68
 | 
			
		||||
#define CPU_SUBF_S   69
 | 
			
		||||
#define CPU_TRAP     70
 | 
			
		||||
#define CPU_TRNC_SW  71
 | 
			
		||||
#define CPU_XB       72
 | 
			
		||||
#define CPU_XH       73
 | 
			
		||||
#define CPU_XOR      74
 | 
			
		||||
#define CPU_XORI     75
 | 
			
		||||
#define CPU_ANDBSU   76 /* Keep bit string ALU IDs consecutive */
 | 
			
		||||
#define CPU_ANDNBSU  77
 | 
			
		||||
#define CPU_MOVBSU   78
 | 
			
		||||
#define CPU_NOTBSU   79
 | 
			
		||||
#define CPU_ORBSU    80
 | 
			
		||||
#define CPU_ORNBSU   81
 | 
			
		||||
#define CPU_XORBSU   82
 | 
			
		||||
#define CPU_XORNBSU  83
 | 
			
		||||
 | 
			
		||||
/* Functional operand types */
 | 
			
		||||
#define CPU_LITERAL  0
 | 
			
		||||
| 
						 | 
				
			
			@ -206,6 +195,13 @@ static const uint8_t OPDEFS_FLOATENDO[] = {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**************************** Forward references *****************************/
 | 
			
		||||
 | 
			
		||||
static int      phAssess (VB *, uint32_t, int, int32_t);
 | 
			
		||||
static uint32_t phUntil  (VB *);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***************************** Callback Handlers *****************************/
 | 
			
		||||
 | 
			
		||||
/* Prepare to handle an exception */
 | 
			
		||||
| 
						 | 
				
			
			@ -248,6 +244,10 @@ static int cpuRead(VB *sim, uint32_t address, int type, int32_t *value) {
 | 
			
		|||
    /* Retrieve the value from the simulation state directly */
 | 
			
		||||
    busRead(sim, address, type, value);
 | 
			
		||||
 | 
			
		||||
    /* Check for pseudo-halt */
 | 
			
		||||
    if (sim->ph.enabled && phAssess(sim, address, type, *value))
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    /* Invoke the callback if available */
 | 
			
		||||
    if (
 | 
			
		||||
        sim->onRead != NULL &&
 | 
			
		||||
| 
						 | 
				
			
			@ -296,6 +296,10 @@ static int cpuWrite(VB *sim, uint32_t address, int type, int32_t value) {
 | 
			
		|||
    int      cancel = 0;
 | 
			
		||||
    uint32_t cycles = 3; /* TODO: Research this */
 | 
			
		||||
 | 
			
		||||
    /* Reset pseudo-halt */
 | 
			
		||||
    if (sim->ph.enabled)
 | 
			
		||||
        sim->ph.step = 0;
 | 
			
		||||
 | 
			
		||||
    /* Invoke the callback if available */
 | 
			
		||||
    if (
 | 
			
		||||
        sim->onWrite != NULL &&
 | 
			
		||||
| 
						 | 
				
			
			@ -482,10 +486,13 @@ static int cpuException(VB *sim) {
 | 
			
		|||
        /* Interrupts only */
 | 
			
		||||
        if ((cause & 0xFF00) == 0xFE00) {
 | 
			
		||||
            sim->cpu.psw.i = (cause >> 4 & 7) + 1;
 | 
			
		||||
 | 
			
		||||
            /* HALT instruction */
 | 
			
		||||
            if (sim->cpu.halt) {
 | 
			
		||||
                sim->cpu.halt = 0;
 | 
			
		||||
                sim->cpu.pc  += 2;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* All exceptions */
 | 
			
		||||
| 
						 | 
				
			
			@ -583,6 +590,30 @@ static int cpuHalt(VB *sim) {
 | 
			
		|||
    return !cpuIRQ(sim);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Pseudo-halt is pending */
 | 
			
		||||
static int cpuPHalt(VB *sim) {
 | 
			
		||||
    int32_t value; /* Value read from memory */
 | 
			
		||||
 | 
			
		||||
    /* An interrupt will be accepted */
 | 
			
		||||
    if (cpuIRQ(sim)) {
 | 
			
		||||
        sim->ph.step = 0;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Monitor value has not changed */
 | 
			
		||||
    busRead(sim, sim->ph.address, sim->ph.type, &value);
 | 
			
		||||
    if (value == sim->ph.value) {
 | 
			
		||||
        sim->cpu.clocks = phUntil(sim);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Release pseudo-halt */
 | 
			
		||||
    sim->cpu.operation = CPU_FETCH;
 | 
			
		||||
    sim->cpu.step      = 0;
 | 
			
		||||
    sim->ph.step       = 0;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**************************** Instruction Helpers ****************************/
 | 
			
		||||
| 
						 | 
				
			
			@ -1699,10 +1730,11 @@ static int cpuEmulate(VB *sim, uint32_t clocks) {
 | 
			
		|||
 | 
			
		||||
        /* Processing by operation ID */
 | 
			
		||||
        switch (sim->cpu.operation) {
 | 
			
		||||
            case CPU_EXCEPTION: brk = cpuException(sim);    break;
 | 
			
		||||
            case CPU_EXCEPTION: brk = cpuException(sim);     break;
 | 
			
		||||
            case CPU_FATAL    : return 0;
 | 
			
		||||
            case CPU_FETCH    : brk = cpuFetch    (sim);    break;
 | 
			
		||||
            case CPU_HALTING  : if (cpuHalt(sim)) return 0; break;
 | 
			
		||||
            case CPU_FETCH    : brk = cpuFetch    (sim);     break;
 | 
			
		||||
            case CPU_HALTING  : if (cpuHalt (sim)) return 0; break;
 | 
			
		||||
            case CPU_PHALT    : if (cpuPHalt(sim)) return 0; break;
 | 
			
		||||
 | 
			
		||||
            case CPU_ADD_IMM:       cpuADDImm (sim); break;
 | 
			
		||||
            case CPU_ADD_REG:       cpuADDReg (sim); break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1826,8 +1858,14 @@ static void cpuReset(VB *sim) {
 | 
			
		|||
/* Determine how many clocks are guaranteed to process */
 | 
			
		||||
static uint32_t cpuUntil(VB *sim, uint32_t clocks) {
 | 
			
		||||
 | 
			
		||||
    /* Pseudo-halting */
 | 
			
		||||
    if (sim->cpu.operation == CPU_PHALT) {
 | 
			
		||||
        if (!sim->ph.operation)
 | 
			
		||||
            return clocks;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Halting */
 | 
			
		||||
    if (sim->cpu.halt) {
 | 
			
		||||
    else if (sim->cpu.halt) {
 | 
			
		||||
        return
 | 
			
		||||
            sim->cpu.operation == CPU_HALTING                      &&
 | 
			
		||||
            !(sim->cpu.psw.id | sim->cpu.psw.ep | sim->cpu.psw.np) &&
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,177 @@
 | 
			
		|||
/* This file is included into vb.c and cannot be compiled on its own. */
 | 
			
		||||
#ifdef VBAPI
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/********************************* Constants *********************************/
 | 
			
		||||
 | 
			
		||||
/* Pseudo-halt operations */
 | 
			
		||||
#define PH_NEVER  0 /* Must be zero */
 | 
			
		||||
#define PH_XPSTTS 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***************************** Module Functions ******************************/
 | 
			
		||||
 | 
			
		||||
/* Activate pseudo-halt */
 | 
			
		||||
static void phActivate(VB *sim, uint32_t address, int type) {
 | 
			
		||||
    int range; /* Memory address range by component */
 | 
			
		||||
 | 
			
		||||
    (void) type;
 | 
			
		||||
 | 
			
		||||
    /* Working variables */
 | 
			
		||||
    address = 0x07FFFFFF;
 | 
			
		||||
    range   = address >> 24;
 | 
			
		||||
 | 
			
		||||
    /* Configure CPU */
 | 
			
		||||
    sim->cpu.operation = CPU_PHALT;
 | 
			
		||||
    sim->ph.operation  = PH_NEVER;
 | 
			
		||||
 | 
			
		||||
    /* VIP */
 | 
			
		||||
    if (range == 0) {
 | 
			
		||||
        address &= 0x0007FFFF;
 | 
			
		||||
 | 
			
		||||
        /* I/O register */
 | 
			
		||||
        switch (address) {
 | 
			
		||||
            case 0x5F840: /* XPSTTS */
 | 
			
		||||
                if (sim->vip.dp.disp && sim->vip.xp.xpen)
 | 
			
		||||
                    sim->ph.operation = PH_XPSTTS;
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Configure CPU */
 | 
			
		||||
    sim->cpu.clocks = phUntil(sim);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Test whether the current memory access matches the monitored access */
 | 
			
		||||
static int phMatches(VB *sim, uint32_t address, int type, int32_t value) {
 | 
			
		||||
    int match; /* Parameter match */
 | 
			
		||||
    int x;     /* Iterator */
 | 
			
		||||
 | 
			
		||||
    /* New memory access */
 | 
			
		||||
    if (sim->ph.step == 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    /* Check memory access parameters */
 | 
			
		||||
    match =
 | 
			
		||||
        address     == sim->ph.address &&
 | 
			
		||||
        sim->cpu.pc == sim->ph.pc      &&
 | 
			
		||||
        type        == sim->ph.type    &&
 | 
			
		||||
        value       == sim->ph.value
 | 
			
		||||
    ;
 | 
			
		||||
    if (!match || sim->ph.step != 3)
 | 
			
		||||
        return match;
 | 
			
		||||
 | 
			
		||||
    /* Check full CPU state */
 | 
			
		||||
    for (x = 1; x < 32; x++) {
 | 
			
		||||
        if (sim->ph.program[x - 1] != sim->cpu.program[x])
 | 
			
		||||
            return 0;
 | 
			
		||||
    }
 | 
			
		||||
    return
 | 
			
		||||
        sim->ph.adtre == sim->cpu.adtre                     &&
 | 
			
		||||
        sim->ph.chcw  == cpuGetSystemRegister(sim, VB_CHCW) &&
 | 
			
		||||
        sim->ph.eipc  == sim->cpu.eipc                      &&
 | 
			
		||||
        sim->ph.eipsw == sim->cpu.eipsw                     &&
 | 
			
		||||
        sim->ph.fepc  == sim->cpu.fepc                      &&
 | 
			
		||||
        sim->ph.fepsw == sim->cpu.fepsw                     &&
 | 
			
		||||
        sim->ph.psw   == cpuGetSystemRegister(sim, VB_PSW)
 | 
			
		||||
    ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/****************************** Clock Measurers ******************************/
 | 
			
		||||
 | 
			
		||||
/* XPSTTS */
 | 
			
		||||
static uint32_t phXPSTTS(VB *sim) {
 | 
			
		||||
    uint32_t  clocks;    /* Return value */
 | 
			
		||||
    uint16_t *halfwords; /* Drawing clocks this SBCOUNT */
 | 
			
		||||
    uint32_t  x;         /* Iterator */
 | 
			
		||||
 | 
			
		||||
    /* Drawing is underway */
 | 
			
		||||
    if (sim->vip.xp.f0bsy || sim->vip.xp.f1bsy) {
 | 
			
		||||
        clocks    = 0;
 | 
			
		||||
        halfwords = &sim->vip.halfwords[
 | 
			
		||||
            (uint32_t) sim->vip.xp.sbcount * 384 + sim->vip.xp.column];
 | 
			
		||||
        for (x = sim->vip.xp.column; x < 384; x++, halfwords++)
 | 
			
		||||
            clocks += *halfwords;
 | 
			
		||||
        return clocks;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Drawing is idle */
 | 
			
		||||
    switch (sim->vip.dp.step) {
 | 
			
		||||
        case 0: /* 0ms - FCLK rising edge */
 | 
			
		||||
            return sim->vip.dp.until;
 | 
			
		||||
        case 1: /* 3ms - L*BSY rising edge */
 | 
			
		||||
        case 2: /* 3ms-8ms - Display left frame buffer */
 | 
			
		||||
        case 3: /* 8ms - L*BSY falling edge */
 | 
			
		||||
            return sim->vip.dp.until + vipClocksMs(12);
 | 
			
		||||
    }
 | 
			
		||||
    /* case 4: 10ms - FCLK falling edge */
 | 
			
		||||
    /* case 5: 13ms - R*BSY rising edge */
 | 
			
		||||
    /* case 6: 13ms-18ms - Display right frame buffer */
 | 
			
		||||
    /* case 7: 18ms - R*BSY falling edge */
 | 
			
		||||
    return sim->vip.dp.until + vipClocksMs(2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/***************************** Library Functions *****************************/
 | 
			
		||||
 | 
			
		||||
/* Test whether to activate pseudo-halt */
 | 
			
		||||
static int phAssess(VB *sim, uint32_t address, int type, int32_t value) {
 | 
			
		||||
    int x; /* Iterator */
 | 
			
		||||
 | 
			
		||||
    /* Memory access does not match last time */
 | 
			
		||||
    if (!phMatches(sim, address, type, value))
 | 
			
		||||
        sim->ph.step = 0;
 | 
			
		||||
 | 
			
		||||
    /* New memory access */
 | 
			
		||||
    if (sim->ph.step == 0) {
 | 
			
		||||
        sim->ph.address = address;
 | 
			
		||||
        sim->ph.pc      = sim->cpu.pc;
 | 
			
		||||
        sim->ph.step    = 1;
 | 
			
		||||
        sim->ph.type    = type;
 | 
			
		||||
        sim->ph.value   = value;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Repeated memory access, not checking full CPU state */
 | 
			
		||||
    if (sim->ph.step < 2) {
 | 
			
		||||
        sim->ph.step++;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Take a snapshot of the full CPU state */
 | 
			
		||||
    if (sim->ph.step == 2) {
 | 
			
		||||
        for (x = 1; x < 32; x++)
 | 
			
		||||
            sim->ph.program[x - 1] = sim->cpu.program[x];
 | 
			
		||||
        sim->ph.adtre = sim->cpu.adtre;
 | 
			
		||||
        sim->ph.chcw  = cpuGetSystemRegister(sim, VB_CHCW);
 | 
			
		||||
        sim->ph.eipc  = sim->cpu.eipc;
 | 
			
		||||
        sim->ph.eipsw = sim->cpu.eipsw;
 | 
			
		||||
        sim->ph.fepc  = sim->cpu.fepc;
 | 
			
		||||
        sim->ph.fepsw = sim->cpu.fepsw;
 | 
			
		||||
        sim->ph.psw   = cpuGetSystemRegister(sim, VB_PSW);
 | 
			
		||||
        sim->ph.step  = 3;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Activate pseudo-halt */
 | 
			
		||||
    phActivate(sim, address, type);
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Determine how long the CPU should wait before checking the monitor value */
 | 
			
		||||
static uint32_t phUntil(VB *sim) {
 | 
			
		||||
    switch (sim->ph.operation) {
 | 
			
		||||
        case PH_XPSTTS: return phXPSTTS(sim);
 | 
			
		||||
    }
 | 
			
		||||
    return 0; /* PH_NEVER */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* VBAPI */
 | 
			
		||||
							
								
								
									
										53
									
								
								core/vb.c
								
								
								
								
							
							
						
						
									
										53
									
								
								core/vb.c
								
								
								
								
							| 
						 | 
				
			
			@ -308,6 +308,29 @@ struct VB {
 | 
			
		|||
        int      sample; /* Output sample index, period 417 */
 | 
			
		||||
    } vsu;
 | 
			
		||||
 | 
			
		||||
    /* Pseudo-halt */
 | 
			
		||||
    struct {
 | 
			
		||||
        uint32_t address;   /* Monitor address */
 | 
			
		||||
        uint8_t  enabled;   /* Pseudo-halt function is enabled */
 | 
			
		||||
        uint8_t  operation; /* Monitoring operation */
 | 
			
		||||
        uint8_t  step;      /* Number of consecutive matching reads */
 | 
			
		||||
        int      type;      /* Memory access type */
 | 
			
		||||
        int32_t  value;     /* Value read from monitor address */
 | 
			
		||||
 | 
			
		||||
        /* CPU snapshot */
 | 
			
		||||
        uint32_t adtre;
 | 
			
		||||
        uint32_t chcw;
 | 
			
		||||
        uint32_t eipc;
 | 
			
		||||
        uint32_t eipsw;
 | 
			
		||||
        uint32_t fepc;
 | 
			
		||||
        uint32_t fepsw;
 | 
			
		||||
        uint32_t pc;
 | 
			
		||||
        int32_t  program[31];
 | 
			
		||||
        uint32_t psw;
 | 
			
		||||
        uint32_t sr29;
 | 
			
		||||
        uint32_t sr31;
 | 
			
		||||
    } ph;
 | 
			
		||||
 | 
			
		||||
    /* Other state */
 | 
			
		||||
    uint8_t wcr;           /* Wait controller state */
 | 
			
		||||
    uint8_t wram[0x10000]; /* System RAM */
 | 
			
		||||
| 
						 | 
				
			
			@ -348,6 +371,7 @@ static int32_t SignExtend(int32_t value, int32_t bits) {
 | 
			
		|||
#include "cpu.c"
 | 
			
		||||
#include "vip.c"
 | 
			
		||||
#include "vsu.c"
 | 
			
		||||
#include "pseudo-halt.c"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -451,6 +475,14 @@ VBAPI uint16_t vbGetKeys(VB *sim) {
 | 
			
		|||
    return sim->pad.keys;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Retrieve a core option value */
 | 
			
		||||
VBAPI int vbGetOption(VB *sim, int key) {
 | 
			
		||||
    switch (key) {
 | 
			
		||||
        case VB_PSEUDO_HALT: return sim->ph.enabled;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Retrieve the most recent frame image pixels */
 | 
			
		||||
VBAPI void vbGetPixels(VB *sim, void *left, int leftStrideX, int leftStrideY,
 | 
			
		||||
    void *right, int rightStrideX, int rightStrideY) {
 | 
			
		||||
| 
						 | 
				
			
			@ -553,6 +585,7 @@ VBAPI VB* vbInit(VB *sim) {
 | 
			
		|||
    sim->onRead          = NULL;
 | 
			
		||||
    sim->onSamples       = NULL;
 | 
			
		||||
    sim->onWrite         = NULL;
 | 
			
		||||
    sim->ph.enabled      = 0;
 | 
			
		||||
    vbReset(sim);
 | 
			
		||||
    return sim;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -583,6 +616,9 @@ VBAPI VB* vbReset(VB *sim) {
 | 
			
		|||
    tmrReset(sim);
 | 
			
		||||
    vipReset(sim);
 | 
			
		||||
    vsuReset(sim);
 | 
			
		||||
 | 
			
		||||
    /* Pseudo-halt */
 | 
			
		||||
    sim->ph.step = 0;
 | 
			
		||||
    return sim;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -641,6 +677,23 @@ VBAPI uint16_t vbSetKeys(VB *sim, uint16_t keys) {
 | 
			
		|||
    return sim->pad.keys = keys;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Specify a new core option value */
 | 
			
		||||
VBAPI int vbSetOption(VB *sim, int key, int value) {
 | 
			
		||||
    switch (key) {
 | 
			
		||||
        case VB_PSEUDO_HALT:
 | 
			
		||||
            sim->ph.enabled = value = !!value;
 | 
			
		||||
            if (!value) {
 | 
			
		||||
                sim->ph.step = 0;
 | 
			
		||||
                if (sim->cpu.operation == CPU_PHALT) {
 | 
			
		||||
                    sim->cpu.operation = CPU_FETCH;
 | 
			
		||||
                    sim->cpu.step      = 0;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Specify a new value for the program counter */
 | 
			
		||||
VBAPI uint32_t vbSetProgramCounter(VB *sim, uint32_t value) {
 | 
			
		||||
    sim->cpu.operation = CPU_FETCH;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,6 +79,9 @@ extern "C" {
 | 
			
		|||
#define VB_U16 3
 | 
			
		||||
#define VB_S32 4
 | 
			
		||||
 | 
			
		||||
/* Option keys */
 | 
			
		||||
#define VB_PSEUDO_HALT 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*********************************** Types ***********************************/
 | 
			
		||||
| 
						 | 
				
			
			@ -110,6 +113,7 @@ VBAPI vbOnExecute   vbGetExecuteCallback  (VB *sim);
 | 
			
		|||
VBAPI vbOnFetch     vbGetFetchCallback    (VB *sim);
 | 
			
		||||
VBAPI vbOnFrame     vbGetFrameCallback    (VB *sim);
 | 
			
		||||
VBAPI uint16_t      vbGetKeys             (VB *sim);
 | 
			
		||||
VBAPI int           vbGetOption           (VB *sim, int key);
 | 
			
		||||
VBAPI void          vbGetPixels           (VB *sim, void *left, int leftStrideX, int leftStrideY, void *right, int rightStrideX, int rightStrideY);
 | 
			
		||||
VBAPI uint32_t      vbGetProgramCounter   (VB *sim);
 | 
			
		||||
VBAPI int32_t       vbGetProgramRegister  (VB *sim, int index);
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +133,7 @@ VBAPI vbOnExecute   vbSetExecuteCallback  (VB *sim, vbOnExecute callback);
 | 
			
		|||
VBAPI vbOnFetch     vbSetFetchCallback    (VB *sim, vbOnFetch callback);
 | 
			
		||||
VBAPI vbOnFrame     vbSetFrameCallback    (VB *sim, vbOnFrame callback);
 | 
			
		||||
VBAPI uint16_t      vbSetKeys             (VB *sim, uint16_t keys);
 | 
			
		||||
VBAPI int           vbSetOption           (VB *sim, int key, int value);
 | 
			
		||||
VBAPI uint32_t      vbSetProgramCounter   (VB *sim, uint32_t value);
 | 
			
		||||
VBAPI int32_t       vbSetProgramRegister  (VB *sim, int index, int32_t value);
 | 
			
		||||
VBAPI vbOnRead      vbSetReadCallback     (VB *sim, vbOnRead callback);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue