Implement floating-point instructions
This commit is contained in:
		
							parent
							
								
									2e0af6b109
								
							
						
					
					
						commit
						5f563e6cac
					
				
							
								
								
									
										471
									
								
								core/cpu.c
								
								
								
								
							
							
						
						
									
										471
									
								
								core/cpu.c
								
								
								
								
							| 
						 | 
					@ -426,6 +426,23 @@ static void cpuAdvance(VB *sim, uint32_t clocks) {
 | 
				
			||||||
    sim->cpu.step      = 0;
 | 
					    sim->cpu.step      = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Interpret floating short bits as word integer bits */
 | 
				
			||||||
 | 
					static int32_t cpuFloatToWord(float x) {
 | 
				
			||||||
 | 
					    return *(int32_t *) &x;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Raise an exception */
 | 
				
			||||||
 | 
					static int cpuThrow(VB *sim, uint16_t cause) {
 | 
				
			||||||
 | 
					    sim->cpu.exception = cause;
 | 
				
			||||||
 | 
					    sim->cpu.operation = CPU_EXCEPTION;
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Interpret word integer bits as floating short bits */
 | 
				
			||||||
 | 
					static float cpuWordToFloat(int32_t x) {
 | 
				
			||||||
 | 
					    return *(float *) &x;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Retrieve the value of a system register */
 | 
					/* Retrieve the value of a system register */
 | 
				
			||||||
static uint32_t cpuGetSystemRegister(VB *sim, int index) {
 | 
					static uint32_t cpuGetSystemRegister(VB *sim, int index) {
 | 
				
			||||||
    switch (index) {
 | 
					    switch (index) {
 | 
				
			||||||
| 
						 | 
					@ -545,6 +562,56 @@ static int cpuCondition(VB *sim, int id) {
 | 
				
			||||||
    return !cpuCondition(sim, id & 7);
 | 
					    return !cpuCondition(sim, id & 7);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Floating-point common processing */
 | 
				
			||||||
 | 
					static int cpuFloatCommon(VB *sim, double value, int32_t *bits) {
 | 
				
			||||||
 | 
					    float floatVal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Overflow */
 | 
				
			||||||
 | 
					    if (value < -FLT_MAX || value > FLT_MAX) {
 | 
				
			||||||
 | 
					        /* TODO: CPU does give reg2 some value */
 | 
				
			||||||
 | 
					        sim->cpu.psw.fov = 1;
 | 
				
			||||||
 | 
					        cpuThrow(sim, 0xFF64);
 | 
				
			||||||
 | 
					        return 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Underflow */
 | 
				
			||||||
 | 
					    if (value < 0 ? value > -FLT_MIN : value < FLT_MIN) {
 | 
				
			||||||
 | 
					        sim->cpu.psw.fud = 1;
 | 
				
			||||||
 | 
					        floatVal         = 0;
 | 
				
			||||||
 | 
					        /* TODO: Can this produce negative zero? */
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Regular conversion */
 | 
				
			||||||
 | 
					    else floatVal = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Precision degradation */
 | 
				
			||||||
 | 
					    if (floatVal != value)
 | 
				
			||||||
 | 
					        sim->cpu.psw.fpr = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Update state */
 | 
				
			||||||
 | 
					    *bits = cpuFloatToWord(floatVal);
 | 
				
			||||||
 | 
					    sim->cpu.psw.cy  = floatVal <  0;
 | 
				
			||||||
 | 
					    sim->cpu.psw.ov  = 0;
 | 
				
			||||||
 | 
					    sim->cpu.psw.s   = floatVal <  0;
 | 
				
			||||||
 | 
					    sim->cpu.psw.z   = floatVal == 0;
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Test whether a floating-point register value is a reserved operand */
 | 
				
			||||||
 | 
					static int cpuFloatReservedOne(int32_t bits) {
 | 
				
			||||||
 | 
					    int32_t e = bits >> 23 & 0xFF;
 | 
				
			||||||
 | 
					    return e ? (bits & 0x7FFFFFFF) != 0 : e == 0xFF;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Test whether floating-point register values are reserved operands */
 | 
				
			||||||
 | 
					static int cpuFloatReserved(VB *sim, int32_t a, int32_t b) {
 | 
				
			||||||
 | 
					    if (!(cpuFloatReservedOne(a) || cpuFloatReservedOne(b)))
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    sim->cpu.psw.fro = 1;
 | 
				
			||||||
 | 
					    cpuThrow(sim, 0xFF60);
 | 
				
			||||||
 | 
					    return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Jump and branch common processing */
 | 
					/* Jump and branch common processing */
 | 
				
			||||||
static void cpuJump(VB *sim, uint32_t address) {
 | 
					static void cpuJump(VB *sim, uint32_t address) {
 | 
				
			||||||
    sim->cpu.clocks   += cpuClocks(3);
 | 
					    sim->cpu.clocks   += cpuClocks(3);
 | 
				
			||||||
| 
						 | 
					@ -667,46 +734,55 @@ static int cpuST_OUT(VB *sim, int type) {
 | 
				
			||||||
/************************** Instruction Operations ***************************/
 | 
					/************************** Instruction Operations ***************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ADD immediate */
 | 
					/* ADD immediate */
 | 
				
			||||||
static int cpuADDImm(VB *sim) {
 | 
					static void cpuADDImm(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuAdd(sim, cpuGetImm5S(sim)));
 | 
					    cpuSetReg2(sim, cpuAdd(sim, cpuGetImm5S(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ADD register */
 | 
					/* ADD register */
 | 
				
			||||||
static int cpuADDReg(VB *sim) {
 | 
					static void cpuADDReg(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuAdd(sim, cpuGetReg1(sim)));
 | 
					    cpuSetReg2(sim, cpuAdd(sim, cpuGetReg1(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ADDF.S */
 | 
				
			||||||
 | 
					static void cpuADDF_S(VB *sim) {
 | 
				
			||||||
 | 
					    int32_t a = cpuGetReg2(sim);
 | 
				
			||||||
 | 
					    int32_t b = cpuGetReg1(sim);
 | 
				
			||||||
 | 
					    double  c; /* Result */
 | 
				
			||||||
 | 
					    int32_t d; /* Float bits for result */
 | 
				
			||||||
 | 
					    if (cpuFloatReserved(sim, a, b))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    c = (double) cpuWordToFloat(a) + cpuWordToFloat(b);
 | 
				
			||||||
 | 
					    if (cpuFloatCommon(sim, c, &d))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    cpuSetReg2(sim, d);
 | 
				
			||||||
 | 
					    cpuAdvance(sim, cpuClocks(28)); /* TODO: Research */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ADDI */
 | 
					/* ADDI */
 | 
				
			||||||
static int cpuADDI(VB *sim) {
 | 
					static void cpuADDI(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuAdd(sim, cpuGetImm16S(sim)));
 | 
					    cpuSetReg2(sim, cpuAdd(sim, cpuGetImm16S(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* AND */
 | 
					/* AND */
 | 
				
			||||||
static int cpuAND(VB *sim) {
 | 
					static void cpuAND(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) & cpuGetReg1(sim)));
 | 
					    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) & cpuGetReg1(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ANDI */
 | 
					/* ANDI */
 | 
				
			||||||
static int cpuANDI(VB *sim) {
 | 
					static void cpuANDI(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) & cpuGetImm16U(sim)));
 | 
					    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) & cpuGetImm16U(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* BCOND */
 | 
					/* BCOND */
 | 
				
			||||||
static int cpuBCOND(VB *sim) {
 | 
					static void cpuBCOND(VB *sim) {
 | 
				
			||||||
    if (cpuCondition(sim, cpuGetCond(sim)))
 | 
					    if (cpuCondition(sim, cpuGetCond(sim)))
 | 
				
			||||||
        cpuJump(sim, sim->cpu.pc + cpuGetDisp9(sim));
 | 
					        cpuJump(sim, sim->cpu.pc + cpuGetDisp9(sim));
 | 
				
			||||||
    else cpuAdvance(sim, cpuClocks(1));
 | 
					    else cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* CAXI */
 | 
					/* CAXI */
 | 
				
			||||||
| 
						 | 
					@ -749,28 +825,78 @@ static int cpuCAXI(VB *sim) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* CLI */
 | 
					/* CLI */
 | 
				
			||||||
static int cpuCLI(VB *sim) {
 | 
					static void cpuCLI(VB *sim) {
 | 
				
			||||||
    sim->cpu.psw.id = 0;
 | 
					    sim->cpu.psw.id = 0;
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(12));
 | 
					    cpuAdvance(sim, cpuClocks(12));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* CMP immediate */
 | 
					/* CMP immediate */
 | 
				
			||||||
static int cpuCMPImm(VB *sim) {
 | 
					static void cpuCMPImm(VB *sim) {
 | 
				
			||||||
    cpuSubtract(sim, cpuGetImm5S(sim));
 | 
					    cpuSubtract(sim, cpuGetImm5S(sim));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* CMP register */
 | 
					/* CMP register */
 | 
				
			||||||
static int cpuCMPReg(VB *sim) {
 | 
					static void cpuCMPReg(VB *sim) {
 | 
				
			||||||
    cpuSubtract(sim, cpuGetReg1(sim));
 | 
					    cpuSubtract(sim, cpuGetReg1(sim));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* CMPF.S */
 | 
				
			||||||
 | 
					static void cpuCMPF_S(VB *sim) {
 | 
				
			||||||
 | 
					    int32_t a = cpuGetReg2(sim);
 | 
				
			||||||
 | 
					    int32_t b = cpuGetReg1(sim);
 | 
				
			||||||
 | 
					    double  c; /* Result */
 | 
				
			||||||
 | 
					    int32_t d; /* Float bits for result */
 | 
				
			||||||
 | 
					    if (cpuFloatReserved(sim, a, b))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    c = (double) cpuWordToFloat(a) - cpuWordToFloat(b);
 | 
				
			||||||
 | 
					    if (cpuFloatCommon(sim, c, &d))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    cpuAdvance(sim, cpuClocks(10)); /* TODO: Research */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* CVT.SW */
 | 
				
			||||||
 | 
					static void cpuCVT_SW(VB *sim) {
 | 
				
			||||||
 | 
					    double  f;
 | 
				
			||||||
 | 
					    int32_t w = cpuGetReg1(sim);
 | 
				
			||||||
 | 
					    if (cpuFloatReservedOne(w)) {
 | 
				
			||||||
 | 
					        cpuThrow(sim, 0xFF60);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    f = cpuWordToFloat(w);
 | 
				
			||||||
 | 
					    if (f <= -2147483648.5 || f >= 2147483647.5) {
 | 
				
			||||||
 | 
					        sim->cpu.psw.fiv = 1;
 | 
				
			||||||
 | 
					        cpuThrow(sim, 0xFF70);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    w = f < 0 ? f - 0.5 : f + 0.5;
 | 
				
			||||||
 | 
					    cpuSetReg2(sim, w);
 | 
				
			||||||
 | 
					    if (w != f)
 | 
				
			||||||
 | 
					        sim->cpu.psw.fpr = 1;
 | 
				
			||||||
 | 
					    sim->cpu.psw.ov = 0;
 | 
				
			||||||
 | 
					    sim->cpu.psw.s  = w <  0;
 | 
				
			||||||
 | 
					    sim->cpu.psw.z  = w == 0;
 | 
				
			||||||
 | 
					    cpuAdvance(sim, cpuClocks(14)); /* TODO: Research */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* CVT.WS */
 | 
				
			||||||
 | 
					static void cpuCVT_WS(VB *sim) {
 | 
				
			||||||
 | 
					    int32_t w = cpuGetReg1(sim);
 | 
				
			||||||
 | 
					    float   f = w;
 | 
				
			||||||
 | 
					    if (f != w)
 | 
				
			||||||
 | 
					        sim->cpu.psw.fpr = 1;
 | 
				
			||||||
 | 
					    w = cpuFloatToWord(f);
 | 
				
			||||||
 | 
					    cpuSetReg2(sim, w);
 | 
				
			||||||
 | 
					    sim->cpu.psw.cy = w <  0;
 | 
				
			||||||
 | 
					    sim->cpu.psw.ov = 0;
 | 
				
			||||||
 | 
					    sim->cpu.psw.s  = w <  0;
 | 
				
			||||||
 | 
					    sim->cpu.psw.z  = w == 0;
 | 
				
			||||||
 | 
					    cpuAdvance(sim, cpuClocks(16)); /* TODO: Research */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* DIV */
 | 
					/* DIV */
 | 
				
			||||||
static int cpuDIV(VB *sim) {
 | 
					static void cpuDIV(VB *sim) {
 | 
				
			||||||
    int32_t a;  /* Dividend */
 | 
					    int32_t a;  /* Dividend */
 | 
				
			||||||
    int32_t b;  /* Divisor */
 | 
					    int32_t b;  /* Divisor */
 | 
				
			||||||
    int32_t c;  /* Remainder */
 | 
					    int32_t c;  /* Remainder */
 | 
				
			||||||
| 
						 | 
					@ -783,10 +909,8 @@ static int cpuDIV(VB *sim) {
 | 
				
			||||||
    /* Zero division */
 | 
					    /* Zero division */
 | 
				
			||||||
    b = cpuGetReg1(sim);
 | 
					    b = cpuGetReg1(sim);
 | 
				
			||||||
    if (b == 0) {
 | 
					    if (b == 0) {
 | 
				
			||||||
        sim->cpu.exception = 0xFF80;
 | 
					        cpuThrow(sim, 0xFF80);
 | 
				
			||||||
        sim->cpu.operation = CPU_EXCEPTION;
 | 
					        return;
 | 
				
			||||||
        /* TODO: Research clocks */
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Compute results */
 | 
					    /* Compute results */
 | 
				
			||||||
| 
						 | 
					@ -831,11 +955,29 @@ static int cpuDIV(VB *sim) {
 | 
				
			||||||
    sim->cpu.psw.s  = d <  0;
 | 
					    sim->cpu.psw.s  = d <  0;
 | 
				
			||||||
    sim->cpu.psw.z  = d == 0;
 | 
					    sim->cpu.psw.z  = d == 0;
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(38));
 | 
					    cpuAdvance(sim, cpuClocks(38));
 | 
				
			||||||
    return 0;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* DIVF.S */
 | 
				
			||||||
 | 
					static void cpuDIVF_S(VB *sim) {
 | 
				
			||||||
 | 
					    int32_t a = cpuGetReg2(sim);
 | 
				
			||||||
 | 
					    int32_t b = cpuGetReg1(sim);
 | 
				
			||||||
 | 
					    double  c; /* Result */
 | 
				
			||||||
 | 
					    int32_t d; /* Float bits for result */
 | 
				
			||||||
 | 
					    if (cpuFloatReserved(sim, a, b))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    if ((b & 0x7FFFFFFF) == 0) {
 | 
				
			||||||
 | 
					        cpuThrow(sim, (a & 0x7FFFFFFF) == 0 ? 0xFF70 : 0xFF68);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    c = (double) cpuWordToFloat(a) / cpuWordToFloat(b);
 | 
				
			||||||
 | 
					    if (cpuFloatCommon(sim, c, &d))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    cpuSetReg2(sim, d);
 | 
				
			||||||
 | 
					    cpuAdvance(sim, cpuClocks(44));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* DIVU */
 | 
					/* DIVU */
 | 
				
			||||||
static int cpuDIVU(VB *sim) {
 | 
					static void cpuDIVU(VB *sim) {
 | 
				
			||||||
    uint32_t a;  /* Dividend */
 | 
					    uint32_t a;  /* Dividend */
 | 
				
			||||||
    uint32_t b;  /* Divisor */
 | 
					    uint32_t b;  /* Divisor */
 | 
				
			||||||
    int32_t  c;  /* Remainder */
 | 
					    int32_t  c;  /* Remainder */
 | 
				
			||||||
| 
						 | 
					@ -844,10 +986,8 @@ static int cpuDIVU(VB *sim) {
 | 
				
			||||||
    /* Zero division */
 | 
					    /* Zero division */
 | 
				
			||||||
    b = cpuGetReg1(sim);
 | 
					    b = cpuGetReg1(sim);
 | 
				
			||||||
    if (b == 0) {
 | 
					    if (b == 0) {
 | 
				
			||||||
        sim->cpu.exception = 0xFF80;
 | 
					        cpuThrow(sim, 0xFF80);
 | 
				
			||||||
        sim->cpu.operation = CPU_EXCEPTION;
 | 
					        return;
 | 
				
			||||||
        /* TODO: Research clocks */
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Compute results */
 | 
					    /* Compute results */
 | 
				
			||||||
| 
						 | 
					@ -862,14 +1002,12 @@ static int cpuDIVU(VB *sim) {
 | 
				
			||||||
    sim->cpu.psw.s  = d <  0;
 | 
					    sim->cpu.psw.s  = d <  0;
 | 
				
			||||||
    sim->cpu.psw.z  = d == 0;
 | 
					    sim->cpu.psw.z  = d == 0;
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(36));
 | 
					    cpuAdvance(sim, cpuClocks(36));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* HALT */
 | 
					/* HALT */
 | 
				
			||||||
static int cpuHALT(VB *sim) {
 | 
					static void cpuHALT(VB *sim) {
 | 
				
			||||||
    sim->cpu.operation = CPU_HALTING;
 | 
					    sim->cpu.operation = CPU_HALTING;
 | 
				
			||||||
    /* TODO: Research clocks */
 | 
					    /* TODO: Research clocks */
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* IN.B */
 | 
					/* IN.B */
 | 
				
			||||||
| 
						 | 
					@ -888,22 +1026,19 @@ static int cpuIN_W(VB *sim) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* JAL */
 | 
					/* JAL */
 | 
				
			||||||
static int cpuJAL(VB *sim) {
 | 
					static void cpuJAL(VB *sim) {
 | 
				
			||||||
    sim->cpu.program[31] = sim->cpu.pc + 4;
 | 
					    sim->cpu.program[31] = sim->cpu.pc + 4;
 | 
				
			||||||
    cpuJump(sim, sim->cpu.pc + cpuGetDisp26(sim));
 | 
					    cpuJump(sim, sim->cpu.pc + cpuGetDisp26(sim));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* JMP */
 | 
					/* JMP */
 | 
				
			||||||
static int cpuJMP(VB *sim) {
 | 
					static void cpuJMP(VB *sim) {
 | 
				
			||||||
    cpuJump(sim, cpuGetReg1(sim));
 | 
					    cpuJump(sim, cpuGetReg1(sim));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* JR */
 | 
					/* JR */
 | 
				
			||||||
static int cpuJR(VB *sim) {
 | 
					static void cpuJR(VB *sim) {
 | 
				
			||||||
    cpuJump(sim, sim->cpu.pc + cpuGetDisp26(sim));
 | 
					    cpuJump(sim, sim->cpu.pc + cpuGetDisp26(sim));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* LD.B */
 | 
					/* LD.B */
 | 
				
			||||||
| 
						 | 
					@ -922,48 +1057,42 @@ static int cpuLD_W(VB *sim) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* LDSR */
 | 
					/* LDSR */
 | 
				
			||||||
static int cpuLDSR(VB *sim) {
 | 
					static void cpuLDSR(VB *sim) {
 | 
				
			||||||
    cpuSetSystemRegister(sim, cpuGetImm5U(sim), cpuGetReg2(sim), 0);
 | 
					    cpuSetSystemRegister(sim, cpuGetImm5U(sim), cpuGetReg2(sim), 0);
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(8));
 | 
					    cpuAdvance(sim, cpuClocks(8));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MOV immediate */
 | 
					/* MOV immediate */
 | 
				
			||||||
static int cpuMOVImm(VB *sim) {
 | 
					static void cpuMOVImm(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuGetImm5S(sim));
 | 
					    cpuSetReg2(sim, cpuGetImm5S(sim));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MOV register */
 | 
					/* MOV register */
 | 
				
			||||||
static int cpuMOVReg(VB *sim) {
 | 
					static void cpuMOVReg(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuGetReg1(sim));
 | 
					    cpuSetReg2(sim, cpuGetReg1(sim));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MOVEA */
 | 
					/* MOVEA */
 | 
				
			||||||
static int cpuMOVEA(VB *sim) {
 | 
					static void cpuMOVEA(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuGetReg1(sim) + cpuGetImm16S(sim));
 | 
					    cpuSetReg2(sim, cpuGetReg1(sim) + cpuGetImm16S(sim));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MOVHI */
 | 
					/* MOVHI */
 | 
				
			||||||
static int cpuMOVHI(VB *sim) {
 | 
					static void cpuMOVHI(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuGetReg1(sim) + (cpuGetImm16U(sim) << 16));
 | 
					    cpuSetReg2(sim, cpuGetReg1(sim) + (cpuGetImm16U(sim) << 16));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MPYHW */
 | 
					/* MPYHW */
 | 
				
			||||||
static int cpuMPYHW(VB *sim) {
 | 
					static void cpuMPYHW(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuGetReg2(sim) * SignExtend(cpuGetReg1(sim), 17));
 | 
					    cpuSetReg2(sim, cpuGetReg2(sim) * SignExtend(cpuGetReg1(sim), 17));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MUL */
 | 
					/* MUL */
 | 
				
			||||||
static int cpuMUL(VB *sim) {
 | 
					static void cpuMUL(VB *sim) {
 | 
				
			||||||
    int64_t a = cpuGetReg2(sim);
 | 
					    int64_t a = cpuGetReg2(sim);
 | 
				
			||||||
    int64_t b = cpuGetReg1(sim);
 | 
					    int64_t b = cpuGetReg1(sim);
 | 
				
			||||||
    int64_t c = a * b;
 | 
					    int64_t c = a * b;
 | 
				
			||||||
| 
						 | 
					@ -974,11 +1103,25 @@ static int cpuMUL(VB *sim) {
 | 
				
			||||||
    sim->cpu.psw.s  = d <  0;
 | 
					    sim->cpu.psw.s  = d <  0;
 | 
				
			||||||
    sim->cpu.psw.z  = d == 0;
 | 
					    sim->cpu.psw.z  = d == 0;
 | 
				
			||||||
    cpuAdvance(sim, 13);
 | 
					    cpuAdvance(sim, 13);
 | 
				
			||||||
    return 0;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* MULF.S */
 | 
				
			||||||
 | 
					static void cpuMULF_S(VB *sim) {
 | 
				
			||||||
 | 
					    int32_t a = cpuGetReg2(sim);
 | 
				
			||||||
 | 
					    int32_t b = cpuGetReg1(sim);
 | 
				
			||||||
 | 
					    double  c; /* Result */
 | 
				
			||||||
 | 
					    int32_t d; /* Float bits for result */
 | 
				
			||||||
 | 
					    if (cpuFloatReserved(sim, a, b))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    c = (double) cpuWordToFloat(a) * cpuWordToFloat(b);
 | 
				
			||||||
 | 
					    if (cpuFloatCommon(sim, c, &d))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    cpuSetReg2(sim, d);
 | 
				
			||||||
 | 
					    cpuAdvance(sim, cpuClocks(30)); /* TODO: Research */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MULU */
 | 
					/* MULU */
 | 
				
			||||||
static int cpuMULU(VB *sim) {
 | 
					static void cpuMULU(VB *sim) {
 | 
				
			||||||
    uint64_t a = cpuGetReg2(sim);
 | 
					    uint64_t a = cpuGetReg2(sim);
 | 
				
			||||||
    uint64_t b = cpuGetReg1(sim);
 | 
					    uint64_t b = cpuGetReg1(sim);
 | 
				
			||||||
    int64_t  c = a * b;
 | 
					    int64_t  c = a * b;
 | 
				
			||||||
| 
						 | 
					@ -989,28 +1132,24 @@ static int cpuMULU(VB *sim) {
 | 
				
			||||||
    sim->cpu.psw.s  = d <  0;
 | 
					    sim->cpu.psw.s  = d <  0;
 | 
				
			||||||
    sim->cpu.psw.z  = d == 0;
 | 
					    sim->cpu.psw.z  = d == 0;
 | 
				
			||||||
    cpuAdvance(sim, 13);
 | 
					    cpuAdvance(sim, 13);
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* NOT */
 | 
					/* NOT */
 | 
				
			||||||
static int cpuNOT(VB *sim) {
 | 
					static void cpuNOT(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuBitwise(sim, ~cpuGetReg1(sim)));
 | 
					    cpuSetReg2(sim, cpuBitwise(sim, ~cpuGetReg1(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* OR */
 | 
					/* OR */
 | 
				
			||||||
static int cpuOR(VB *sim) {
 | 
					static void cpuOR(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) | cpuGetReg1(sim)));
 | 
					    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) | cpuGetReg1(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ORI */
 | 
					/* ORI */
 | 
				
			||||||
static int cpuORI(VB *sim) {
 | 
					static void cpuORI(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) | cpuGetImm16U(sim)));
 | 
					    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) | cpuGetImm16U(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* OUT.B */
 | 
					/* OUT.B */
 | 
				
			||||||
| 
						 | 
					@ -1029,7 +1168,7 @@ static int cpuOUT_W(VB *sim) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* RETI */
 | 
					/* RETI */
 | 
				
			||||||
static int cpuRETI(VB *sim) {
 | 
					static void cpuRETI(VB *sim) {
 | 
				
			||||||
    if (sim->cpu.psw.np) {
 | 
					    if (sim->cpu.psw.np) {
 | 
				
			||||||
        sim->cpu.nextPC = sim->cpu.fepc;
 | 
					        sim->cpu.nextPC = sim->cpu.fepc;
 | 
				
			||||||
        cpuSetSystemRegister(sim, VB_PSW, sim->cpu.fepsw, 0);
 | 
					        cpuSetSystemRegister(sim, VB_PSW, sim->cpu.fepsw, 0);
 | 
				
			||||||
| 
						 | 
					@ -1039,11 +1178,10 @@ static int cpuRETI(VB *sim) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    sim->cpu.clocks   += cpuClocks(10);
 | 
					    sim->cpu.clocks   += cpuClocks(10);
 | 
				
			||||||
    sim->cpu.operation = CPU_FETCH;
 | 
					    sim->cpu.operation = CPU_FETCH;
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* REV */
 | 
					/* REV */
 | 
				
			||||||
static int cpuREV(VB *sim) {
 | 
					static void cpuREV(VB *sim) {
 | 
				
			||||||
    uint32_t x = cpuGetReg1(sim);
 | 
					    uint32_t x = cpuGetReg1(sim);
 | 
				
			||||||
    x = (x << 16 & 0xFFFF0000) | (x >> 16 & 0x0000FFFF);
 | 
					    x = (x << 16 & 0xFFFF0000) | (x >> 16 & 0x0000FFFF);
 | 
				
			||||||
    x = (x <<  8 & 0xFF00FF00) | (x >>  8 & 0x00FF00FF);
 | 
					    x = (x <<  8 & 0xFF00FF00) | (x >>  8 & 0x00FF00FF);
 | 
				
			||||||
| 
						 | 
					@ -1051,63 +1189,54 @@ static int cpuREV(VB *sim) {
 | 
				
			||||||
    x = (x <<  2 & 0xCCCCCCCC) | (x >>  2 & 0x33333333);
 | 
					    x = (x <<  2 & 0xCCCCCCCC) | (x >>  2 & 0x33333333);
 | 
				
			||||||
    x = (x <<  1 & 0xAAAAAAAA) | (x >>  1 & 0x55555555);
 | 
					    x = (x <<  1 & 0xAAAAAAAA) | (x >>  1 & 0x55555555);
 | 
				
			||||||
    cpuSetReg2(sim, x);
 | 
					    cpuSetReg2(sim, x);
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SAR immediate */
 | 
					/* SAR immediate */
 | 
				
			||||||
static int cpuSARImm(VB *sim) {
 | 
					static void cpuSARImm(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuShiftArithmetic(sim, cpuGetImm5U(sim)));
 | 
					    cpuSetReg2(sim, cpuShiftArithmetic(sim, cpuGetImm5U(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SEI */
 | 
					/* SEI */
 | 
				
			||||||
static int cpuSEI(VB *sim) {
 | 
					static void cpuSEI(VB *sim) {
 | 
				
			||||||
    sim->cpu.psw.id = 1;
 | 
					    sim->cpu.psw.id = 1;
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(12));
 | 
					    cpuAdvance(sim, cpuClocks(12));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SETF */
 | 
					/* SETF */
 | 
				
			||||||
static int cpuSETF(VB *sim) {
 | 
					static void cpuSETF(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuCondition(sim, cpuGetImm5U(sim) & 15));
 | 
					    cpuSetReg2(sim, cpuCondition(sim, cpuGetImm5U(sim) & 15));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SHR register */
 | 
					/* SHR register */
 | 
				
			||||||
static int cpuSARReg(VB *sim) {
 | 
					static void cpuSARReg(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuShiftArithmetic(sim, cpuGetReg1(sim) & 31));
 | 
					    cpuSetReg2(sim, cpuShiftArithmetic(sim, cpuGetReg1(sim) & 31));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SHL immediate */
 | 
					/* SHL immediate */
 | 
				
			||||||
static int cpuSHLImm(VB *sim) {
 | 
					static void cpuSHLImm(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuShiftLeft(sim, cpuGetImm5U(sim)));
 | 
					    cpuSetReg2(sim, cpuShiftLeft(sim, cpuGetImm5U(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SHR register */
 | 
					/* SHR register */
 | 
				
			||||||
static int cpuSHLReg(VB *sim) {
 | 
					static void cpuSHLReg(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuShiftLeft(sim, cpuGetReg1(sim) & 31));
 | 
					    cpuSetReg2(sim, cpuShiftLeft(sim, cpuGetReg1(sim) & 31));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SHR immediate */
 | 
					/* SHR immediate */
 | 
				
			||||||
static int cpuSHRImm(VB *sim) {
 | 
					static void cpuSHRImm(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuShiftRight(sim, cpuGetImm5U(sim)));
 | 
					    cpuSetReg2(sim, cpuShiftRight(sim, cpuGetImm5U(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SHR register */
 | 
					/* SHR register */
 | 
				
			||||||
static int cpuSHRReg(VB *sim) {
 | 
					static void cpuSHRReg(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuShiftRight(sim, cpuGetReg1(sim) & 31));
 | 
					    cpuSetReg2(sim, cpuShiftRight(sim, cpuGetReg1(sim) & 31));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ST.B */
 | 
					/* ST.B */
 | 
				
			||||||
| 
						 | 
					@ -1126,55 +1255,87 @@ static int cpuST_W(VB *sim) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* STSR */
 | 
					/* STSR */
 | 
				
			||||||
static int cpuSTSR(VB *sim) {
 | 
					static void cpuSTSR(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuGetSystemRegister(sim, cpuGetImm5U(sim)));
 | 
					    cpuSetReg2(sim, cpuGetSystemRegister(sim, cpuGetImm5U(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(8));
 | 
					    cpuAdvance(sim, cpuClocks(8));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SUB */
 | 
					/* SUB */
 | 
				
			||||||
static int cpuSUB(VB *sim) {
 | 
					static void cpuSUB(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuSubtract(sim, cpuGetReg1(sim)));
 | 
					    cpuSetReg2(sim, cpuSubtract(sim, cpuGetReg1(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* SUBF.S */
 | 
				
			||||||
 | 
					static void cpuSUBF_S(VB *sim) {
 | 
				
			||||||
 | 
					    int32_t a = cpuGetReg2(sim);
 | 
				
			||||||
 | 
					    int32_t b = cpuGetReg1(sim);
 | 
				
			||||||
 | 
					    double  c; /* Result */
 | 
				
			||||||
 | 
					    int32_t d; /* Float bits for result */
 | 
				
			||||||
 | 
					    if (cpuFloatReserved(sim, a, b))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    c = (double) cpuWordToFloat(a) - cpuWordToFloat(b);
 | 
				
			||||||
 | 
					    if (cpuFloatCommon(sim, c, &d))
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    cpuSetReg2(sim, d);
 | 
				
			||||||
 | 
					    cpuAdvance(sim, cpuClocks(28)); /* TODO: Research */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* TRAP */
 | 
					/* TRAP */
 | 
				
			||||||
static int cpuTRAP(VB *sim) {
 | 
					static void cpuTRAP(VB *sim) {
 | 
				
			||||||
    sim->cpu.clocks   += cpuClocks(15);
 | 
					    sim->cpu.clocks   += cpuClocks(15);
 | 
				
			||||||
    sim->cpu.exception = 0xFFA0 + cpuGetImm5U(sim);
 | 
					    sim->cpu.exception = 0xFFA0 + cpuGetImm5U(sim);
 | 
				
			||||||
    sim->cpu.operation = CPU_EXCEPTION;
 | 
					    sim->cpu.operation = CPU_EXCEPTION;
 | 
				
			||||||
    return 0;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* TRNC.SW */
 | 
				
			||||||
 | 
					static void cpuTRNC_SW(VB *sim) {
 | 
				
			||||||
 | 
					    double  f;
 | 
				
			||||||
 | 
					    int32_t w = cpuGetReg1(sim);
 | 
				
			||||||
 | 
					    if (cpuFloatReservedOne(w)) {
 | 
				
			||||||
 | 
					        cpuThrow(sim, 0xFF60);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    f = cpuWordToFloat(w);
 | 
				
			||||||
 | 
					    if (f <= -2147483649.0 || f >= 2147483648.0) {
 | 
				
			||||||
 | 
					        sim->cpu.psw.fiv = 1;
 | 
				
			||||||
 | 
					        cpuThrow(sim, 0xFF70);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    w = f;
 | 
				
			||||||
 | 
					    cpuSetReg2(sim, w);
 | 
				
			||||||
 | 
					    if (w != f)
 | 
				
			||||||
 | 
					        sim->cpu.psw.fpr = 1;
 | 
				
			||||||
 | 
					    sim->cpu.psw.ov = 0;
 | 
				
			||||||
 | 
					    sim->cpu.psw.s  = w <  0;
 | 
				
			||||||
 | 
					    sim->cpu.psw.z  = w == 0;
 | 
				
			||||||
 | 
					    cpuAdvance(sim, cpuClocks(14)); /* TODO: Research */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* XB */
 | 
					/* XB */
 | 
				
			||||||
static int cpuXB(VB *sim) {
 | 
					static void cpuXB(VB *sim) {
 | 
				
			||||||
    uint32_t x = cpuGetReg2(sim);
 | 
					    uint32_t x = cpuGetReg2(sim);
 | 
				
			||||||
    x = (x & 0xFFFF0000) | (x << 8 & 0x0000FF00) | (x >> 8 & 0x000000FF);
 | 
					    x = (x & 0xFFFF0000) | (x << 8 & 0x0000FF00) | (x >> 8 & 0x000000FF);
 | 
				
			||||||
    cpuSetReg2(sim, x);
 | 
					    cpuSetReg2(sim, x);
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* XH */
 | 
					/* XH */
 | 
				
			||||||
static int cpuXH(VB *sim) {
 | 
					static void cpuXH(VB *sim) {
 | 
				
			||||||
    uint32_t x = cpuGetReg2(sim);
 | 
					    uint32_t x = cpuGetReg2(sim);
 | 
				
			||||||
    x = (x << 16 & 0xFFFF0000) | (x >> 16 & 0x0000FFFF);
 | 
					    x = (x << 16 & 0xFFFF0000) | (x >> 16 & 0x0000FFFF);
 | 
				
			||||||
    cpuSetReg2(sim, x);
 | 
					    cpuSetReg2(sim, x);
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* XOR */
 | 
					/* XOR */
 | 
				
			||||||
static int cpuXOR(VB *sim) {
 | 
					static void cpuXOR(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) ^ cpuGetReg1(sim)));
 | 
					    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) ^ cpuGetReg1(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* XORI */
 | 
					/* XORI */
 | 
				
			||||||
static int cpuXORI(VB *sim) {
 | 
					static void cpuXORI(VB *sim) {
 | 
				
			||||||
    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) ^ cpuGetImm16U(sim)));
 | 
					    cpuSetReg2(sim, cpuBitwise(sim, cpuGetReg2(sim) ^ cpuGetImm16U(sim)));
 | 
				
			||||||
    cpuAdvance(sim, cpuClocks(1));
 | 
					    cpuAdvance(sim, cpuClocks(1));
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1183,7 +1344,7 @@ static int cpuXORI(VB *sim) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Process component */
 | 
					/* Process component */
 | 
				
			||||||
static int cpuEmulate(VB *sim, uint32_t clocks) {
 | 
					static int cpuEmulate(VB *sim, uint32_t clocks) {
 | 
				
			||||||
    int brk;
 | 
					    int brk = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Process until there are clocks to wait */
 | 
					    /* Process until there are clocks to wait */
 | 
				
			||||||
    for (;;) {
 | 
					    for (;;) {
 | 
				
			||||||
| 
						 | 
					@ -1204,62 +1365,70 @@ static int cpuEmulate(VB *sim, uint32_t clocks) {
 | 
				
			||||||
        switch (sim->cpu.operation) {
 | 
					        switch (sim->cpu.operation) {
 | 
				
			||||||
            case CPU_FETCH: brk = cpuFetch(sim); break;
 | 
					            case CPU_FETCH: brk = cpuFetch(sim); break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            case CPU_ADD_IMM: brk = cpuADDImm(sim); break;
 | 
					            case CPU_ADD_IMM:       cpuADDImm (sim); break;
 | 
				
			||||||
            case CPU_ADD_REG: brk = cpuADDReg(sim); break;
 | 
					            case CPU_ADD_REG:       cpuADDReg (sim); break;
 | 
				
			||||||
            case CPU_ADDI   : brk = cpuADDI  (sim); break;
 | 
					            case CPU_ADDF_S :       cpuADDF_S (sim); break;
 | 
				
			||||||
            case CPU_AND    : brk = cpuAND   (sim); break;
 | 
					            case CPU_ADDI   :       cpuADDI   (sim); break;
 | 
				
			||||||
            case CPU_ANDI   : brk = cpuANDI  (sim); break;
 | 
					            case CPU_AND    :       cpuAND    (sim); break;
 | 
				
			||||||
            case CPU_BCOND  : brk = cpuBCOND (sim); break;
 | 
					            case CPU_ANDI   :       cpuANDI   (sim); break;
 | 
				
			||||||
            case CPU_CAXI   : brk = cpuCAXI  (sim); break;
 | 
					            case CPU_BCOND  :       cpuBCOND  (sim); break;
 | 
				
			||||||
            case CPU_CLI    : brk = cpuCLI   (sim); break;
 | 
					            case CPU_CAXI   : brk = cpuCAXI   (sim); break;
 | 
				
			||||||
            case CPU_CMP_IMM: brk = cpuCMPImm(sim); break;
 | 
					            case CPU_CLI    :       cpuCLI    (sim); break;
 | 
				
			||||||
            case CPU_CMP_REG: brk = cpuCMPReg(sim); break;
 | 
					            case CPU_CMP_IMM:       cpuCMPImm (sim); break;
 | 
				
			||||||
            case CPU_DIV    : brk = cpuDIV   (sim); break;
 | 
					            case CPU_CMP_REG:       cpuCMPReg (sim); break;
 | 
				
			||||||
            case CPU_DIVU   : brk = cpuDIVU  (sim); break;
 | 
					            case CPU_CMPF_S :       cpuCMPF_S (sim); break;
 | 
				
			||||||
            case CPU_HALT   : brk = cpuHALT  (sim); break;
 | 
					            case CPU_CVT_SW :       cpuCVT_SW (sim); break;
 | 
				
			||||||
            case CPU_IN_B   : brk = cpuIN_B  (sim); break;
 | 
					            case CPU_CVT_WS :       cpuCVT_WS (sim); break;
 | 
				
			||||||
            case CPU_IN_H   : brk = cpuIN_H  (sim); break;
 | 
					            case CPU_DIV    :       cpuDIV    (sim); break;
 | 
				
			||||||
            case CPU_IN_W   : brk = cpuIN_W  (sim); break;
 | 
					            case CPU_DIVF_S :       cpuDIVF_S (sim); break;
 | 
				
			||||||
            case CPU_JAL    : brk = cpuJAL   (sim); break;
 | 
					            case CPU_DIVU   :       cpuDIVU   (sim); break;
 | 
				
			||||||
            case CPU_JMP    : brk = cpuJMP   (sim); break;
 | 
					            case CPU_HALT   :       cpuHALT   (sim); break;
 | 
				
			||||||
            case CPU_JR     : brk = cpuJR    (sim); break;
 | 
					            case CPU_IN_B   : brk = cpuIN_B   (sim); break;
 | 
				
			||||||
            case CPU_LD_B   : brk = cpuLD_B  (sim); break;
 | 
					            case CPU_IN_H   : brk = cpuIN_H   (sim); break;
 | 
				
			||||||
            case CPU_LD_H   : brk = cpuLD_H  (sim); break;
 | 
					            case CPU_IN_W   : brk = cpuIN_W   (sim); break;
 | 
				
			||||||
            case CPU_LD_W   : brk = cpuLD_W  (sim); break;
 | 
					            case CPU_JAL    :       cpuJAL    (sim); break;
 | 
				
			||||||
            case CPU_LDSR   : brk = cpuLDSR  (sim); break;
 | 
					            case CPU_JMP    :       cpuJMP    (sim); break;
 | 
				
			||||||
            case CPU_MOV_IMM: brk = cpuMOVImm(sim); break;
 | 
					            case CPU_JR     :       cpuJR     (sim); break;
 | 
				
			||||||
            case CPU_MOV_REG: brk = cpuMOVReg(sim); break;
 | 
					            case CPU_LD_B   : brk = cpuLD_B   (sim); break;
 | 
				
			||||||
            case CPU_MOVEA  : brk = cpuMOVEA (sim); break;
 | 
					            case CPU_LD_H   : brk = cpuLD_H   (sim); break;
 | 
				
			||||||
            case CPU_MOVHI  : brk = cpuMOVHI (sim); break;
 | 
					            case CPU_LD_W   : brk = cpuLD_W   (sim); break;
 | 
				
			||||||
            case CPU_MPYHW  : brk = cpuMPYHW (sim); break;
 | 
					            case CPU_LDSR   :       cpuLDSR   (sim); break;
 | 
				
			||||||
            case CPU_MUL    : brk = cpuMUL   (sim); break;
 | 
					            case CPU_MOV_IMM:       cpuMOVImm (sim); break;
 | 
				
			||||||
            case CPU_MULU   : brk = cpuMULU  (sim); break;
 | 
					            case CPU_MOV_REG:       cpuMOVReg (sim); break;
 | 
				
			||||||
            case CPU_NOT    : brk = cpuNOT   (sim); break;
 | 
					            case CPU_MOVEA  :       cpuMOVEA  (sim); break;
 | 
				
			||||||
            case CPU_OR     : brk = cpuOR    (sim); break;
 | 
					            case CPU_MOVHI  :       cpuMOVHI  (sim); break;
 | 
				
			||||||
            case CPU_ORI    : brk = cpuORI   (sim); break;
 | 
					            case CPU_MPYHW  :       cpuMPYHW  (sim); break;
 | 
				
			||||||
            case CPU_OUT_B  : brk = cpuOUT_B (sim); break;
 | 
					            case CPU_MUL    :       cpuMUL    (sim); break;
 | 
				
			||||||
            case CPU_OUT_H  : brk = cpuOUT_H (sim); break;
 | 
					            case CPU_MULF_S :       cpuMULF_S (sim); break;
 | 
				
			||||||
            case CPU_OUT_W  : brk = cpuOUT_W (sim); break;
 | 
					            case CPU_MULU   :       cpuMULU   (sim); break;
 | 
				
			||||||
            case CPU_RETI   : brk = cpuRETI  (sim); break;
 | 
					            case CPU_NOT    :       cpuNOT    (sim); break;
 | 
				
			||||||
            case CPU_REV    : brk = cpuREV   (sim); break;
 | 
					            case CPU_OR     :       cpuOR     (sim); break;
 | 
				
			||||||
            case CPU_SAR_IMM: brk = cpuSARImm(sim); break;
 | 
					            case CPU_ORI    :       cpuORI    (sim); break;
 | 
				
			||||||
            case CPU_SAR_REG: brk = cpuSARReg(sim); break;
 | 
					            case CPU_OUT_B  : brk = cpuOUT_B  (sim); break;
 | 
				
			||||||
            case CPU_SEI    : brk = cpuSEI   (sim); break;
 | 
					            case CPU_OUT_H  : brk = cpuOUT_H  (sim); break;
 | 
				
			||||||
            case CPU_SETF   : brk = cpuSETF  (sim); break;
 | 
					            case CPU_OUT_W  : brk = cpuOUT_W  (sim); break;
 | 
				
			||||||
            case CPU_SHL_IMM: brk = cpuSHLImm(sim); break;
 | 
					            case CPU_RETI   :       cpuRETI   (sim); break;
 | 
				
			||||||
            case CPU_SHL_REG: brk = cpuSHLReg(sim); break;
 | 
					            case CPU_REV    :       cpuREV    (sim); break;
 | 
				
			||||||
            case CPU_SHR_IMM: brk = cpuSHRImm(sim); break;
 | 
					            case CPU_SAR_IMM:       cpuSARImm (sim); break;
 | 
				
			||||||
            case CPU_SHR_REG: brk = cpuSHRReg(sim); break;
 | 
					            case CPU_SAR_REG:       cpuSARReg (sim); break;
 | 
				
			||||||
            case CPU_ST_B   : brk = cpuST_B  (sim); break;
 | 
					            case CPU_SEI    :       cpuSEI    (sim); break;
 | 
				
			||||||
            case CPU_ST_H   : brk = cpuST_H  (sim); break;
 | 
					            case CPU_SETF   :       cpuSETF   (sim); break;
 | 
				
			||||||
            case CPU_ST_W   : brk = cpuST_W  (sim); break;
 | 
					            case CPU_SHL_IMM:       cpuSHLImm (sim); break;
 | 
				
			||||||
            case CPU_STSR   : brk = cpuSTSR  (sim); break;
 | 
					            case CPU_SHL_REG:       cpuSHLReg (sim); break;
 | 
				
			||||||
            case CPU_SUB    : brk = cpuSUB   (sim); break;
 | 
					            case CPU_SHR_IMM:       cpuSHRImm (sim); break;
 | 
				
			||||||
            case CPU_TRAP   : brk = cpuTRAP  (sim); break;
 | 
					            case CPU_SHR_REG:       cpuSHRReg (sim); break;
 | 
				
			||||||
            case CPU_XB     : brk = cpuXB    (sim); break;
 | 
					            case CPU_ST_B   : brk = cpuST_B   (sim); break;
 | 
				
			||||||
            case CPU_XH     : brk = cpuXH    (sim); break;
 | 
					            case CPU_ST_H   : brk = cpuST_H   (sim); break;
 | 
				
			||||||
            case CPU_XOR    : brk = cpuXOR   (sim); break;
 | 
					            case CPU_ST_W   : brk = cpuST_W   (sim); break;
 | 
				
			||||||
            case CPU_XORI   : brk = cpuXORI  (sim); break;
 | 
					            case CPU_STSR   :       cpuSTSR   (sim); break;
 | 
				
			||||||
 | 
					            case CPU_SUB    :       cpuSUB    (sim); break;
 | 
				
			||||||
 | 
					            case CPU_SUBF_S :       cpuSUBF_S (sim); break;
 | 
				
			||||||
 | 
					            case CPU_TRAP   :       cpuTRAP   (sim); break;
 | 
				
			||||||
 | 
					            case CPU_TRNC_SW:       cpuTRNC_SW(sim); break;
 | 
				
			||||||
 | 
					            case CPU_XB     :       cpuXB     (sim); break;
 | 
				
			||||||
 | 
					            case CPU_XH     :       cpuXH     (sim); break;
 | 
				
			||||||
 | 
					            case CPU_XOR    :       cpuXOR    (sim); break;
 | 
				
			||||||
 | 
					            case CPU_XORI   :       cpuXORI   (sim); break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            default: return -1; /* TODO: Temporary for debugging */
 | 
					            default: return -1; /* TODO: Temporary for debugging */
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue