From 1386d36b0d1970d84b9e97da012637b541a92d82 Mon Sep 17 00:00:00 2001 From: Guy Perfect Date: Fri, 14 Aug 2020 17:53:15 -0500 Subject: [PATCH] Implementing breakpoint condition evaluator in C, refactoring Java version --- makefile | 2 +- src/desktop/vue/Breakpoint.c | 636 +++++++++++++++++++++++++ src/desktop/vue/Breakpoint.java | 811 ++++++++++++++++++-------------- src/desktop/vue/NativeVUE.c | 56 ++- src/desktop/vue/NativeVUE.java | 4 +- 5 files changed, 1139 insertions(+), 370 deletions(-) create mode 100644 src/desktop/vue/Breakpoint.c diff --git a/makefile b/makefile index 3eb7dab..47973e6 100644 --- a/makefile +++ b/makefile @@ -10,7 +10,7 @@ default: @echo @echo "Planet Virtual Boy Emulator" @echo " https://www.planetvb.com/" - @echo " August 11, 2020" + @echo " August 14, 2020" @echo @echo "Intended build environment: Debian i386 or amd64" @echo " gcc-multilib" diff --git a/src/desktop/vue/Breakpoint.c b/src/desktop/vue/Breakpoint.c new file mode 100644 index 0000000..4c57500 --- /dev/null +++ b/src/desktop/vue/Breakpoint.c @@ -0,0 +1,636 @@ +// 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->numCondition == 0) + return brk->enabled; + + // Process tokens + int size = 0; + for (int x = 0; x < brk->numCondition; x++) { + TOKEN *tok = &brk->condition[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 diff --git a/src/desktop/vue/Breakpoint.java b/src/desktop/vue/Breakpoint.java index 152aabb..190cb32 100644 --- a/src/desktop/vue/Breakpoint.java +++ b/src/desktop/vue/Breakpoint.java @@ -33,55 +33,55 @@ public class Breakpoint { public static final int UNEXPECTED = 7; // Token types - private static final int BINARY = 1; - private static final int CLOSE = 2; - private static final int FLOAT = 3; - private static final int OPEN = 4; - private static final int SYMBOL = 5; - private static final int UNARY = 6; + private static final int BINARY = 4; + private static final int CLOSE = 6; + private static final int FLOAT = 1; + private static final int UNARY = 3; + private static final int OPEN = 5; + private static final int SYMBOL = 2; private static final int WORD = 0; // Expected token modes adjacent to any given token // 0 = Value, unary or open expected, 1 = Binary or close expected - private static final int MODES_AFTER = 0b0101101; - private static final int MODES_BEFORE = 0b0000110; + private static final int MODES_AFTER = 0b1000111; + private static final int MODES_BEFORE = 0b1010000; // Operator IDs - private static final int ADD = 0; - private static final int BITWISE_AND = 1; - private static final int BITWISE_NOT = 2; - private static final int BITWISE_OR = 3; - private static final int BITWISE_XOR = 4; - private static final int CEIL = 5; - private static final int DIVIDE = 6; - private static final int EQUAL = 7; - private static final int FLOATOP = 8; - private static final int FLOOR = 9; - private static final int GREATER_EQUAL_SIGNED = 10; - private static final int GREATER_EQUAL_UNSIGNED = 11; - private static final int GREATER_SIGNED = 12; - private static final int GREATER_UNSIGNED = 13; - private static final int GROUP = 14; - private static final int LESS_EQUAL_SIGNED = 15; - private static final int LESS_EQUAL_UNSIGNED = 16; - private static final int LESS_SIGNED = 17; - private static final int LESS_UNSIGNED = 18; - private static final int LOGICAL_AND = 19; - private static final int LOGICAL_NOT = 20; - private static final int LOGICAL_OR = 21; - private static final int LOGICAL_XOR = 22; - private static final int MULTIPLY = 23; - private static final int NEGATE = 24; - private static final int NOT_EQUAL = 25; - private static final int READ_WORD = 26; - private static final int REMAINDER = 27; - private static final int ROUND = 28; - private static final int SHIFT_LEFT = 29; - private static final int SHIFT_RIGHT = 30; - private static final int SHIFT_RIGHT_ARITHMETIC = 31; - private static final int SUBTRACT = 32; - private static final int TRUNC = 33; - private static final int WORDOP = 34; + private static final int ADD = 2; + private static final int BITWISE_AND = 3; + private static final int BITWISE_NOT = 4; + private static final int BITWISE_OR = 5; + private static final int BITWISE_XOR = 6; + private static final int CEIL = 7; + private static final int DIVIDE = 8; + private static final int EQUAL = 9; + private static final int FLOOR = 10; + //private static final int FLOAT = 1; // Same as type + private static final int GREATER_EQUAL_SIGNED = 11; + private static final int GREATER_EQUAL_UNSIGNED = 12; + private static final int GREATER_SIGNED = 13; + private static final int GREATER_UNSIGNED = 14; + private static final int GROUP = 15; + private static final int LESS_EQUAL_SIGNED = 16; + private static final int LESS_EQUAL_UNSIGNED = 17; + private static final int LESS_SIGNED = 18; + private static final int LESS_UNSIGNED = 19; + private static final int LOGICAL_AND = 20; + private static final int LOGICAL_NOT = 21; + private static final int LOGICAL_OR = 22; + private static final int LOGICAL_XOR = 23; + private static final int MULTIPLY = 24; + private static final int NEGATE = 25; + private static final int NOT_EQUAL = 26; + private static final int READ_WORD = 27; + private static final int REMAINDER = 28; + private static final int ROUND = 29; + private static final int SHIFT_LEFT = 30; + private static final int SHIFT_RIGHT = 31; + private static final int SHIFT_RIGHT_ARITHMETIC = 32; + private static final int SUBTRACT = 33; + private static final int TRUNC = 34; + //private static final int WORD = 0; // Same as type private static final int XFLOAT = 35; private static final int XWORD = 36; @@ -122,11 +122,11 @@ public class Breakpoint { OPDEFS.put("!" , new OpDef( 1, UNARY , LOGICAL_NOT )); OPDEFS.put("-" , new OpDef( 1, UNARY , NEGATE )); OPDEFS.put("ceil" , new OpDef( 1, UNARY , CEIL )); - OPDEFS.put("float" , new OpDef( 1, UNARY , FLOATOP )); + OPDEFS.put("float" , new OpDef( 1, UNARY , FLOAT )); OPDEFS.put("floor" , new OpDef( 1, UNARY , FLOOR )); OPDEFS.put("round" , new OpDef( 1, UNARY , ROUND )); OPDEFS.put("trunc" , new OpDef( 1, UNARY , TRUNC )); - OPDEFS.put("word" , new OpDef( 1, UNARY , WORDOP )); + OPDEFS.put("word" , new OpDef( 1, UNARY , WORD )); OPDEFS.put("xfloat", new OpDef( 1, UNARY , XFLOAT )); OPDEFS.put("xword" , new OpDef( 1, UNARY , XWORD )); OPDEFS.put("/" , new OpDef( 2, BINARY, DIVIDE )); @@ -233,16 +233,20 @@ public class Breakpoint { SYMDEFS.put("lp" , 131); // System register symbol definitions - SYMDEFS.put("adtre", 225); SYMDEFS.put("fepsw", 203); - SYMDEFS.put("chcw" , 224); SYMDEFS.put("pc" , 199); - SYMDEFS.put("ecr" , 204); SYMDEFS.put("psw" , 205); - SYMDEFS.put("eipc" , 200); SYMDEFS.put("sr29" , 229); - SYMDEFS.put("eipsw", 201); SYMDEFS.put("sr31" , 231); - SYMDEFS.put("fepc" , 202); + SYMDEFS.put("adtre", 200 + VUE.ADTRE); + SYMDEFS.put("chcw" , 200 + VUE.CHCW ); + SYMDEFS.put("ecr" , 200 + VUE.ECR ); + SYMDEFS.put("eipc" , 200 + VUE.EIPC ); + SYMDEFS.put("eipsw", 200 + VUE.EIPSW); + SYMDEFS.put("fepc" , 200 + VUE.FEPC ); + SYMDEFS.put("fepsw", 200 + VUE.FEPSW); + SYMDEFS.put("pc" , VUE.PC ); + SYMDEFS.put("psw" , 200 + VUE.PSW ); + SYMDEFS.put("sr29" , 229 ); + SYMDEFS.put("sr31" , 231 ); LITDEFS.put("pir" , 0x00005346); LITDEFS.put("tkcw" , 0x000000E0); LITDEFS.put("sr30" , 0x00000004); - }; @@ -473,6 +477,30 @@ public class Breakpoint { // Package Methods // /////////////////////////////////////////////////////////////////////////// + // Evaluate the condition for an emulation context + boolean evaluate(JavaVUE vue, int[] stack) { + + // The condition is empty + if (tokens.length == 0) + return isEnabled && errCode == NONE; + + // Process tokens + int size = 0; + for (var tok : tokens) { + switch (tok.type) { + case BINARY: size = + evalBinary( tok.id, stack, size); continue; + case SYMBOL: size = + evalSymbol(vue, tok.id, stack, size); continue; + case UNARY : + evalUnary (vue, tok.id, stack, size); continue; + } + stack[size++] = tok.type; + stack[size++] = tok.value; + } + return (stack[1] & (stack[0] == WORD ? 0xFFFFFFFF : 0x7FFFFFFF)) != 0; + } + // Determine the required stack size to evaluate the expression int depth() { @@ -849,253 +877,134 @@ public class Breakpoint { // Evaluation Methods // /////////////////////////////////////////////////////////////////////////// - // Evaluate the condition for an emulation context - boolean evaluate(JavaVUE vue, int[] stack) { + // Resolve a float from word bits + private static float asFloat(int value) { + return Float.intBitsToFloat(value); + } - // The condition is empty - if (tokens.length == 0) - return isEnabled && errCode == NONE; + // Resolve the word bits of a float + private static int asWord(float value) { + return Float.floatToRawIntBits(fixFloat(value)); + } - // Process tokens - int size = 0; - for (var tok : tokens) { - switch (tok.type) { - //case BINARY: size = - // evalBinary(vue, tok.id, stack, size); continue; - case SYMBOL: size = - evalSymbol(vue, tok.id, stack, size); continue; - case UNARY : size = - evalUnary (vue, tok.id, stack, size); continue; - } - stack[size++] = tok.type; - stack[size++] = tok.value; - } - return (stack[1] & (stack[0] == FLOAT ? 0x7FFFFFFF : 0xFFFFFFFF)) != 0; + // Convert an unsigned word to a float + private static float ufloat(int value) { + return (float) (value & 0xFFFFFFFFL); + } + + // Convert a float to a word + private static int toWord(float value) { + value = (float) Math.round(value); + return value >= 0x7FFFFFFF || value < 0x80000000 ? 0 : (int) value; } // Evaluate a binary operator - private int evalBinary(JavaVUE vue, int id, int[] stack, int size) { - int lw = stack[size - 3]; - float lf = Float.intBitsToFloat(lw); - int ret = 0; - int rw = stack[size - 1]; - float rf = Float.intBitsToFloat(rw); - int type = stack[size - 2] | stack[size - 4]; + private static int evalBinary(int id, int[] stack, int size) { + int rv = stack[size - 1]; + int rt = stack[size - 2]; + boolean rw = rt == WORD; + int lv = stack[size - 3]; + int lt = stack[size - 4]; + boolean lw = lt == WORD; + int type = rw && lw ? WORD : FLOAT; + int value = 0; switch (id) { + + // Arithmetic case ADD : - ret = evalAdd (type, lw, lf, rw, rf); break; - case BITWISE_AND : - ret = evalBitwiseAnd (type, lw, lf, rw, rf); break; - case BITWISE_XOR : - ret = evalBitwiseXOr (type, lw, lf, rw, rf); break; - case BITWISE_OR : - ret = evalBitwiseOr (type, lw, lf, rw, rf); break; + value = evalAdd (lw, lv, rw, rv); break; case DIVIDE : - ret = evalDivide (type, lw, lf, rw, rf); break; - case EQUAL : - ret = evalEqual (type, lw, lf, rw, rf); - type = WORD; break; - case GREATER_EQUAL_SIGNED : - ret = evalGreaterEqualSigned (type, lw, lf, rw, rf); - type = WORD; break; - case GREATER_EQUAL_UNSIGNED: - ret = evalGreaterEqualUnsigned(type, lw, lf, rw, rf); - type = WORD; break; - case GREATER_SIGNED : - ret = evalGreaterSigned (type, lw, lf, rw, rf); - type = WORD; break; - case GREATER_UNSIGNED : - ret = evalGreaterUnsigned (type, lw, lf, rw, rf); - type = WORD; break; - case LESS_EQUAL_SIGNED : - ret = evalLessEqualSigned (type, lw, lf, rw, rf); - type = WORD; break; - case LESS_EQUAL_UNSIGNED : - ret = evalLessEqualUnsigned (type, lw, lf, rw, rf); - type = WORD; break; - case LESS_SIGNED : - ret = evalLessSigned (type, lw, lf, rw, rf); - type = WORD; break; - case LESS_UNSIGNED : - ret = evalLessUnsigned (type, lw, lf, rw, rf); - type = WORD; break; - case LOGICAL_AND : - ret = evalLogicalAnd (type, lw, lf, rw, rf); - type = WORD; break; - case LOGICAL_OR : - ret = evalLogicalOr (type, lw, lf, rw, rf); - type = WORD; break; - case LOGICAL_XOR : - ret = evalLogicalXOr (type, lw, lf, rw, rf); - type = WORD; break; + value = evalDivide (lw, lv, rw, rv); break; case MULTIPLY : - ret = evalMultiply (type, lw, lf, rw, rf); break; - case NOT_EQUAL : - ret = evalNotEqual (type, lw, lf, rw, rf); - type = WORD; break; + value = evalMultiply (lw, lv, rw, rv); break; case REMAINDER : - ret = evalRemainder (type, lw, lf, rw, rf); break; - case SHIFT_LEFT : - ret = evalShiftLeft (type, lw, lf, rw, rf); break; - case SHIFT_RIGHT : - ret = evalShiftRight (type, lw, lf, rw, rf); break; - case SHIFT_RIGHT_ARITHMETIC: - ret = evalShiftRightArithmetic(type, lw, lf, rw, rf); break; + value = evalRemainder (lw, lv, rw, rv); break; case SUBTRACT : - ret = evalSubtract (type, lw, lf, rw, rf); break; - } + 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] = ret; + stack[size - 3] = value; return size - 2; } - // Evaluate + - private int evalAdd(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? lw + rw : Float.floatToRawIntBits(lf + rf); - } - - // Evaluate & - private int evalBitwiseAnd(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? lw & rw : Float.floatToRawIntBits( - fixFloat(Float.intBitsToFloat(lw & rw))); - } - - // Evaluate | - private int evalBitwiseOr(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? lw | rw : Float.floatToRawIntBits( - fixFloat(Float.intBitsToFloat(lw | rw))); - } - - // Evaluate ^ - private int evalBitwiseXOr(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? lw ^ rw : Float.floatToRawIntBits( - fixFloat(Float.intBitsToFloat(lw ^ rw))); - } - - // Evaluate / - private int evalDivide(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? rw == 0 ? 0 : lw / rw : rf == 0 ? 0 : - Float.floatToRawIntBits(lf / rf); - } - - // Evaluate == - private int evalEqual(int type, int lw, float lf, int rw, float rf) { - return (type == WORD ? lw == rw : lf == rf) ? 1 : 0; - } - - // Evaluate >= - private int evalGreaterEqualSigned(int type, - int lw, float lf, int rw, float rf) { - return (type == WORD ? lw >= rw : (lf >= rf)) ? 1 : 0; - } - - // Evaluate >=_ - private int evalGreaterEqualUnsigned(int type, - int lw, float lf, int rw, float rf) { - return (type == WORD ? Integer.compareUnsigned(lw, rw) >= 0 : - (lf >= rf)) ? 1 : 0; - } - - // Evaluate > - private int evalGreaterSigned(int type,int lw,float lf,int rw,float rf) { - return (type == WORD ? lw > rw : (lf > rf)) ? 1 : 0; - } - - // Evaluate >_ - private int evalGreaterUnsigned(int type,int lw,float lf,int rw,float rf) { - return (type == WORD ? Integer.compareUnsigned(lw, rw) > 0 : - (lf > rf)) ? 1 : 0; - } - - // Evaluate <= - private int evalLessEqualSigned(int type, - int lw, float lf, int rw, float rf) { - return (type == WORD ? lw <= rw : (lf <= rf)) ? 1 : 0; - } - - // Evaluate <=_ - private int evalLessEqualUnsigned(int type, - int lw, float lf, int rw, float rf) { - return (type == WORD ? Integer.compareUnsigned(lw, rw) <= 0 : - (lf <= rf)) ? 1 : 0; - } - - // Evaluate < - private int evalLessSigned(int type, int lw, float lf, int rw, float rf) { - return (type == WORD ? lw < rw : (lf < rf)) ? 1 : 0; - } - - // Evaluate <_ - private int evalLessUnsigned(int type, int lw, float lf, int rw, float rf){ - return (type == WORD ? Integer.compareUnsigned(lw, rw) < 0 : - (lf < rf)) ? 1 : 0; - } - - // Evaluate && - private int evalLogicalAnd(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? lw != 0 ? rw : 0 : - Float.floatToRawIntBits(lf != 0 ? rf : 0); - } - - // Evaluate || - private int evalLogicalOr(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? lw != 0 ? lw : rw : - Float.floatToRawIntBits(lf != 0 ? lf : rf); - } - - // Evaluate ^^ - private int evalLogicalXOr(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? lw!=0 ? rw!=0 ? 0 : lw : rw!=0 ? rw : 0 : - Float.floatToRawIntBits(lf!=0 ? rf!=0 ? 0 : lf : rf!=0 ? rf : 0); - } - - // Evaluate * - private int evalMultiply(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? lw * rw : Float.floatToRawIntBits(lf * rf); - } - - // Evaluate != - private int evalNotEqual(int type, int lw, float lf, int rw, float rf) { - return (type == WORD ? lw != rw : lf != rf) ? 1 : 0; - } - - // Evaluate % - private int evalRemainder(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? rw == 0 ? 0 : lw % rw : rf == 0 ? 0 : - Float.floatToRawIntBits(lf % rf); - } - - // Evaluate << - private int evalShiftLeft(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? lw << (rw & 31) : Float.floatToRawIntBits( - fixFloat(Float.intBitsToFloat(lw << ((int) rf & 31)))); - } - - // Evaluate >>> - private int evalShiftRight(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? lw >>> (rw & 31) : Float.floatToRawIntBits( - fixFloat(Float.intBitsToFloat(lw >>> ((int) rf & 31)))); - } - - // Evaluate >> - private int evalShiftRightArithmetic(int type, - int lw, float lf, int rw, float rf) { - return type == WORD ? lw >> (rw & 31) : Float.floatToRawIntBits( - fixFloat(Float.intBitsToFloat(lw >> ((int) rf & 31)))); - } - - // Evaluate - - private int evalSubtract(int type, int lw, float lf, int rw, float rf) { - return type == WORD ? lw - rw : Float.floatToRawIntBits(lf - rf); - } - // Evaluate a functional symbol - private int evalSymbol(JavaVUE vue, int id, int[] stack, int size) { + private static int evalSymbol(JavaVUE vue, int id, int[] stack, int size) { int ret = 0; - if (vue.cpu.stage == CPU.EXCEPTION) switch (id) { - case CODE: ret = vue.cpu.exception.code; break; - } - else switch (id) { + if (id == VUE.PC) + ret = vue.cpu.pc; + else if (id >= 200) + ret = vue.cpu.getSystemRegister(id - 200); + else if (id >= 100) + ret = vue.cpu.program[id - 100]; + else if (vue.cpu.stage == CPU.EXCEPTION && id == CODE) + ret = vue.cpu.exception.code; + else if (vue.cpu.stage == CPU.EXECUTE) switch (id) { case ADDRESS : ret = evalAddress (vue); break; case COND : ret = evalCond (vue); break; case DISP : ret = evalDisp (vue); break; @@ -1116,8 +1025,235 @@ public class Breakpoint { return size; } + // Evaluate a unary operator + private static void evalUnary(JavaVUE vue, int id, int[] stack, int size) { + int type = stack[size - 2]; + int value = stack[size - 1]; + boolean 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; + } + + + + /////////////////////////////////////////////////////////////////////////// + // Binary Methods // + /////////////////////////////////////////////////////////////////////////// + + // Evaluate + + private static int evalAdd( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return leftWord && rightWord ? leftValue + rightValue : asWord( + (leftWord ? (float) leftValue : asFloat(leftValue )) + + (rightWord ? (float) rightValue : asFloat(rightValue)) + ); + } + + // Evaluate & + private static int evalBitwiseAnd( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord ? leftValue : toWord(asFloat(leftValue ))) & + (rightWord ? rightValue : toWord(asFloat(rightValue))); + } + + // Evaluate | + private static int evalBitwiseOr( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord ? leftValue : toWord(asFloat(leftValue ))) | + (rightWord ? rightValue : toWord(asFloat(rightValue))); + } + + // Evaluate ^ + private static int evalBitwiseXOr( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord ? leftValue : toWord(asFloat(leftValue ))) ^ + (rightWord ? rightValue : toWord(asFloat(rightValue))); + } + + // Evaluate / + private static int evalDivide( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (rightWord ? rightValue : rightValue & 0x7FFFFFFF) == 0 ? 0 : + leftWord && rightWord ? leftValue / rightValue : asWord( + (leftWord ? (float) leftValue : asFloat(leftValue )) / + (rightWord ? (float) rightValue : asFloat(rightValue)) + ); + } + + // Evaluate == + private static int evalEqual( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord && rightWord ? leftValue == rightValue : ( + (leftWord ? (float) leftValue : asFloat(leftValue )) == + (rightWord ? (float) rightValue : asFloat(rightValue)) + )) ? 1 : 0; + } + + // Evaluate >= + private static int evalGreaterEqualSigned( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord && rightWord ? leftValue >= rightValue : ( + (leftWord ? (float) leftValue : asFloat(leftValue )) >= + (rightWord ? (float) rightValue : asFloat(rightValue)) + )) ? 1 : 0; + } + + // Evaluate >=_ + private static int evalGreaterEqualUnsigned( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord && rightWord ? + Integer.compareUnsigned(leftValue, rightValue) >= 0 : ( + (leftWord ? ufloat(leftValue ) : asFloat(leftValue )) >= + (rightWord ? ufloat(rightValue) : asFloat(rightValue)) + )) ? 1 : 0; + } + + // Evaluate > + private static int evalGreaterSigned( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord && rightWord ? leftValue > rightValue : ( + (leftWord ? (float) leftValue : asFloat(leftValue )) > + (rightWord ? (float) rightValue : asFloat(rightValue)) + )) ? 1 : 0; + } + + // Evaluate >_ + private static int evalGreaterUnsigned( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord && rightWord ? + Integer.compareUnsigned(leftValue, rightValue) > 0 : ( + (leftWord ? ufloat(leftValue ) : asFloat(leftValue )) > + (rightWord ? ufloat(rightValue) : asFloat(rightValue)) + )) ? 1 : 0; + } + + // Evaluate <= + private static int evalLessEqualSigned( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord && rightWord ? leftValue <= rightValue : ( + (leftWord ? (float) leftValue : asFloat(leftValue )) <= + (rightWord ? (float) rightValue : asFloat(rightValue)) + )) ? 1 : 0; + } + + // Evaluate <=_ + private static int evalLessEqualUnsigned( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord && rightWord ? + Integer.compareUnsigned(leftValue, rightValue) <= 0 : ( + (leftWord ? ufloat(leftValue ) : asFloat(leftValue )) <= + (rightWord ? ufloat(rightValue) : asFloat(rightValue)) + )) ? 1 : 0; + } + + // Evaluate < + private static int evalLessSigned( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord && rightWord ? leftValue < rightValue : ( + (leftWord ? (float) leftValue : asFloat(leftValue )) < + (rightWord ? (float) rightValue : asFloat(rightValue)) + )) ? 1 : 0; + } + + // Evaluate <_ + private static int evalLessUnsigned( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord && rightWord ? + Integer.compareUnsigned(leftValue, rightValue) < 0 : ( + (leftWord ? ufloat(leftValue ) : asFloat(leftValue )) < + (rightWord ? ufloat(rightValue) : asFloat(rightValue)) + )) ? 1 : 0; + } + + // Evaluate * + private static int evalMultiply( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return leftWord && rightWord ? leftValue * rightValue : asWord( + (leftWord ? (float) leftValue : asFloat(leftValue )) * + (rightWord ? (float) rightValue : asFloat(rightValue)) + ); + } + + // Evaluate != + private static int evalNotEqual( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (leftWord && rightWord ? leftValue != rightValue : ( + (leftWord ? (float) leftValue : asFloat(leftValue )) != + (rightWord ? (float) rightValue : asFloat(rightValue)) + )) ? 1 : 0; + } + + // Evaluate % + private static int evalRemainder( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return (rightWord ? rightValue : rightValue & 0x7FFFFFFF) == 0 ? 0 : + leftWord && rightWord ? leftValue % rightValue : asWord( + (leftWord ? (float) leftValue : asFloat(leftValue )) % + (rightWord ? (float) rightValue : asFloat(rightValue)) + ); + } + + // Evaluate << + private static int evalShiftLeft( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + leftValue = leftWord ? leftValue : toWord(asFloat(leftValue )); + leftValue = (rightWord ? rightValue : toWord(asFloat(rightValue)))&31; + return leftValue << rightValue; + } + + // Evaluate >>> + private static int evalShiftRight( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + leftValue = leftWord ? leftValue : toWord(asFloat(leftValue )); + leftValue = (rightWord ? rightValue : toWord(asFloat(rightValue)))&31; + return leftValue >>> rightValue; + } + + // Evaluate >> + private static int evalShiftRightArithmetic( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + leftValue = leftWord ? leftValue : toWord(asFloat(leftValue )); + leftValue = (rightWord ? rightValue : toWord(asFloat(rightValue)))&31; + return leftValue >> rightValue; + } + + // Evaluate - + private static int evalSubtract( + boolean leftWord, int leftValue, boolean rightWord, int rightValue) { + return leftWord && rightWord ? leftValue - rightValue : asWord( + (leftWord ? (float) leftValue : asFloat(leftValue )) - + (rightWord ? (float) rightValue : asFloat(rightValue)) + ); + } + + + + /////////////////////////////////////////////////////////////////////////// + // Symbol Methods // + /////////////////////////////////////////////////////////////////////////// + // Evaluate address - private int evalAddress(JavaVUE vue) { + private static int evalAddress(JavaVUE vue) { if (vue.cpu.inst.format == 6) return vue.cpu.program[vue.cpu.inst.reg1] + vue.cpu.inst.disp; switch (vue.cpu.inst.id) { @@ -1132,7 +1268,7 @@ public class Breakpoint { } // Evaluate cond - private int evalCond(JavaVUE vue) { + private static int evalCond(JavaVUE vue) { switch (vue.cpu.inst.id) { case VUE.BCOND: return vue.cpu.inst.cond; case VUE.SETF : return vue.cpu.inst.imm; @@ -1141,7 +1277,7 @@ public class Breakpoint { } // Evaluate disp - private int evalDisp(JavaVUE vue) { + private static int evalDisp(JavaVUE vue) { switch (vue.cpu.inst.format) { case 3: case 4: case 6: return vue.cpu.inst.disp; } @@ -1149,7 +1285,7 @@ public class Breakpoint { } // Evaluate imm - private int evalImm(JavaVUE vue) { + private static int evalImm(JavaVUE vue) { switch (vue.cpu.inst.format) { case 2: case 5: return vue.cpu.inst.imm; } @@ -1157,7 +1293,7 @@ public class Breakpoint { } // Evaluate reg1 - private int evalReg1(JavaVUE vue) { + private static int evalReg1(JavaVUE vue) { switch (vue.cpu.inst.format) { case 1: case 5: case 6: case 7: return vue.cpu.inst.reg1; } @@ -1165,7 +1301,7 @@ public class Breakpoint { } // Evaluate reg2 - private int evalReg2(JavaVUE vue) { + private static int evalReg2(JavaVUE vue) { switch (vue.cpu.inst.format) { case 1: case 2: case 5: case 6: case 7: return vue.cpu.inst.reg2; } @@ -1173,7 +1309,7 @@ public class Breakpoint { } // Evaluate regid - private int evalRegId(JavaVUE vue) { + private static int evalRegId(JavaVUE vue) { switch (vue.cpu.inst.id) { case VUE.LDSR: case VUE.STSR: return vue.cpu.inst.imm; } @@ -1181,7 +1317,7 @@ public class Breakpoint { } // Evaluate subopcode - private int evalSubopcode(JavaVUE vue) { + private static int evalSubopcode(JavaVUE vue) { switch (vue.cpu.inst.opcode) { case 0x1F: return vue.cpu.inst.imm; case 0x3E: return vue.cpu.inst.subopcode; @@ -1190,110 +1326,75 @@ public class Breakpoint { } // Evaluate value - private int evalValue(JavaVUE vue) { + private static int evalValue(JavaVUE vue) { return vue.cpu.inst.format == 6 ? vue.cpu.access.value : 0; } // Evaluate vector - private int evalVector(JavaVUE vue) { + private static int evalVector(JavaVUE vue) { return vue.cpu.inst.id == VUE.TRAP ? vue.cpu.inst.imm : 0; } - // Evaluate a unary operator - private int evalUnary(JavaVUE vue, int id, int[] stack, int size) { - int ret = 0; - int type = stack[size - 2]; - int w = stack[size - 1]; - float f = Float.intBitsToFloat(w); - switch (id) { - case BITWISE_NOT: ret = evalBitwiseNot(type, w, f); break; - case LOGICAL_NOT: ret = evalLogicalNot(type, w, f); - type = WORD ; break; - case NEGATE : ret = evalNegate (type, w, f); break; - case CEIL : ret = evalCeil (type, w, f); break; - case FLOATOP : ret = evalFloat (type, w, f); - type = FLOAT; break; - case FLOOR : ret = evalFloor (type, w, f); break; - case READ_WORD : ret = evalReadWord (type, w, f, vue); - type = WORD ; break; - case ROUND : ret = evalRound (type, w, f); break; - case TRUNC : ret = evalTrunc (type, w, f); break; - case WORDOP : ret = evalWord (type, w, f); - type = WORD ; break; - case XFLOAT : ret = evalXFloat (type, w, f); - type = FLOAT; break; - case XWORD : ret = w; type = WORD; break; - } - stack[size - 2] = type; - stack[size - 1] = ret; - return size; - } + + + /////////////////////////////////////////////////////////////////////////// + // Unary Methods // + /////////////////////////////////////////////////////////////////////////// // Evaluate ~ - private int evalBitwiseNot(int type, int w, float f) { - return type == WORD ? ~w : - Float.floatToRawIntBits(fixFloat(Float.intBitsToFloat(~w))); + private static int evalBitwiseNot(boolean isWord, int value) { + return isWord ? ~value : ~toWord(asFloat(value)); } // Evaluate ! - private int evalLogicalNot(int type, int w, float f) { - return (type == WORD ? w == 0 : f == 0) ? 1 : 0; + private static int evalLogicalNot(boolean isWord, int value) { + return (isWord ? value != 0 : (value & 0x7FFFFFFF) != 0) ? 1 : 0; } // Evaluate - - private int evalNegate(int type, int w, float f) { - return type == WORD ? -w : Float.floatToRawIntBits(-f); + private static int evalNegate(boolean isWord, int value) { + return isWord ? -value : asWord(-asFloat(value)); } // Evaluate ceil - private int evalCeil(int type, int w, float f) { - return type == WORD ? w : - Float.floatToRawIntBits((float) Math.ceil(f)); + private static int evalCeil(boolean isWord, int value) { + return isWord ? value : asWord((float) Math.ceil(asFloat(value))); } // Evaluate float - private int evalFloat(int type, int w, float f) { - return Float.floatToRawIntBits(type == FLOAT ? f : (float) w); + private static int evalFloat(boolean isWord, int value) { + return isWord ? asWord((float) value) : value; } // Evaluate floor - private int evalFloor(int type, int w, float f) { - return type == WORD ? w : - Float.floatToRawIntBits((float) Math.floor(f)); + private static int evalFloor(boolean isWord, int value) { + return isWord ? value : asWord((float) Math.floor(asFloat(value))); } // Evaluate [] - private int evalReadWord(int type, int w, float f, JavaVUE vue) { - if (type == FLOAT) { - if (f > 0x7FFFFFFF || f < 0x80000000) - return 0; - w = (int) f; - } - return vue.read(w, VUE.S32); + private static int evalReadWord(boolean isWord, int value, JavaVUE vue) { + return vue.read(isWord ? value : toWord(asFloat(value)), VUE.S32); } // Evaluate round - private int evalRound(int type, int w, float f) { - return type == WORD ? w : - Float.floatToRawIntBits((float) Math.round(f)); + private static int evalRound(boolean isWord, int value) { + return isWord ? value : asWord((float) Math.round(asFloat(value))); } // Evaluate trunc - private int evalTrunc(int type, int w, float f) { - return type == WORD ? w : Float.floatToRawIntBits((float) - (f < 0 ? Math.ceil(f) : Math.floor(f))); + private static int evalTrunc(boolean isWord, int value) { + return isWord ? value : asWord((float) (value < 0 ? + Math.ceil(asFloat(value)) : Math.ceil(asFloat(value)))); } // Evaluate word - private int evalWord(int type, int w, float f) { - return type == WORD ? w : - f > 0x7FFFFFFF || f < 0x80000000 ? 0 : (int) f; + private static int evalWord(boolean isWord, int value) { + return isWord ? value : toWord(asFloat(value)); } // Evaluate xfloat - private int evalXFloat(int type, int w, float f) { - return Float.floatToRawIntBits(type == FLOAT ? f : - fixFloat(Float.intBitsToFloat(w))); + private static int evalXFloat(boolean isWord, int value) { + return isWord ? asWord(asFloat(value)) : value; } } diff --git a/src/desktop/vue/NativeVUE.c b/src/desktop/vue/NativeVUE.c index 16a9ff5..5a477d4 100644 --- a/src/desktop/vue/NativeVUE.c +++ b/src/desktop/vue/NativeVUE.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include "vue_NativeVUE.h" @@ -21,27 +22,58 @@ static const int TYPE_SIZES[] = { 1, 1, 2, 2, 4 }; // Types // /////////////////////////////////////////////////////////////////////////////// +// Breakpoint token +typedef struct { + int32_t type; + int32_t value; +} TOKEN; + +// Precompiled breakpoint +typedef struct { + int32_t enabled; // The breakpoint is enabled + int32_t numAddresses; // Number of address ranges + int32_t numCondition; // Number of tokens in condition + int32_t *addresses; // Address ranges + TOKEN *condition; // Condition tokens in RPN order +} BREAKPOINT; + // Core context state type typedef struct { - VUE vue; /* Context into the generic C library */ + VUE vue; // Context into the generic C library + int32_t numBreakpoints; // Number of breakpoints + BREAKPOINT *breakpoints; // Application breakpoints + int32_t *stack; // Expression stack for breakpoints } CORE; +/////////////////////////////////////////////////////////////////////////////// +// Macros // +/////////////////////////////////////////////////////////////////////////////// + +/* Sign-extend a value */ +#define SIGN_EXTEND(bits, value) \ + ((value) & 1 << (bits - 1) ? (value) | (~(1 << bits) + 1) : (value)) + + + +/////////////////////////////////////////////////////////////////////////////// +// Component Includes // +/////////////////////////////////////////////////////////////////////////////// + +#define NATIVEVUE +#include "Breakpoint.c" + + + /////////////////////////////////////////////////////////////////////////////// // Internal Functions // /////////////////////////////////////////////////////////////////////////////// -// Determine the field ID of NativeVUE.pointer -static jfieldID GetPointerID(JNIEnv *env, jobject vue) { - return (*env)->GetFieldID(env, - (*env)->GetObjectClass(env, vue), "pointer", "[B"); -} - // Retrieve the handle to a NativeVUE's core context static CORE* GetCore(JNIEnv *env, jobject vue) { - jbyteArray pointer = - (*env)->GetObjectField(env, vue, GetPointerID(env, vue)); + jbyteArray pointer = (*env)->GetObjectField(env, vue, (*env)->GetFieldID( + env, (*env)->GetObjectClass(env, vue), "pointer", "[B")); jbyte *elems = (*env)->GetByteArrayElements(env, pointer, NULL); CORE *core = *(CORE **)elems; (*env)->ReleaseByteArrayElements(env, pointer, elems, 0); @@ -55,10 +87,10 @@ static CORE* GetCore(JNIEnv *env, jobject vue) { /////////////////////////////////////////////////////////////////////////////// // Native constructor -JNIEXPORT void JNICALL Java_vue_NativeVUE_construct +JNIEXPORT jbyteArray JNICALL Java_vue_NativeVUE_construct (JNIEnv *env, jobject vue) { - // Produce and initialize s new core context + // Produce and initialize a new core context CORE *core = calloc(sizeof (CORE), 1); vueInitialize(&core->vue); vueReset(&core->vue); @@ -68,7 +100,7 @@ JNIEXPORT void JNICALL Java_vue_NativeVUE_construct jbyte *elems = (*env)->GetByteArrayElements(env, pointer, NULL); *(CORE **)elems = core; (*env)->ReleaseByteArrayElements(env, pointer, elems, 0); - (*env)->SetObjectField(env, vue, GetPointerID(env, vue), pointer); + return pointer; } // Release any used resources diff --git a/src/desktop/vue/NativeVUE.java b/src/desktop/vue/NativeVUE.java index c5ab28d..e5c4285 100644 --- a/src/desktop/vue/NativeVUE.java +++ b/src/desktop/vue/NativeVUE.java @@ -14,7 +14,7 @@ class NativeVUE extends VUE { // Default constructor NativeVUE() { - construct(); + pointer = construct(); } @@ -86,6 +86,6 @@ class NativeVUE extends VUE { /////////////////////////////////////////////////////////////////////////// // Native constructor - private native void construct(); + private native byte[] construct(); }