Implementing breakpoint condition evaluator in C, refactoring Java version

This commit is contained in:
Guy Perfect 2020-08-14 17:53:15 -05:00
parent 2df99895fa
commit 1386d36b0d
5 changed files with 1139 additions and 370 deletions

View File

@ -10,7 +10,7 @@ default:
@echo @echo
@echo "Planet Virtual Boy Emulator" @echo "Planet Virtual Boy Emulator"
@echo " https://www.planetvb.com/" @echo " https://www.planetvb.com/"
@echo " August 11, 2020" @echo " August 14, 2020"
@echo @echo
@echo "Intended build environment: Debian i386 or amd64" @echo "Intended build environment: Debian i386 or amd64"
@echo " gcc-multilib" @echo " gcc-multilib"

View File

@ -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

View File

@ -33,55 +33,55 @@ public class Breakpoint {
public static final int UNEXPECTED = 7; public static final int UNEXPECTED = 7;
// Token types // Token types
private static final int BINARY = 1; private static final int BINARY = 4;
private static final int CLOSE = 2; private static final int CLOSE = 6;
private static final int FLOAT = 3; private static final int FLOAT = 1;
private static final int OPEN = 4; private static final int UNARY = 3;
private static final int SYMBOL = 5; private static final int OPEN = 5;
private static final int UNARY = 6; private static final int SYMBOL = 2;
private static final int WORD = 0; private static final int WORD = 0;
// Expected token modes adjacent to any given token // Expected token modes adjacent to any given token
// 0 = Value, unary or open expected, 1 = Binary or close expected // 0 = Value, unary or open expected, 1 = Binary or close expected
private static final int MODES_AFTER = 0b0101101; private static final int MODES_AFTER = 0b1000111;
private static final int MODES_BEFORE = 0b0000110; private static final int MODES_BEFORE = 0b1010000;
// Operator IDs // Operator IDs
private static final int ADD = 0; private static final int ADD = 2;
private static final int BITWISE_AND = 1; private static final int BITWISE_AND = 3;
private static final int BITWISE_NOT = 2; private static final int BITWISE_NOT = 4;
private static final int BITWISE_OR = 3; private static final int BITWISE_OR = 5;
private static final int BITWISE_XOR = 4; private static final int BITWISE_XOR = 6;
private static final int CEIL = 5; private static final int CEIL = 7;
private static final int DIVIDE = 6; private static final int DIVIDE = 8;
private static final int EQUAL = 7; private static final int EQUAL = 9;
private static final int FLOATOP = 8; private static final int FLOOR = 10;
private static final int FLOOR = 9; //private static final int FLOAT = 1; // Same as type
private static final int GREATER_EQUAL_SIGNED = 10; private static final int GREATER_EQUAL_SIGNED = 11;
private static final int GREATER_EQUAL_UNSIGNED = 11; private static final int GREATER_EQUAL_UNSIGNED = 12;
private static final int GREATER_SIGNED = 12; private static final int GREATER_SIGNED = 13;
private static final int GREATER_UNSIGNED = 13; private static final int GREATER_UNSIGNED = 14;
private static final int GROUP = 14; private static final int GROUP = 15;
private static final int LESS_EQUAL_SIGNED = 15; private static final int LESS_EQUAL_SIGNED = 16;
private static final int LESS_EQUAL_UNSIGNED = 16; private static final int LESS_EQUAL_UNSIGNED = 17;
private static final int LESS_SIGNED = 17; private static final int LESS_SIGNED = 18;
private static final int LESS_UNSIGNED = 18; private static final int LESS_UNSIGNED = 19;
private static final int LOGICAL_AND = 19; private static final int LOGICAL_AND = 20;
private static final int LOGICAL_NOT = 20; private static final int LOGICAL_NOT = 21;
private static final int LOGICAL_OR = 21; private static final int LOGICAL_OR = 22;
private static final int LOGICAL_XOR = 22; private static final int LOGICAL_XOR = 23;
private static final int MULTIPLY = 23; private static final int MULTIPLY = 24;
private static final int NEGATE = 24; private static final int NEGATE = 25;
private static final int NOT_EQUAL = 25; private static final int NOT_EQUAL = 26;
private static final int READ_WORD = 26; private static final int READ_WORD = 27;
private static final int REMAINDER = 27; private static final int REMAINDER = 28;
private static final int ROUND = 28; private static final int ROUND = 29;
private static final int SHIFT_LEFT = 29; private static final int SHIFT_LEFT = 30;
private static final int SHIFT_RIGHT = 30; private static final int SHIFT_RIGHT = 31;
private static final int SHIFT_RIGHT_ARITHMETIC = 31; private static final int SHIFT_RIGHT_ARITHMETIC = 32;
private static final int SUBTRACT = 32; private static final int SUBTRACT = 33;
private static final int TRUNC = 33; private static final int TRUNC = 34;
private static final int WORDOP = 34; //private static final int WORD = 0; // Same as type
private static final int XFLOAT = 35; private static final int XFLOAT = 35;
private static final int XWORD = 36; 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 , LOGICAL_NOT ));
OPDEFS.put("-" , new OpDef( 1, UNARY , NEGATE )); OPDEFS.put("-" , new OpDef( 1, UNARY , NEGATE ));
OPDEFS.put("ceil" , new OpDef( 1, UNARY , CEIL )); 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("floor" , new OpDef( 1, UNARY , FLOOR ));
OPDEFS.put("round" , new OpDef( 1, UNARY , ROUND )); OPDEFS.put("round" , new OpDef( 1, UNARY , ROUND ));
OPDEFS.put("trunc" , new OpDef( 1, UNARY , TRUNC )); 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("xfloat", new OpDef( 1, UNARY , XFLOAT ));
OPDEFS.put("xword" , new OpDef( 1, UNARY , XWORD )); OPDEFS.put("xword" , new OpDef( 1, UNARY , XWORD ));
OPDEFS.put("/" , new OpDef( 2, BINARY, DIVIDE )); OPDEFS.put("/" , new OpDef( 2, BINARY, DIVIDE ));
@ -233,16 +233,20 @@ public class Breakpoint {
SYMDEFS.put("lp" , 131); SYMDEFS.put("lp" , 131);
// System register symbol definitions // System register symbol definitions
SYMDEFS.put("adtre", 225); SYMDEFS.put("fepsw", 203); SYMDEFS.put("adtre", 200 + VUE.ADTRE);
SYMDEFS.put("chcw" , 224); SYMDEFS.put("pc" , 199); SYMDEFS.put("chcw" , 200 + VUE.CHCW );
SYMDEFS.put("ecr" , 204); SYMDEFS.put("psw" , 205); SYMDEFS.put("ecr" , 200 + VUE.ECR );
SYMDEFS.put("eipc" , 200); SYMDEFS.put("sr29" , 229); SYMDEFS.put("eipc" , 200 + VUE.EIPC );
SYMDEFS.put("eipsw", 201); SYMDEFS.put("sr31" , 231); SYMDEFS.put("eipsw", 200 + VUE.EIPSW);
SYMDEFS.put("fepc" , 202); 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("pir" , 0x00005346);
LITDEFS.put("tkcw" , 0x000000E0); LITDEFS.put("tkcw" , 0x000000E0);
LITDEFS.put("sr30" , 0x00000004); LITDEFS.put("sr30" , 0x00000004);
}; };
@ -473,6 +477,30 @@ public class Breakpoint {
// Package Methods // // 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 // Determine the required stack size to evaluate the expression
int depth() { int depth() {
@ -849,253 +877,134 @@ public class Breakpoint {
// Evaluation Methods // // Evaluation Methods //
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Evaluate the condition for an emulation context // Resolve a float from word bits
boolean evaluate(JavaVUE vue, int[] stack) { private static float asFloat(int value) {
return Float.intBitsToFloat(value);
// 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(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; // Resolve the word bits of a float
private static int asWord(float value) {
return Float.floatToRawIntBits(fixFloat(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 // Evaluate a binary operator
private int evalBinary(JavaVUE vue, int id, int[] stack, int size) { private static int evalBinary(int id, int[] stack, int size) {
int lw = stack[size - 3]; int rv = stack[size - 1];
float lf = Float.intBitsToFloat(lw); int rt = stack[size - 2];
int ret = 0; boolean rw = rt == WORD;
int rw = stack[size - 1]; int lv = stack[size - 3];
float rf = Float.intBitsToFloat(rw); int lt = stack[size - 4];
int type = stack[size - 2] | stack[size - 4]; boolean lw = lt == WORD;
int type = rw && lw ? WORD : FLOAT;
int value = 0;
switch (id) { switch (id) {
// Arithmetic
case ADD : case ADD :
ret = evalAdd (type, lw, lf, rw, rf); break; value = evalAdd (lw, lv, rw, rv); 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;
case DIVIDE : case DIVIDE :
ret = evalDivide (type, lw, lf, rw, rf); break; value = evalDivide (lw, lv, rw, rv); 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;
case MULTIPLY : case MULTIPLY :
ret = evalMultiply (type, lw, lf, rw, rf); break; value = evalMultiply (lw, lv, rw, rv); break;
case NOT_EQUAL :
ret = evalNotEqual (type, lw, lf, rw, rf);
type = WORD; break;
case REMAINDER : case REMAINDER :
ret = evalRemainder (type, lw, lf, rw, rf); break; value = evalRemainder (lw, lv, rw, rv); 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;
case SUBTRACT : 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 - 4] = type;
stack[size - 3] = ret; stack[size - 3] = value;
return size - 2; 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 // 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; int ret = 0;
if (vue.cpu.stage == CPU.EXCEPTION) switch (id) { if (id == VUE.PC)
case CODE: ret = vue.cpu.exception.code; break; ret = vue.cpu.pc;
} else if (id >= 200)
else switch (id) { 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 ADDRESS : ret = evalAddress (vue); break;
case COND : ret = evalCond (vue); break; case COND : ret = evalCond (vue); break;
case DISP : ret = evalDisp (vue); break; case DISP : ret = evalDisp (vue); break;
@ -1116,8 +1025,235 @@ public class Breakpoint {
return size; 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 // Evaluate address
private int evalAddress(JavaVUE vue) { private static int evalAddress(JavaVUE vue) {
if (vue.cpu.inst.format == 6) if (vue.cpu.inst.format == 6)
return vue.cpu.program[vue.cpu.inst.reg1] + vue.cpu.inst.disp; return vue.cpu.program[vue.cpu.inst.reg1] + vue.cpu.inst.disp;
switch (vue.cpu.inst.id) { switch (vue.cpu.inst.id) {
@ -1132,7 +1268,7 @@ public class Breakpoint {
} }
// Evaluate cond // Evaluate cond
private int evalCond(JavaVUE vue) { private static int evalCond(JavaVUE vue) {
switch (vue.cpu.inst.id) { switch (vue.cpu.inst.id) {
case VUE.BCOND: return vue.cpu.inst.cond; case VUE.BCOND: return vue.cpu.inst.cond;
case VUE.SETF : return vue.cpu.inst.imm; case VUE.SETF : return vue.cpu.inst.imm;
@ -1141,7 +1277,7 @@ public class Breakpoint {
} }
// Evaluate disp // Evaluate disp
private int evalDisp(JavaVUE vue) { private static int evalDisp(JavaVUE vue) {
switch (vue.cpu.inst.format) { switch (vue.cpu.inst.format) {
case 3: case 4: case 6: return vue.cpu.inst.disp; case 3: case 4: case 6: return vue.cpu.inst.disp;
} }
@ -1149,7 +1285,7 @@ public class Breakpoint {
} }
// Evaluate imm // Evaluate imm
private int evalImm(JavaVUE vue) { private static int evalImm(JavaVUE vue) {
switch (vue.cpu.inst.format) { switch (vue.cpu.inst.format) {
case 2: case 5: return vue.cpu.inst.imm; case 2: case 5: return vue.cpu.inst.imm;
} }
@ -1157,7 +1293,7 @@ public class Breakpoint {
} }
// Evaluate reg1 // Evaluate reg1
private int evalReg1(JavaVUE vue) { private static int evalReg1(JavaVUE vue) {
switch (vue.cpu.inst.format) { switch (vue.cpu.inst.format) {
case 1: case 5: case 6: case 7: return vue.cpu.inst.reg1; case 1: case 5: case 6: case 7: return vue.cpu.inst.reg1;
} }
@ -1165,7 +1301,7 @@ public class Breakpoint {
} }
// Evaluate reg2 // Evaluate reg2
private int evalReg2(JavaVUE vue) { private static int evalReg2(JavaVUE vue) {
switch (vue.cpu.inst.format) { switch (vue.cpu.inst.format) {
case 1: case 2: case 5: case 6: case 7: return vue.cpu.inst.reg2; case 1: case 2: case 5: case 6: case 7: return vue.cpu.inst.reg2;
} }
@ -1173,7 +1309,7 @@ public class Breakpoint {
} }
// Evaluate regid // Evaluate regid
private int evalRegId(JavaVUE vue) { private static int evalRegId(JavaVUE vue) {
switch (vue.cpu.inst.id) { switch (vue.cpu.inst.id) {
case VUE.LDSR: case VUE.STSR: return vue.cpu.inst.imm; case VUE.LDSR: case VUE.STSR: return vue.cpu.inst.imm;
} }
@ -1181,7 +1317,7 @@ public class Breakpoint {
} }
// Evaluate subopcode // Evaluate subopcode
private int evalSubopcode(JavaVUE vue) { private static int evalSubopcode(JavaVUE vue) {
switch (vue.cpu.inst.opcode) { switch (vue.cpu.inst.opcode) {
case 0x1F: return vue.cpu.inst.imm; case 0x1F: return vue.cpu.inst.imm;
case 0x3E: return vue.cpu.inst.subopcode; case 0x3E: return vue.cpu.inst.subopcode;
@ -1190,110 +1326,75 @@ public class Breakpoint {
} }
// Evaluate value // Evaluate value
private int evalValue(JavaVUE vue) { private static int evalValue(JavaVUE vue) {
return vue.cpu.inst.format == 6 ? vue.cpu.access.value : 0; return vue.cpu.inst.format == 6 ? vue.cpu.access.value : 0;
} }
// Evaluate vector // 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; 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]; // Unary Methods //
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;
}
// Evaluate ~ // Evaluate ~
private int evalBitwiseNot(int type, int w, float f) { private static int evalBitwiseNot(boolean isWord, int value) {
return type == WORD ? ~w : return isWord ? ~value : ~toWord(asFloat(value));
Float.floatToRawIntBits(fixFloat(Float.intBitsToFloat(~w)));
} }
// Evaluate ! // Evaluate !
private int evalLogicalNot(int type, int w, float f) { private static int evalLogicalNot(boolean isWord, int value) {
return (type == WORD ? w == 0 : f == 0) ? 1 : 0; return (isWord ? value != 0 : (value & 0x7FFFFFFF) != 0) ? 1 : 0;
} }
// Evaluate - // Evaluate -
private int evalNegate(int type, int w, float f) { private static int evalNegate(boolean isWord, int value) {
return type == WORD ? -w : Float.floatToRawIntBits(-f); return isWord ? -value : asWord(-asFloat(value));
} }
// Evaluate ceil // Evaluate ceil
private int evalCeil(int type, int w, float f) { private static int evalCeil(boolean isWord, int value) {
return type == WORD ? w : return isWord ? value : asWord((float) Math.ceil(asFloat(value)));
Float.floatToRawIntBits((float) Math.ceil(f));
} }
// Evaluate float // Evaluate float
private int evalFloat(int type, int w, float f) { private static int evalFloat(boolean isWord, int value) {
return Float.floatToRawIntBits(type == FLOAT ? f : (float) w); return isWord ? asWord((float) value) : value;
} }
// Evaluate floor // Evaluate floor
private int evalFloor(int type, int w, float f) { private static int evalFloor(boolean isWord, int value) {
return type == WORD ? w : return isWord ? value : asWord((float) Math.floor(asFloat(value)));
Float.floatToRawIntBits((float) Math.floor(f));
} }
// Evaluate [] // Evaluate []
private int evalReadWord(int type, int w, float f, JavaVUE vue) { private static int evalReadWord(boolean isWord, int value, JavaVUE vue) {
if (type == FLOAT) { return vue.read(isWord ? value : toWord(asFloat(value)), VUE.S32);
if (f > 0x7FFFFFFF || f < 0x80000000)
return 0;
w = (int) f;
}
return vue.read(w, VUE.S32);
} }
// Evaluate round // Evaluate round
private int evalRound(int type, int w, float f) { private static int evalRound(boolean isWord, int value) {
return type == WORD ? w : return isWord ? value : asWord((float) Math.round(asFloat(value)));
Float.floatToRawIntBits((float) Math.round(f));
} }
// Evaluate trunc // Evaluate trunc
private int evalTrunc(int type, int w, float f) { private static int evalTrunc(boolean isWord, int value) {
return type == WORD ? w : Float.floatToRawIntBits((float) return isWord ? value : asWord((float) (value < 0 ?
(f < 0 ? Math.ceil(f) : Math.floor(f))); Math.ceil(asFloat(value)) : Math.ceil(asFloat(value))));
} }
// Evaluate word // Evaluate word
private int evalWord(int type, int w, float f) { private static int evalWord(boolean isWord, int value) {
return type == WORD ? w : return isWord ? value : toWord(asFloat(value));
f > 0x7FFFFFFF || f < 0x80000000 ? 0 : (int) f;
} }
// Evaluate xfloat // Evaluate xfloat
private int evalXFloat(int type, int w, float f) { private static int evalXFloat(boolean isWord, int value) {
return Float.floatToRawIntBits(type == FLOAT ? f : return isWord ? asWord(asFloat(value)) : value;
fixFloat(Float.intBitsToFloat(w)));
} }
} }

View File

@ -2,6 +2,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h>
#include <jni.h> #include <jni.h>
#include <vue.h> #include <vue.h>
#include "vue_NativeVUE.h" #include "vue_NativeVUE.h"
@ -21,27 +22,58 @@ static const int TYPE_SIZES[] = { 1, 1, 2, 2, 4 };
// Types // // 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 // Core context state type
typedef struct { 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; } 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 // // 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 // Retrieve the handle to a NativeVUE's core context
static CORE* GetCore(JNIEnv *env, jobject vue) { static CORE* GetCore(JNIEnv *env, jobject vue) {
jbyteArray pointer = jbyteArray pointer = (*env)->GetObjectField(env, vue, (*env)->GetFieldID(
(*env)->GetObjectField(env, vue, GetPointerID(env, vue)); env, (*env)->GetObjectClass(env, vue), "pointer", "[B"));
jbyte *elems = (*env)->GetByteArrayElements(env, pointer, NULL); jbyte *elems = (*env)->GetByteArrayElements(env, pointer, NULL);
CORE *core = *(CORE **)elems; CORE *core = *(CORE **)elems;
(*env)->ReleaseByteArrayElements(env, pointer, elems, 0); (*env)->ReleaseByteArrayElements(env, pointer, elems, 0);
@ -55,10 +87,10 @@ static CORE* GetCore(JNIEnv *env, jobject vue) {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Native constructor // Native constructor
JNIEXPORT void JNICALL Java_vue_NativeVUE_construct JNIEXPORT jbyteArray JNICALL Java_vue_NativeVUE_construct
(JNIEnv *env, jobject vue) { (JNIEnv *env, jobject vue) {
// Produce and initialize s new core context // Produce and initialize a new core context
CORE *core = calloc(sizeof (CORE), 1); CORE *core = calloc(sizeof (CORE), 1);
vueInitialize(&core->vue); vueInitialize(&core->vue);
vueReset(&core->vue); vueReset(&core->vue);
@ -68,7 +100,7 @@ JNIEXPORT void JNICALL Java_vue_NativeVUE_construct
jbyte *elems = (*env)->GetByteArrayElements(env, pointer, NULL); jbyte *elems = (*env)->GetByteArrayElements(env, pointer, NULL);
*(CORE **)elems = core; *(CORE **)elems = core;
(*env)->ReleaseByteArrayElements(env, pointer, elems, 0); (*env)->ReleaseByteArrayElements(env, pointer, elems, 0);
(*env)->SetObjectField(env, vue, GetPointerID(env, vue), pointer); return pointer;
} }
// Release any used resources // Release any used resources

View File

@ -14,7 +14,7 @@ class NativeVUE extends VUE {
// Default constructor // Default constructor
NativeVUE() { NativeVUE() {
construct(); pointer = construct();
} }
@ -86,6 +86,6 @@ class NativeVUE extends VUE {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Native constructor // Native constructor
private native void construct(); private native byte[] construct();
} }