Finalizing breakpoint architecture, correcting CPU conditions, tweaking top-level emulation logic
This commit is contained in:
parent
826e921dac
commit
e13c56e1e7
8
makefile
8
makefile
|
@ -1,6 +1,6 @@
|
|||
# Java include directory pathnames
|
||||
# The Windows files need to be copied from a Windows JDK installation
|
||||
include_linux = /usr/lib/jvm/java-14-openjdk-`\
|
||||
include_linux = /usr/lib/jvm/java-15-openjdk-`\
|
||||
uname -r | sed 's/.*-//'`/include
|
||||
include_windows = jni-windows-include
|
||||
|
||||
|
@ -10,12 +10,12 @@ default:
|
|||
@echo $(include_linux)
|
||||
@echo "Planet Virtual Boy Emulator"
|
||||
@echo " https://www.planetvb.com/"
|
||||
@echo " October 16, 2020"
|
||||
@echo " December 17, 2020"
|
||||
@echo
|
||||
@echo "Intended build environment: Debian i386 or amd64"
|
||||
@echo " gcc-multilib"
|
||||
@echo " mingw-w64"
|
||||
@echo " openjdk-14-jdk"
|
||||
@echo " openjdk-15-jdk"
|
||||
@echo
|
||||
@echo "Usage: make <recipe>"
|
||||
@echo " Package recipes:"
|
||||
|
@ -69,7 +69,7 @@ core:
|
|||
desktop: clean_desktop
|
||||
@echo " Compiling Java desktop application"
|
||||
@javac -sourcepath src/desktop --release 10 -Xlint:unchecked \
|
||||
-h src/desktop/vue -d . src/desktop/Main.java
|
||||
-Xlint:deprecation -h src/desktop/vue -d . src/desktop/Main.java
|
||||
|
||||
# Build all native modules
|
||||
.PHONY: native
|
||||
|
|
|
@ -436,7 +436,7 @@ static int8_t cpuTestCondition(Vue *vue, int32_t condition) {
|
|||
case 3: return vue->cpu.psw_cy | vue->cpu.psw_z;
|
||||
case 4: return vue->cpu.psw_s;
|
||||
case 5: return 1;
|
||||
case 6: return vue->cpu.psw_ov | vue->cpu.psw_s;
|
||||
case 6: return vue->cpu.psw_ov ^ vue->cpu.psw_s;
|
||||
case 7: return (vue->cpu.psw_ov ^ vue->cpu.psw_s) | vue->cpu.psw_z;
|
||||
}
|
||||
return cpuTestCondition(vue, condition & 7) ^ 1;
|
||||
|
@ -1174,8 +1174,8 @@ static vbool cpuException(Vue *vue) {
|
|||
/* Process the simulation */
|
||||
static void cpuEmulate(Vue *vue, int32_t cycles) {
|
||||
|
||||
/* The CPU is in permanent halt */
|
||||
if (vue->cpu.stage == CPU_FATAL)
|
||||
/* The CPU is halting */
|
||||
if (vue->cpu.stage == CPU_FATAL || vue->cpu.stage == CPU_HALT)
|
||||
return;
|
||||
|
||||
vue->cpu.cycles = 0; /* DEBUG: Stop processing after execute */
|
||||
|
@ -1190,6 +1190,7 @@ vue->cpu.cycles = 0; /* DEBUG: Stop processing after execute */
|
|||
}
|
||||
|
||||
/* Processing by stage */
|
||||
vue->cpu.cycles = 0;
|
||||
switch (vue->cpu.stage) {
|
||||
case CPU_EXCEPTION: if (cpuException (vue)) return; break;
|
||||
case CPU_EXECUTE : if (cpuExecute (vue)) return; break;
|
||||
|
|
|
@ -49,31 +49,41 @@ public class Main {
|
|||
useNative = true;
|
||||
|
||||
// Begin application operations
|
||||
new App(useNative);
|
||||
//new App(useNative);
|
||||
|
||||
/*
|
||||
var brk = new Breakpoint(null);
|
||||
|
||||
String exp =
|
||||
"([sp - 8] & 3) << 6 != 12.0 + r6 * ecr && [0x0500008C + r8] == 0";
|
||||
/*
|
||||
//String exp =
|
||||
// "([sp - 8] & 3) << 6 != 12.0 + r6 * ecr && [0x0500008C + r8] == 0";
|
||||
//String exp = "float true + -3 * 4";
|
||||
String exp = "1100 ^ uword 1010";
|
||||
System.out.println("\n" + exp);
|
||||
if (brk.setCondition(exp))
|
||||
System.out.println(brk.debug());
|
||||
else System.out.println(
|
||||
brk.getErrorCode (Breakpoint.CONDITION) + "\t" +
|
||||
brk.getErrorPosition(Breakpoint.CONDITION) + ":" +
|
||||
brk.getErrorText (Breakpoint.CONDITION)
|
||||
System.out.println(brk.debugTokens());
|
||||
else {
|
||||
var err = brk.getConditionError();
|
||||
System.out.println("Error " +
|
||||
err.code + "\t" +
|
||||
err.position + ":" +
|
||||
err.text
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
exp = "123, 456 - 987 , f0-fffffff2";
|
||||
System.out.println("\n" + exp);
|
||||
if (brk.setAddresses(exp))
|
||||
System.out.println(brk.test());
|
||||
else System.out.println(
|
||||
brk.getErrorCode (Breakpoint.ADDRESS) + "\t" +
|
||||
brk.getErrorPosition(Breakpoint.ADDRESS) + ":" +
|
||||
brk.getErrorText (Breakpoint.ADDRESS)
|
||||
System.out.println(brk.debugRanges());
|
||||
else {
|
||||
var err = brk.getAddressError();
|
||||
System.out.println("Error " +
|
||||
err.code + "\t" +
|
||||
err.position + ":" +
|
||||
err.text
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
|
@ -1,636 +1,4 @@
|
|||
// This file is included through NativeVUE.c and cannot be built directly. */
|
||||
#ifdef NATIVEVUE
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Constants //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Token types
|
||||
#define BINARY 4
|
||||
#define FLOAT 1
|
||||
#define UNARY 3
|
||||
#define SYMBOL 2
|
||||
#define WORD 0
|
||||
|
||||
// CPU stages
|
||||
#define EXCEPTION 2
|
||||
#define EXECUTE 1
|
||||
|
||||
// Operator IDs
|
||||
#define ADD 2
|
||||
#define BITWISE_AND 3
|
||||
#define BITWISE_NOT 4
|
||||
#define BITWISE_OR 5
|
||||
#define BITWISE_XOR 6
|
||||
#define CEIL 7
|
||||
#define DIVIDE 8
|
||||
#define EQUAL 9
|
||||
#define FLOOR 10
|
||||
//#define FLOAT 1 // Same as type
|
||||
#define GREATER_EQUAL_SIGNED 11
|
||||
#define GREATER_EQUAL_UNSIGNED 12
|
||||
#define GREATER_SIGNED 13
|
||||
#define GREATER_UNSIGNED 14
|
||||
#define GROUP 15
|
||||
#define LESS_EQUAL_SIGNED 16
|
||||
#define LESS_EQUAL_UNSIGNED 17
|
||||
#define LESS_SIGNED 18
|
||||
#define LESS_UNSIGNED 19
|
||||
#define LOGICAL_AND 20
|
||||
#define LOGICAL_NOT 21
|
||||
#define LOGICAL_OR 22
|
||||
#define LOGICAL_XOR 23
|
||||
#define MULTIPLY 24
|
||||
#define NEGATE 25
|
||||
#define NOT_EQUAL 26
|
||||
#define READ_WORD 27
|
||||
#define REMAINDER 28
|
||||
#define ROUND 29
|
||||
#define SHIFT_LEFT 30
|
||||
#define SHIFT_RIGHT 31
|
||||
#define SHIFT_RIGHT_ARITHMETIC 32
|
||||
#define SUBTRACT 33
|
||||
#define TRUNC 34
|
||||
//#define WORD 0 // Same as type
|
||||
#define XFLOAT 35
|
||||
#define XWORD 36
|
||||
|
||||
// Functional symbol IDs
|
||||
#define ADDRESS 0
|
||||
#define CODE 1
|
||||
#define COND 2
|
||||
#define DISP 3
|
||||
#define FORMAT 4
|
||||
#define ID 5
|
||||
#define IMM 6
|
||||
#define OPCODE 7
|
||||
#define REG1 8
|
||||
#define REG2 9
|
||||
#define REGID 10
|
||||
#define SIZE 11
|
||||
#define SUBOPCODE 12
|
||||
#define VALUE 13
|
||||
#define VECTOR 14
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Evaluation Helpers //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Resolve a float from word bits
|
||||
static float asFloat(int32_t value) {
|
||||
return *(float *)&value;
|
||||
}
|
||||
|
||||
// Resolve the word bits of a float
|
||||
static int32_t asWord(float value) {
|
||||
int32_t bits = *(int32_t *)&value;
|
||||
int32_t exp = bits & 0x7F800000;
|
||||
int32_t digits = bits & 0x007FFFFF;
|
||||
return
|
||||
!(bits & 0x7FFFFFFF) || // Zero
|
||||
exp == 0x7F800000 || // Indefinite
|
||||
!exp && digits != 0 // Denormal
|
||||
? 0 : bits;
|
||||
}
|
||||
|
||||
// Convert a float to a word
|
||||
static int32_t toWord(float value) {
|
||||
value = roundf(value);
|
||||
return value>=0x7FFFFFFF || value<(int32_t)0x80000000 ? 0 : (int) value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Binary Functions //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Evaluate +
|
||||
static int32_t evalAdd(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return leftWord && rightWord ? leftValue + rightValue : asWord(
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) +
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate &
|
||||
static int32_t evalBitwiseAnd(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return (leftWord ? leftValue : toWord(asFloat(leftValue ))) &
|
||||
(rightWord ? rightValue : toWord(asFloat(rightValue)));
|
||||
}
|
||||
|
||||
// Evaluate |
|
||||
static int32_t evalBitwiseOr(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return (leftWord ? leftValue : toWord(asFloat(leftValue ))) |
|
||||
(rightWord ? rightValue : toWord(asFloat(rightValue)));
|
||||
}
|
||||
|
||||
// Evaluate ^
|
||||
static int32_t evalBitwiseXOr(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return (leftWord ? leftValue : toWord(asFloat(leftValue ))) ^
|
||||
(rightWord ? rightValue : toWord(asFloat(rightValue)));
|
||||
}
|
||||
|
||||
// Evaluate /
|
||||
static int32_t evalDivide(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return !(rightWord ? rightValue : rightValue & 0x7FFFFFFF) ? 0 :
|
||||
leftWord && rightWord ? leftValue / rightValue : asWord(
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) /
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate ==
|
||||
static int32_t evalEqual(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return leftWord && rightWord ? leftValue == rightValue : (
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) ==
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate >=
|
||||
static int32_t evalGreaterEqualSigned(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return leftWord && rightWord ? leftValue >= rightValue : (
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) >=
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate >=_
|
||||
static int32_t evalGreaterEqualUnsigned(
|
||||
int32_t leftWord,uint32_t leftValue,int32_t rightWord,uint32_t rightValue){
|
||||
return leftWord && rightWord ? leftValue >= rightValue : (
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) >=
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate >
|
||||
static int32_t evalGreaterSigned(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return leftWord && rightWord ? leftValue > rightValue : (
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) >
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate >_
|
||||
static int32_t evalGreaterUnsigned(
|
||||
int32_t leftWord,uint32_t leftValue,int32_t rightWord,uint32_t rightValue){
|
||||
return leftWord && rightWord ? leftValue > rightValue : (
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) >
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate <=
|
||||
static int32_t evalLessEqualSigned(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return leftWord && rightWord ? leftValue <= rightValue : (
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) <=
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate <=_
|
||||
static int32_t evalLessEqualUnsigned(
|
||||
int32_t leftWord,uint32_t leftValue,int32_t rightWord,uint32_t rightValue){
|
||||
return leftWord && rightWord ? leftValue <= rightValue : (
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) <=
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate <
|
||||
static int32_t evalLessSigned(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return leftWord && rightWord ? leftValue < rightValue : (
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) <
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate <_
|
||||
static int32_t evalLessUnsigned(
|
||||
int32_t leftWord,uint32_t leftValue,int32_t rightWord,uint32_t rightValue){
|
||||
return leftWord && rightWord ? leftValue < rightValue : (
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) <
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate *
|
||||
static int32_t evalMultiply(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return leftWord && rightWord ? leftValue * rightValue : asWord(
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) *
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate !=
|
||||
static int32_t evalNotEqual(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return leftWord && rightWord ? leftValue != rightValue : (
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) !=
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
// Evaluate %
|
||||
static int32_t evalRemainder(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return !(rightWord ? rightValue : rightValue & 0x7FFFFFFF) ? 0 :
|
||||
leftWord && rightWord ? leftValue % rightValue : asWord(fmodf(
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )),
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
));
|
||||
}
|
||||
|
||||
// Evaluate <<
|
||||
static int32_t evalShiftLeft(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
leftValue = leftWord ? leftValue : toWord(asFloat(leftValue ));
|
||||
leftValue = (rightWord ? rightValue : toWord(asFloat(rightValue))) & 31;
|
||||
return leftValue << rightValue;
|
||||
}
|
||||
|
||||
// Evaluate >>
|
||||
static int32_t evalShiftRightArithmetic(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
leftValue = leftWord ? leftValue : toWord(asFloat(leftValue ));
|
||||
leftValue = (rightWord ? rightValue : toWord(asFloat(rightValue))) & 31;
|
||||
return !rightValue ? leftValue :
|
||||
leftValue >> rightValue & (1 << 32 - rightValue) - 1;
|
||||
}
|
||||
|
||||
// Evaluate >>>
|
||||
static int32_t evalShiftRight(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
leftValue = leftWord ? leftValue : toWord(asFloat(leftValue ));
|
||||
leftValue = (rightWord ? rightValue : toWord(asFloat(rightValue))) & 31;
|
||||
if (!rightValue)
|
||||
return leftValue;
|
||||
leftValue >>= rightValue;
|
||||
rightValue = 32 - rightValue;
|
||||
return SIGN_EXTEND(rightValue, leftValue);
|
||||
}
|
||||
|
||||
// Evaluate -
|
||||
static int32_t evalSubtract(
|
||||
int32_t leftWord,int32_t leftValue,int32_t rightWord,int32_t rightValue) {
|
||||
return leftWord && rightWord ? leftValue - rightValue : asWord(
|
||||
(leftWord ? (float) leftValue : asFloat(leftValue )) -
|
||||
(rightWord ? (float) rightValue : asFloat(rightValue))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Symbol Functions //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Evaluate address
|
||||
static int32_t evalAddress(Vue *vue) {
|
||||
if (vue->cpu.inst.format == 6)
|
||||
return vue->cpu.program[vue->cpu.inst.reg1] + vue->cpu.inst.disp;
|
||||
switch (vue->cpu.inst.id) {
|
||||
case VUE_BCOND: case VUE_JAL: case VUE_JMP: case VUE_JR:
|
||||
return vue->cpu.pc + vue->cpu.inst.disp;
|
||||
case VUE_RETI:
|
||||
return vue->cpu.psw_np ? vue->cpu.fepc : vue->cpu.eipc;
|
||||
case VUE_TRAP:
|
||||
return 0xFFFFFFA0 + vue->cpu.inst.imm & 0xFFFFFFF0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluate cond
|
||||
static int32_t evalCond(Vue *vue) {
|
||||
switch (vue->cpu.inst.id) {
|
||||
case VUE_BCOND: return vue->cpu.inst.cond;
|
||||
case VUE_SETF : return vue->cpu.inst.imm;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluate disp
|
||||
static int32_t evalDisp(Vue *vue) {
|
||||
switch (vue->cpu.inst.format) {
|
||||
case 3: case 4: case 6: return vue->cpu.inst.disp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluate imm
|
||||
static int32_t evalImm(Vue *vue) {
|
||||
switch (vue->cpu.inst.format) {
|
||||
case 2: case 5: return vue->cpu.inst.imm;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluate reg1
|
||||
static int32_t evalReg1(Vue *vue) {
|
||||
switch (vue->cpu.inst.format) {
|
||||
case 1: case 5: case 6: case 7: return vue->cpu.inst.reg1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluate reg2
|
||||
static int32_t evalReg2(Vue *vue) {
|
||||
switch (vue->cpu.inst.format) {
|
||||
case 1: case 2: case 5: case 6: case 7: return vue->cpu.inst.reg2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluate regid
|
||||
static int32_t evalRegId(Vue *vue) {
|
||||
switch (vue->cpu.inst.id) {
|
||||
case VUE_LDSR: case VUE_STSR: return vue->cpu.inst.imm;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluate subopcode
|
||||
static int32_t evalSubopcode(Vue *vue) {
|
||||
switch (vue->cpu.inst.opcode) {
|
||||
case 0x1F: return vue->cpu.inst.imm;
|
||||
case 0x3E: return vue->cpu.inst.subopcode;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Evaluate value
|
||||
static int evalValue(Vue *vue) {
|
||||
return vue->cpu.inst.format == 6 ? vue->cpu.access.value : 0;
|
||||
}
|
||||
|
||||
// Evaluate vector
|
||||
static int evalVector(Vue *vue) {
|
||||
return vue->cpu.inst.id == VUE_TRAP ? vue->cpu.inst.imm : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Unary Functions //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Evaluate ~
|
||||
static int32_t evalBitwiseNot(int32_t isWord, int32_t value) {
|
||||
return isWord ? ~value : ~toWord(asFloat(value));
|
||||
}
|
||||
|
||||
// Evaluate !
|
||||
static int32_t evalLogicalNot(int32_t isWord, int32_t value) {
|
||||
return isWord ? !value : !asFloat(value);
|
||||
}
|
||||
|
||||
// Evaluate -
|
||||
static int32_t evalNegate(int32_t isWord, int32_t value) {
|
||||
return isWord ? -value : asWord(-asFloat(value));
|
||||
}
|
||||
|
||||
// Evaluate ceil
|
||||
static int32_t evalCeil(int32_t isWord, int32_t value) {
|
||||
return isWord ? value : asWord(ceilf(asFloat(value)));
|
||||
}
|
||||
|
||||
// Evaluate float
|
||||
static int32_t evalFloat(int32_t isWord, int32_t value) {
|
||||
return isWord ? asWord((float) value) : value;
|
||||
}
|
||||
|
||||
// Evaluate floor
|
||||
static int32_t evalFloor(int32_t isWord, int32_t value) {
|
||||
return isWord ? value : asWord(floorf(asFloat(value)));
|
||||
}
|
||||
|
||||
// Evaluate []
|
||||
static int32_t evalReadWord(int32_t isWord, int32_t value, Vue *vue) {
|
||||
return vueRead(vue, isWord ? value : toWord(asFloat(value)), VUE_S32);
|
||||
}
|
||||
|
||||
// Evaluate round
|
||||
static int32_t evalRound(int32_t isWord, int32_t value) {
|
||||
return isWord ? value : asWord(roundf(asFloat(value)));
|
||||
}
|
||||
|
||||
// Evaluate trunc
|
||||
static int32_t evalTrunc(int32_t isWord, int32_t value) {
|
||||
return isWord ? value : asWord(truncf(asFloat(value)));
|
||||
}
|
||||
|
||||
// Evaluate word
|
||||
static int32_t evalWord(int32_t isWord, int32_t value) {
|
||||
return isWord ? value : toWord(asFloat(value));
|
||||
}
|
||||
|
||||
// Evaluate xfloat
|
||||
static int32_t evalXFloat(int32_t isWord, int32_t value) {
|
||||
return isWord ? asWord(asFloat(value)) : value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Evaluation Functions //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Evaluate a binary operator
|
||||
static int32_t evalBinary(int32_t id, int32_t *stack, int32_t size) {
|
||||
int32_t rv = stack[size - 1];
|
||||
int32_t rt = stack[size - 2];
|
||||
int32_t rw = rt == WORD;
|
||||
int32_t lv = stack[size - 3];
|
||||
int32_t lt = stack[size - 4];
|
||||
int32_t lw = lt == WORD;
|
||||
int32_t type = rw && lw ? WORD : FLOAT;
|
||||
int32_t value = 0;
|
||||
switch (id) {
|
||||
|
||||
// Arithmetic
|
||||
case ADD :
|
||||
value = evalAdd (lw, lv, rw, rv); break;
|
||||
case DIVIDE :
|
||||
value = evalDivide (lw, lv, rw, rv); break;
|
||||
case MULTIPLY :
|
||||
value = evalMultiply (lw, lv, rw, rv); break;
|
||||
case REMAINDER :
|
||||
value = evalRemainder (lw, lv, rw, rv); break;
|
||||
case SUBTRACT :
|
||||
value = evalSubtract (lw, lv, rw, rv); break;
|
||||
default:
|
||||
type = WORD; switch (id) {
|
||||
|
||||
// Bitwise
|
||||
case BITWISE_AND :
|
||||
value = evalBitwiseAnd (lw, lv, rw, rv); break;
|
||||
case BITWISE_OR :
|
||||
value = evalBitwiseOr (lw, lv, rw, rv); break;
|
||||
case BITWISE_XOR :
|
||||
value = evalBitwiseXOr (lw, lv, rw, rv); break;
|
||||
case SHIFT_LEFT :
|
||||
value = evalShiftLeft (lw, lv, rw, rv); break;
|
||||
case SHIFT_RIGHT :
|
||||
value = evalShiftRight (lw, lv, rw, rv); break;
|
||||
case SHIFT_RIGHT_ARITHMETIC:
|
||||
value = evalShiftRightArithmetic(lw, lv, rw, rv); break;
|
||||
|
||||
// Relational
|
||||
case EQUAL :
|
||||
value = evalEqual (lw, lv, rw, rv); break;
|
||||
case GREATER_EQUAL_SIGNED :
|
||||
value = evalGreaterEqualSigned (lw, lv, rw, rv); break;
|
||||
case GREATER_EQUAL_UNSIGNED:
|
||||
value = evalGreaterEqualUnsigned(lw, lv, rw, rv); break;
|
||||
case GREATER_SIGNED :
|
||||
value = evalGreaterSigned (lw, lv, rw, rv); break;
|
||||
case GREATER_UNSIGNED :
|
||||
value = evalGreaterUnsigned (lw, lv, rw, rv); break;
|
||||
case LESS_EQUAL_SIGNED :
|
||||
value = evalLessEqualSigned (lw, lv, rw, rv); break;
|
||||
case LESS_EQUAL_UNSIGNED :
|
||||
value = evalLessEqualUnsigned (lw, lv, rw, rv); break;
|
||||
case LESS_SIGNED :
|
||||
value = evalLessSigned (lw, lv, rw, rv); break;
|
||||
case LESS_UNSIGNED :
|
||||
value = evalLessUnsigned (lw, lv, rw, rv); break;
|
||||
case NOT_EQUAL :
|
||||
value = evalNotEqual (lw, lv, rw, rv); break;
|
||||
|
||||
// Logical
|
||||
default:
|
||||
lw = (lv & (lw ? 0xFFFFFFFF : 0x7FFFFFFF)) != 0;
|
||||
rw = (rv & (rw ? 0xFFFFFFFF : 0x7FFFFFFF)) != 0;
|
||||
|
||||
// Evaluate &&
|
||||
case LOGICAL_AND:
|
||||
type = lt; value = lv;
|
||||
if (lw)
|
||||
{ type = rt; value = rv; }
|
||||
break;
|
||||
|
||||
// Evaluate ||
|
||||
case LOGICAL_OR:
|
||||
type = lt; value = lv;
|
||||
if (!lw)
|
||||
{ type = rt; value = rv; }
|
||||
break;
|
||||
|
||||
// Evaluate ^^
|
||||
case LOGICAL_XOR:
|
||||
type = rt; value = rv;
|
||||
if (lw == rw)
|
||||
{ type = WORD; value = 0; }
|
||||
else if (lw)
|
||||
{ type = lt; value = lv; }
|
||||
break;
|
||||
}}
|
||||
stack[size - 4] = type;
|
||||
stack[size - 3] = value;
|
||||
return size - 2;
|
||||
}
|
||||
|
||||
// Evaluate a functional symbol
|
||||
static int32_t evalSymbol(Vue *vue, int32_t id, int32_t *stack, int32_t size) {
|
||||
int32_t ret = 0;
|
||||
if (id == VUE_PC)
|
||||
ret = vue->cpu.pc;
|
||||
else if (id >= 200)
|
||||
ret = vueGetRegister(vue, id - 200, VUE_TRUE);
|
||||
else if (id >= 100)
|
||||
ret = vue->cpu.program[id - 100];
|
||||
else if (vue->cpu.stage == EXCEPTION && id == CODE)
|
||||
ret = vue->cpu.exception.code;
|
||||
else if (vue->cpu.stage == EXECUTE) switch (id) {
|
||||
case ADDRESS : ret = evalAddress (vue); break;
|
||||
case COND : ret = evalCond (vue); break;
|
||||
case DISP : ret = evalDisp (vue); break;
|
||||
case FORMAT : ret = vue->cpu.inst.format; break;
|
||||
case ID : ret = vue->cpu.inst.id ; break;
|
||||
case IMM : ret = evalImm (vue); break;
|
||||
case OPCODE : ret = vue->cpu.inst.opcode; break;
|
||||
case REG1 : ret = evalReg1 (vue); break;
|
||||
case REG2 : ret = evalReg2 (vue); break;
|
||||
case REGID : ret = evalRegId (vue); break;
|
||||
case SIZE : ret = vue->cpu.inst.size ; break;
|
||||
case SUBOPCODE: ret = evalSubopcode (vue); break;
|
||||
case VALUE : ret = evalValue (vue); break;
|
||||
case VECTOR : ret = evalVector (vue); break;
|
||||
}
|
||||
stack[size++] = WORD;
|
||||
stack[size++] = ret;
|
||||
return size;
|
||||
}
|
||||
|
||||
// Evaluate a unary operator
|
||||
static void evalUnary(Vue *vue, int32_t id, int32_t *stack, int32_t size) {
|
||||
int32_t type = stack[size - 2];
|
||||
int32_t value = stack[size - 1];
|
||||
int32_t isWord = type == WORD;
|
||||
switch (id) {
|
||||
case BITWISE_NOT: value = evalBitwiseNot(isWord, value);
|
||||
type = WORD ; break;
|
||||
case LOGICAL_NOT: value = evalLogicalNot(isWord, value);
|
||||
type = WORD ; break;
|
||||
case NEGATE : value = evalNegate (isWord, value); break;
|
||||
case CEIL : value = evalCeil (isWord, value); break;
|
||||
case FLOAT : value = evalFloat (isWord, value);
|
||||
type = FLOAT; break;
|
||||
case FLOOR : value = evalFloor (isWord, value); break;
|
||||
case READ_WORD : value = evalReadWord (isWord, value, vue);
|
||||
type = WORD ; break;
|
||||
case ROUND : value = evalRound (isWord, value); break;
|
||||
case TRUNC : value = evalTrunc (isWord, value); break;
|
||||
case WORD : value = evalWord (isWord, value);
|
||||
type = WORD ; break;
|
||||
case XFLOAT : value = evalXFloat (isWord, value);
|
||||
type = FLOAT; break;
|
||||
case XWORD : type = WORD;
|
||||
}
|
||||
stack[size - 2] = type;
|
||||
stack[size - 1] = value;
|
||||
}
|
||||
|
||||
// Evaluate a breakpoint condition for an emulation context
|
||||
int32_t evaluate(Vue *vue, Breakpoint *brk, int32_t *stack) {
|
||||
|
||||
// The condition is empty
|
||||
if (brk->numTokens == 0)
|
||||
return brk->enabled;
|
||||
|
||||
// Process tokens
|
||||
int size = 0;
|
||||
for (int x = 0; x < brk->numTokens; x++) {
|
||||
Token *tok = &brk->tokens[x];
|
||||
switch (tok->type) {
|
||||
case BINARY: size =
|
||||
evalBinary( tok->value, stack, size); continue;
|
||||
case SYMBOL: size =
|
||||
evalSymbol(vue, tok->value, stack, size); continue;
|
||||
case UNARY :
|
||||
evalUnary (vue, tok->value, stack, size); continue;
|
||||
}
|
||||
stack[size++] = tok->type;
|
||||
stack[size++] = tok->value;
|
||||
}
|
||||
return (stack[1] & (stack[0] == WORD ? 0xFFFFFFFF : 0x7FFFFFFF)) != 0;
|
||||
}
|
||||
|
||||
#endif // NATIVEVUE
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,7 +12,7 @@ class CPU {
|
|||
// Package fields
|
||||
Access access; // Access state
|
||||
int cycles; // Cycles until next stage
|
||||
Ecxeption exception; // Exception code
|
||||
Ecxeption exception; // Exception state
|
||||
int fetch; // Fetch unit index
|
||||
Instruction inst; // Instruction state
|
||||
int irq; // Interrupt lines
|
||||
|
@ -114,8 +114,8 @@ class CPU {
|
|||
// Process the simulation
|
||||
void emulate(int cycles) {
|
||||
|
||||
// The CPU is in permanent halt
|
||||
if (stage == FATAL)
|
||||
// The CPU is halting
|
||||
if (stage == HALT || stage == FATAL)
|
||||
return;
|
||||
|
||||
this.cycles = 0; // DEBUG: Stop processing after execute
|
||||
|
@ -130,6 +130,7 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
}
|
||||
|
||||
// Processing by stage
|
||||
this.cycles = 0;
|
||||
switch (stage) {
|
||||
case EXCEPTION: if (exception ()) return; break;
|
||||
case EXECUTE : if (execute ()) return; break;
|
||||
|
@ -273,7 +274,7 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
private boolean exception() {
|
||||
|
||||
// Application callback
|
||||
vue.breakCode = vue.onException(exception);
|
||||
vue.breakCode = vue.onException() ? 1 : 0;
|
||||
if (vue.breakCode != 0)
|
||||
return true;
|
||||
|
||||
|
@ -331,7 +332,7 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
private boolean execute() {
|
||||
|
||||
// Application callback
|
||||
vue.breakCode = vue.onExecute(inst);
|
||||
vue.breakCode = vue.onExecute() ? 1 : 0;
|
||||
if (vue.breakCode != 0)
|
||||
return true;
|
||||
|
||||
|
@ -471,7 +472,7 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
access.value = vue.read(address, type);
|
||||
|
||||
// Application callback
|
||||
vue.breakCode = vue.onRead(access);
|
||||
vue.breakCode = vue.onRead() ? 1 : 0;
|
||||
return vue.breakCode != 0;
|
||||
}
|
||||
|
||||
|
@ -484,7 +485,7 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
case 3: return psw_cy | psw_z;
|
||||
case 4: return psw_s;
|
||||
case 5: return 1;
|
||||
case 6: return psw_ov | psw_s;
|
||||
case 6: return psw_ov ^ psw_s;
|
||||
case 7: return psw_ov ^ psw_s | psw_z;
|
||||
}
|
||||
return testCondition(condition & 7) ^ 1;
|
||||
|
@ -522,7 +523,7 @@ this.cycles = 0; // DEBUG: Stop processing after execute
|
|||
access.value = value;
|
||||
|
||||
// Application callback
|
||||
vue.breakCode = vue.onWrite(access);
|
||||
vue.breakCode = vue.onWrite() ? 1 : 0;
|
||||
if (vue.breakCode != 0)
|
||||
return true;
|
||||
if (access.type == Vue.CANCEL)
|
||||
|
|
|
@ -17,4 +17,10 @@ public class Ecxeption {
|
|||
// Default constructor
|
||||
Ecxeption() { }
|
||||
|
||||
// Cloning constructor
|
||||
Ecxeption(Ecxeption o) {
|
||||
this();
|
||||
code = o.code;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -82,6 +82,22 @@ public class Instruction {
|
|||
// Default constructor
|
||||
public Instruction() { }
|
||||
|
||||
// Cloning constructor
|
||||
Instruction(Instruction o) {
|
||||
this();
|
||||
bits = o.bits;
|
||||
cond = o.cond;
|
||||
disp = o.disp;
|
||||
format = o.format;
|
||||
id = o.id;
|
||||
imm = o.imm;
|
||||
opcode = o.opcode;
|
||||
reg1 = o.reg1;
|
||||
reg2 = o.reg2;
|
||||
size = o.size;
|
||||
subopcode = o.subopcode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -9,7 +9,9 @@ class JavaVue extends Vue {
|
|||
// Package fields
|
||||
int breakCode; // Application break code
|
||||
CPU cpu; // Processor
|
||||
int hook; // Most recent breakpoint hook
|
||||
GamePak pak; // Game pak
|
||||
int[] stack; // Breakpoint evaluation stack
|
||||
byte[] wram; // System WRAM
|
||||
|
||||
|
||||
|
@ -31,6 +33,7 @@ class JavaVue extends Vue {
|
|||
JavaVue() {
|
||||
cpu = new CPU (this);
|
||||
pak = new GamePak(this);
|
||||
stack = new int[0];
|
||||
wram = new byte[0x10000];
|
||||
reset();
|
||||
}
|
||||
|
@ -52,12 +55,12 @@ class JavaVue extends Vue {
|
|||
|
||||
// Determine the number of cycles during which nothing will happen
|
||||
int cycles = -1;
|
||||
cycles = cpu .until(cycles);
|
||||
//cycles = pad .until(cycles);
|
||||
//cycles = link .until(cycles);
|
||||
//cycles = timer.until(cycles);
|
||||
//cycles = vip .until(cycles);
|
||||
//cycles = vsu .until(cycles);
|
||||
cycles = cpu .until(cycles);
|
||||
|
||||
// Range checking
|
||||
if (cycles == -1) // No activity on any component
|
||||
|
@ -66,17 +69,16 @@ class JavaVue extends Vue {
|
|||
cycles = Math.min(cycles, maxCycles);
|
||||
|
||||
// Process all system components
|
||||
breakCode = 0;
|
||||
cpu .emulate(cycles);
|
||||
//pad .emulate(cycles);
|
||||
//link .emulate(cycles);
|
||||
//timer.emulate(cycles);
|
||||
//vip .emulate(cycles);
|
||||
//vsu .emulate(cycles);
|
||||
cpu .emulate(cycles);
|
||||
|
||||
// An application break was requested
|
||||
if (breakCode != 0)
|
||||
break;
|
||||
//if (...)
|
||||
// break;
|
||||
|
||||
// Update the number of cycles remaining
|
||||
if (maxCycles >= 0)
|
||||
|
@ -87,9 +89,14 @@ class JavaVue extends Vue {
|
|||
return Math.max(0, maxCycles);
|
||||
}
|
||||
|
||||
// Retrieve the application break code
|
||||
public int getBreakCode() {
|
||||
return breakCode;
|
||||
// Evaluate an expression
|
||||
public Object evaluate(String expression) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Retrieve the most recent exception code
|
||||
public int getException() {
|
||||
return cpu.exception.code;
|
||||
}
|
||||
|
||||
// Retrieve a register value
|
||||
|
@ -249,23 +256,23 @@ class JavaVue extends Vue {
|
|||
}
|
||||
|
||||
// Exception break handler
|
||||
int onException(Ecxeption exp) {
|
||||
return 0;
|
||||
boolean onException() {
|
||||
return onHook(Breakpoint.EXCEPTION);
|
||||
}
|
||||
|
||||
// Execute break handler
|
||||
int onExecute(Instruction inst) {
|
||||
return 0;
|
||||
boolean onExecute() {
|
||||
return onHook(Breakpoint.EXECUTE);
|
||||
}
|
||||
|
||||
// Read break handler
|
||||
int onRead(Access acc) {
|
||||
return 0;
|
||||
boolean onRead() {
|
||||
return onHook(Breakpoint.READ);
|
||||
}
|
||||
|
||||
// Write break handler
|
||||
int onWrite(Access acc) {
|
||||
return 0;
|
||||
boolean onWrite() {
|
||||
return onHook(Breakpoint.WRITE);
|
||||
}
|
||||
|
||||
// Read a value from a byte buffer
|
||||
|
@ -370,4 +377,19 @@ class JavaVue extends Vue {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Private Methods //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Check breakpoints during a hooked event
|
||||
private boolean onHook(int hook) {
|
||||
this.hook = hook;
|
||||
for (var brk : breakpoints)
|
||||
if (evaluate(brk))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -259,102 +259,3 @@ JNIEXPORT jboolean JNICALL Java_vue_NativeVue_writeBytes
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Private Methods //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Produce a new breakpoint and add it to the collection
|
||||
JNIEXPORT void JNICALL Java_vue_NativeVue_breakpoint
|
||||
(JNIEnv *env, jobject vue, jlong handle) {
|
||||
Core *core = *(Core **)&handle;
|
||||
int32_t size; // Number of bytes to allocate
|
||||
|
||||
// Allocate memory for the breakpoint
|
||||
core->numBreakpoints++;
|
||||
size = core->numBreakpoints * sizeof (Breakpoint);
|
||||
core->breakpoints = core->breakpoints == NULL ?
|
||||
malloc(size) : realloc(core->breakpoints, size);
|
||||
|
||||
// Initialize the breakpoint
|
||||
memset(&core->breakpoints[core->numBreakpoints-1], 0, sizeof (Breakpoint));
|
||||
}
|
||||
|
||||
// Remove a breakpoint from the collection
|
||||
JNIEXPORT void JNICALL Java_vue_NativeVue_remove
|
||||
(JNIEnv *env, jobject vue, jlong handle, jint index) {
|
||||
Core *core = *(Core **)&handle;
|
||||
Breakpoint *brk = &core->breakpoints[index];
|
||||
|
||||
// Delete the breakpoint
|
||||
if (brk->ranges != NULL) free(brk->ranges);
|
||||
if (brk->tokens != NULL) free(brk->tokens);
|
||||
|
||||
// Move all subsequent breakpoints forward
|
||||
if (index != core->numBreakpoints - 1)
|
||||
memmove(brk, &brk[1],
|
||||
(core->numBreakpoints - index) * sizeof (Breakpoint));
|
||||
core->numBreakpoints--;
|
||||
}
|
||||
|
||||
// A breakpoint's address ranges have changed
|
||||
JNIEXPORT void JNICALL Java_vue_NativeVue_updateRanges
|
||||
(JNIEnv *env, jobject vue, jlong handle, jint index, jintArray ranges) {
|
||||
Core *core = *(Core **)&handle;
|
||||
Breakpoint *brk = &core->breakpoints[index];
|
||||
jint *elems; // Array elements
|
||||
int32_t size; // Number of bytes to allocate
|
||||
|
||||
// Determine the number of address ranges
|
||||
brk->numRanges = (*env)->GetArrayLength(env, ranges) / 2;
|
||||
if (brk->numRanges == 0) {
|
||||
if (brk->ranges != NULL)
|
||||
free(brk->ranges);
|
||||
brk->ranges = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate memory for the address ranges
|
||||
size = brk->numRanges * sizeof (Range);
|
||||
brk->ranges = brk->ranges == NULL ?
|
||||
malloc(size) : realloc(brk->ranges, size);
|
||||
|
||||
// Initialize address ranges
|
||||
elems = (*env)->GetIntArrayElements(env, ranges, NULL);
|
||||
memcpy(brk->ranges, elems, size);
|
||||
(*env)->ReleaseIntArrayElements(env, ranges, elems, JNI_ABORT);
|
||||
}
|
||||
|
||||
// A breakpoint's enabled/hook state has changed
|
||||
JNIEXPORT void JNICALL Java_vue_NativeVue_updateState
|
||||
(JNIEnv *env, jobject vue, jlong handle, jint index, jboolean enabled,
|
||||
jint hooks) {
|
||||
Core *core = *(Core **)&handle;
|
||||
Breakpoint *brk = &core->breakpoints[index];
|
||||
brk->enabled = enabled;
|
||||
brk->hooks = hooks;
|
||||
}
|
||||
|
||||
// A breakpoint's condition tokens have changed
|
||||
JNIEXPORT void JNICALL Java_vue_NativeVue_updateTokens
|
||||
(JNIEnv *env, jobject vue, jlong handle, jint index, jintArray tokens) {
|
||||
Core *core = *(Core **)&handle;
|
||||
Breakpoint *brk = &core->breakpoints[index];
|
||||
jint *elems; // Array elements
|
||||
int32_t size; // Number of bytes to allocate
|
||||
|
||||
// Determine the number of condition tokens
|
||||
brk->numTokens = (*env)->GetArrayLength(env, tokens) / 2;
|
||||
if (brk->numTokens == 0) {
|
||||
if (brk->tokens != NULL)
|
||||
free(brk->tokens);
|
||||
brk->tokens = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate memory for the condition tokens
|
||||
size = brk->numTokens * sizeof (Token);
|
||||
brk->tokens = brk->tokens == NULL ?
|
||||
malloc(size) : realloc(brk->tokens, size);
|
||||
|
||||
// Initialize condition tokens
|
||||
elems = (*env)->GetIntArrayElements(env, tokens, NULL);
|
||||
memcpy(brk->tokens, elems, size);
|
||||
(*env)->ReleaseIntArrayElements(env, tokens, elems, JNI_ABORT);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,12 @@ class NativeVue extends Vue {
|
|||
private native int getBreakCode(long handle);
|
||||
public int getBreakCode() { return getBreakCode(handle); }
|
||||
|
||||
// Retrieve the most recent exception code
|
||||
private native int getException(long handle);
|
||||
public int getException() {
|
||||
return getException(handle);
|
||||
}
|
||||
|
||||
// Retrieve a register value
|
||||
private native int getRegister(long handle, int index, boolean system);
|
||||
public int getRegister(int index, boolean system)
|
||||
|
@ -119,20 +125,16 @@ class NativeVue extends Vue {
|
|||
// A breakpoint's address ranges have changed
|
||||
void updateRanges(Breakpoint brk) {
|
||||
super.updateRanges(brk);
|
||||
updateRanges(handle, breakpoints.indexOf(brk), brk.flattenRanges());
|
||||
}
|
||||
|
||||
// A breakpoint's enabled/hook state has changed
|
||||
void updateState(Breakpoint brk) {
|
||||
super.updateState(brk);
|
||||
updateState(handle, breakpoints.indexOf(brk),
|
||||
brk.isEnabled(), brk.getHooks());
|
||||
}
|
||||
|
||||
// A breakpoint's condition tokens have changed
|
||||
void updateTokens(Breakpoint brk) {
|
||||
super.updateTokens(brk);
|
||||
updateTokens(handle, breakpoints.indexOf(brk), brk.flattenTokens());
|
||||
}
|
||||
|
||||
|
||||
|
@ -147,14 +149,4 @@ class NativeVue extends Vue {
|
|||
// Remove a breakpoint from the collection
|
||||
private native void remove(long handle, int index);
|
||||
|
||||
// A breakpoint's address ranges have changed
|
||||
private native void updateRanges(long handle, int index, int[] ranges);
|
||||
|
||||
// A breakpoint's enabled/hook state has changed
|
||||
private native void updateState(long handle, int index, boolean enabled,
|
||||
int hooks);
|
||||
|
||||
// A breakpoint's condition tokens have changed
|
||||
private native void updateTokens(long handle, int index, int[] tokens);
|
||||
|
||||
}
|
||||
|
|
|
@ -180,6 +180,13 @@ public abstract class Vue {
|
|||
return brk;
|
||||
}
|
||||
|
||||
// Evaluate an expression
|
||||
public Object evaluate(String expression) {
|
||||
var brk = new Breakpoint(this);
|
||||
brk.setCondition(expression);
|
||||
return brk.evaluate(null, null, null);
|
||||
}
|
||||
|
||||
// Produce an array of the current breakpoint collection
|
||||
public Breakpoint[] listBreakpoints() {
|
||||
return breakpoints.toArray(new Breakpoint[breakpoints.size()]);
|
||||
|
@ -205,8 +212,8 @@ public abstract class Vue {
|
|||
// Process the simulation
|
||||
public abstract int emulate(int maxCycles);
|
||||
|
||||
// Retrieve the application break code
|
||||
public abstract int getBreakCode();
|
||||
// Retrieve the most recent exception code
|
||||
public abstract int getException();
|
||||
|
||||
// Retrieve a register value
|
||||
public abstract int getRegister(int index, boolean system);
|
||||
|
@ -246,9 +253,6 @@ public abstract class Vue {
|
|||
// Package Methods //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Evaluate the condition in a breakpoint
|
||||
abstract boolean evaluate(Breakpoint brk);
|
||||
|
||||
// A breakpoint's address ranges have changed
|
||||
void updateRanges(Breakpoint brk) { }
|
||||
|
||||
|
|
Loading…
Reference in New Issue