package vue; // Java imports import java.util.*; // CPU state class CPU { // Private fields private JavaVue vue; // Emulation state // Package fields Access access; // Access state int cycles; // Cycles until next stage int exception; // Exception code int fetch; // Fetch unit index Instruction inst; // Instruction state int irq; // Interrupt lines int[] jumpFrom; // Source PCs of most recent jumps int[] jumpTo; // Destination PCs of most recent jumps int stage; // Current processing stage // Program registers int[] program; // System registers int adtre; // Address Trap Register for Execution int eipc; // Exception/interrupt PC int eipsw; // Exception/interrupt PSW int fepc; // Duplexed exception PC int fepsw; // Duplexed exception PSW int pc; // Program Counter int sr29; // System register 29 int sr31; // System register 31 // Program Status Word int psw_ae; // Address Trap Enable int psw_ep; // Exception Pending int psw_id; // Interrupt Disable int psw_cy; // Carry int psw_fiv; // Floating Reserved Operand int psw_fov; // Floating Overflow int psw_fpr; // Floating Precision int psw_fro; // Floating Reserved Operand int psw_fud; // Floating Underflow int psw_fzd; // Floating Zero Divide int psw_i; // Interrupt Level int psw_np; // NMI Pending int psw_ov; // Overflow int psw_s; // Sign int psw_z; // Zero // Cache Control Word int chcw_cec; // Clear Entry Count int chcw_cen; // Clear Entry Number int chcw_icc; // Instruction Cache Clear int chcw_icd; // Instruction Cache Dump int chcw_ice; // Instruction Cache Enable int chcw_icr; // Instruction Cache Restore int chcw_sa; // Spill-Out Base Address // Exception Cause Register int ecr_eicc; // Exception/Interrupt Cause Code int ecr_fecc; // Fatal Error Cause Code /////////////////////////////////////////////////////////////////////////// // Constants // /////////////////////////////////////////////////////////////////////////// // Stages static final int FATAL = -1; static final int FETCH = 0; static final int EXECUTE = 1; static final int EXCEPTION = 2; static final int HALT = 3; static final int CLEAR = 4; static final int DUMP = 5; static final int RESTORE = 6; // Instruction cycle counts private static final byte[] CYCLES = { 1, 1, 28, 1, 1, 1, 1, 1, 1, 26, 12, 1, 1, 10, 14, 16, 38, 44, 36, 1, 5, 5, 5, 3, 3, 3, 5, 5, 5, 8, 1, 1, 1, 1, 1, 9, 13, 30, 13, 1, 1, 1, 1, 1, 1, 4, 4, 4, 10, 22, 1, 1, 1, 1, 1, 1, 12, 1, 1, 1, 1, 1, 4, 4, 4, 8, 1, 28, 15, 14, 6, 1, 1, 1, 1, 1 }; /////////////////////////////////////////////////////////////////////////// // Constructors // /////////////////////////////////////////////////////////////////////////// // Default constructor CPU(JavaVue vue) { access = new Access(); inst = new Instruction(); jumpFrom = new int[3]; jumpTo = new int[3]; program = new int[32]; this.vue = vue; } /////////////////////////////////////////////////////////////////////////// // Package Methods // /////////////////////////////////////////////////////////////////////////// // Process the simulation void emulate(int cycles) { // The CPU is in fatal halt status if (stage == FATAL) return; // Process for the given number of cycles for (;;) { // The next stage occurs after the given number of cycles if (this.cycles > cycles) { this.cycles -= cycles; return; } // Processing by stage cycles -= this.cycles; this.cycles = 0; switch (stage) { case EXCEPTION: if (exception()) return; break; case EXECUTE : if (execute ()) return; break; case FETCH : if (fetch ()) return; break; case HALT : testException(); return; } } } // Read a system register int getSystemRegister(int index) { switch (index) { case Vue.ADTRE: return adtre; case Vue.EIPC : return eipc; case Vue.EIPSW: return eipsw; case Vue.FEPC : return fepc; case Vue.FEPSW: return fepsw; case Vue.ECR : return ecr_fecc << 16 | ecr_eicc; case Vue.PIR : return 0x00005346; case Vue.TKCW : return 0x000000E0; case Vue.CHCW : return chcw_ice << 1; case 29 : return sr29; case 30 : return 0x00000004; case 31 : return sr31; case Vue.PSW : return psw_i << 16 | psw_fro << 9 | psw_fpr << 4 | psw_np << 15 | psw_fiv << 8 | psw_cy << 3 | psw_ep << 14 | psw_fzd << 7 | psw_ov << 2 | psw_ae << 13 | psw_fov << 6 | psw_s << 1 | psw_id << 12 | psw_fud << 5 | psw_z ; // Remaining cases to encourage tableswitch case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: return 0; } return 1; // Unreachable } // System reset void reset() { // Configure instance fields cycles = 0; exception = 0; fetch = -1; irq = 0; stage = FETCH; // Clear all registers (hardware only sets ECR, PC and PSW) for (int x = 0; x < 32; x++) { program[x] = 0; setSystemRegister(x, 0, true); } // Configure jump histories Arrays.fill(jumpFrom, 0xFFFFFFF0); Arrays.fill(jumpTo , 0xFFFFFFF0); // Configure registers ecr_eicc = 0xFFF0; pc = 0xFFFFFFF0; psw_np = 1; } // Write a system register int setSystemRegister(int index, int value, boolean debug) { switch (index) { case Vue.ADTRE: return adtre = value & 0xFFFFFFFE; case Vue.EIPC : return eipc = value & 0xFFFFFFFE; case Vue.EIPSW: return eipsw = value & 0x000FF3FF; case Vue.FEPC : return fepc = value & 0xFFFFFFFE; case Vue.FEPSW: return fepsw = value & 0x000FF3FF; case 29 : return sr29 = value; case 31 : return sr31 = debug || value >= 0 ? value : -value; case Vue.ECR: if (debug) { ecr_fecc = value >> 16 & 0xFFFF; ecr_eicc = value & 0xFFFF; } return ecr_fecc << 16 | ecr_eicc; case Vue.CHCW : chcw_cen = value >> 20 & 0x00000FFF; chcw_cec = value >> 8 & 0x00000FFF; chcw_sa = value >> 8 & 0x00FFFFFF; chcw_icr = value >> 5 & 1; chcw_icd = value >> 4 & 1; chcw_ice = value >> 1 & 1; chcw_icc = value & 1; // Only one of ICC, ICD or ICR is set value &= 0x00000031; if ((value & value - 1) == 0) { // Clear // Dump // Restore } return chcw_ice << 1; case Vue.PSW : psw_i = value >> 16 & 15; psw_fov = value >> 6 & 1; psw_np = value >> 15 & 1; psw_fud = value >> 5 & 1; psw_ep = value >> 14 & 1; psw_fpr = value >> 4 & 1; psw_ae = value >> 13 & 1; psw_cy = value >> 3 & 1; psw_id = value >> 12 & 1; psw_ov = value >> 2 & 1; psw_fro = value >> 9 & 1; psw_s = value >> 1 & 1; psw_fiv = value >> 8 & 1; psw_z = value & 1; psw_fzd = value >> 7 & 1; return value & 0x000FF3FF; // Remaining cases to encourage tableswitch case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 26: case 27: case 28: case 30: return 0; } return 1; // Unreachable } // Determine the number of CPU cycles until a breakpoint could trigger int until(int cycles) { return stage == FATAL || stage == HALT ? cycles : Math.min(cycles, this.cycles); } /////////////////////////////////////////////////////////////////////////// // Private Methods // /////////////////////////////////////////////////////////////////////////// // Operations for exception stage private boolean exception() { // Check for breakpoints if (vue.onBreakpoint(Breakpoint.EXCEPTION)) return true; // Configure working variables exception &= 0xFFFF; boolean isIRQ = (exception & 0xFF00) == 0xFE00; int psw = getSystemRegister(Vue.PSW); // Fatal exception if (psw_np != 0) { vue.write(0x00000000, Vue.S32, 0xFFFF0000 | exception); vue.write(0x00000004, Vue.S32, psw); vue.write(0x00000008, Vue.S32, pc); stage = FATAL; return true; } // Duplexed exception if (psw_ep != 0) { ecr_fecc = exception; fepc = pc; fepsw = psw; psw_np = 1; pc = 0xFFFFFFD0; } // Regular exception else { ecr_eicc = exception; eipc = pc; eipsw = psw; psw_ep = 1; pc = 0xFFFF0000 | exception & 0xFFF0; if (pc == 0xFFFFFF70) // FIV pc = 0xFFFFFF60; } // Interrupt if (isIRQ) { psw_i = Math.min(15, exception >> 4 & 15); if (stage == HALT) pc += 2; } // Common processing cycles = 0; // TODO: Determine the actual number exception = 0; psw_ae = 0; psw_id = 1; stage = FETCH; return false; } // Operations for execute stage private boolean execute() { // Check for breakpoints if (vue.onBreakpoint(Breakpoint.EXECUTE)) return true; // Processing by instruction ID switch (inst.id) { case Vue.ADD_IMM: ADD_IMM(); break; case Vue.ADD_REG: ADD_REG(); break; case Vue.ADDF_S : ADDF_S (); break; case Vue.ADDI : ADDI (); break; case Vue.AND : AND (); break; //case Vue.ANDBSU : ANDBSU (); break; case Vue.ANDI : ANDI (); break; //case Vue.ANDNBSU: ANDNBSU(); break; case Vue.BCOND : BCOND (); break; case Vue.CAXI : CAXI (); break; case Vue.CLI : CLI (); break; case Vue.CMP_IMM: CMP_IMM(); break; case Vue.CMP_REG: CMP_REG(); break; case Vue.CMPF_S : CMPF_S (); break; case Vue.CVT_SW : CVT_SW (); break; case Vue.CVT_WS : CVT_WS (); break; case Vue.DIV : DIV (); break; case Vue.DIVF_S : DIVF_S (); break; case Vue.DIVU : DIVU (); break; case Vue.HALT : HALT (); break; case Vue.IN_B : IN_B (); break; case Vue.IN_H : IN_H (); break; case Vue.IN_W : IN_W (); break; case Vue.JAL : JAL (); break; case Vue.JMP : JMP (); break; case Vue.JR : JR (); break; case Vue.LD_B : LD_B (); break; case Vue.LD_H : LD_H (); break; case Vue.LD_W : LD_W (); break; case Vue.LDSR : LDSR (); break; case Vue.MOV_IMM: MOV_IMM(); break; case Vue.MOV_REG: MOV_REG(); break; //case Vue.MOVBSU : MOVBSU (); break; case Vue.MOVEA : MOVEA (); break; case Vue.MOVHI : MOVHI (); break; case Vue.MPYHW : MPYHW (); break; case Vue.MUL : MUL (); break; case Vue.MULF_S : MULF_S (); break; case Vue.MULU : MULU (); break; case Vue.NOT : NOT (); break; //case Vue.NOTBSU : NOTBSU (); break; case Vue.OR : OR (); break; //case Vue.ORBSU : ORBSU (); break; case Vue.ORI : ORI (); break; //case Vue.ORNBSU : ORNBSU (); break; case Vue.OUT_B : OUT_B (); break; case Vue.OUT_H : OUT_H (); break; case Vue.OUT_W : OUT_W (); break; case Vue.RETI : RETI (); break; case Vue.REV : REV (); break; case Vue.SAR_IMM: SAR_IMM(); break; case Vue.SAR_REG: SAR_REG(); break; //case Vue.SCH0BSD: SCH0BSD(); break; //case Vue.SCH0BSU: SCH0BSU(); break; //case Vue.SCH1BSD: SCH1BSD(); break; //case Vue.SCH1BSU: SCH1BSU(); break; case Vue.SEI : SEI (); break; case Vue.SETF : SETF (); break; case Vue.SHL_IMM: SHL_IMM(); break; case Vue.SHL_REG: SHL_REG(); break; case Vue.SHR_IMM: SHR_IMM(); break; case Vue.SHR_REG: SHR_REG(); break; case Vue.ST_B : ST_B (); break; case Vue.ST_H : ST_H (); break; case Vue.ST_W : ST_W (); break; case Vue.STSR : STSR (); break; case Vue.SUB : SUB (); break; case Vue.SUBF_S : SUBF_S (); break; case Vue.TRAP : TRAP (); break; case Vue.TRNC_SW: TRNC_SW(); break; case Vue.XB : XB (); break; case Vue.XH : XH (); break; case Vue.XOR : XOR (); break; //case Vue.XORBSU : XORBSU (); break; case Vue.XORI : XORI (); break; //case Vue.XORNBSU: XORNBSU(); break; default: // Invalid instruction exception = 0xFF90; } // An application break was requested if (vue.breakCode != 0) return true; // Common processing if (exception == 0) { cycles += CYCLES[inst.id]; pc += inst.size; } program[0] = 0; testException(); if (stage == EXECUTE) stage = FETCH; return false; } // Operations for fetch stage private boolean fetch() { // Entering the fetch stage if (fetch == -1) fetch = 0; // Read the bits from the bus if (read(pc + (fetch << 1), Vue.U16, fetch)) return true; // TODO: Determine how many cycles this takes // First unit if (fetch == 0) { inst.bits = access.value; if (Instruction.size(access.value >> 10) == 4) { fetch = 1; return false; } } // Second unit else { inst.bits |= access.value << 16; fetch = -1; } // Decode the instruction and advance to execute stage inst.decode(inst.bits); stage = EXECUTE; return false; } // Perform a bus read private boolean read(int address, int type, int fetch) { // Perform the operation access.address = address; access.fetch = fetch; access.type = type; access.value = vue.read(address, type); // Check for breakpoints return vue.onBreakpoint(Breakpoint.READ); } // Test a condition private int testCondition(int condition) { switch (condition) { case 0: return psw_ov; case 1: return psw_cy; case 2: return psw_z; case 3: return psw_cy | psw_z; case 4: return psw_s; case 5: return 1; case 6: return psw_ov ^ psw_s; case 7: return psw_ov ^ psw_s | psw_z; } return testCondition(condition & 7) ^ 1; } // Check for an exception or interrupt private boolean testException() { // Check for an interrupt if (irq != 0 && (exception | psw_id | psw_ep | psw_np) == 0) { int level; for (level = 4; level >= 0; level--) if ((irq >> level & 1) != 0) break; exception = 0xFE00 | level << 4; } // There is no exception if (exception == 0) return stage == HALT && cycles == 0; // No further processing // An exception has occurred cycles = 0; stage = EXCEPTION; return false; } // Perform a bus write private boolean write(int address, int type, int value) { // Prepare the operation access.address = address; access.fetch = -1; access.type = type; access.value = value; // Check for breakpoints if (vue.onBreakpoint(Breakpoint.WRITE)) return true; // Perform the operation if (access.type != Vue.CANCEL) vue.write(access.address, access.type, access.value); return false; } /////////////////////////////////////////////////////////////////////////// // Instruction Helpers // /////////////////////////////////////////////////////////////////////////// // Integer addition private int add(int left, int right) { int result = left + right; psw_cy = Integer.compareUnsigned(result, left) < 0 ? 1 : 0; psw_s = result >>> 31; psw_ov = (~(left ^ right) & (left ^ result)) >>> 31; psw_z = result == 0 ? 1 : 0; return result; } // Bitwise operation private void bitwise(int result) { program[inst.reg2] = result; psw_ov = 0; psw_s = result >>> 31; psw_z = result == 0 ? 1 : 0; } // Convert a floating short to word private void floatConvert(boolean round) { // Reserved operand if (floatReserved(false)) return; // Determine the value to convert float value = Float.intBitsToFloat(program[inst.reg1]); value = (float) (round ? Math.round(value) : value < 0 ? Math.ceil(value) : Math.floor(value)); // Invalid operation if (value > 0x7FFFFFFF || value < 0x80000000) { exception = 0xFF70; return; } // Common processing int result = (int) value; if (result != value) // Precision degradation psw_fpr = 1; program[inst.reg2] = result; psw_ov = 0; psw_s = result >>> 31; psw_z = result == 0 ? 1 : 0; } // Determine whether the floating-point operands are reserved values private boolean floatReserved(boolean left) { for (int x = left ? 0 : 1; x < 2; x++) { int operand = program[x == 0 ? inst.reg2 : inst.reg1]; int exponent = operand & 0x7F800000; // Check for a reserved operand if (!( exponent == 0x7F800000 || // Indefinite exponent == 0 && (operand & 0x007FFFFF) != 0 // Denormal )) continue; // The value is a reserved operand exception = 0xFF60; psw_fro = 1; return true; } return false; } // Floating-point result private void floatResult(boolean compare, double full) { // Overflow if (full > Float.MAX_VALUE || full < -Float.MAX_VALUE) { exception = 0xFF64; psw_fov = 1; return; } // Process the result float result = (float) full; int bits = Float.floatToRawIntBits(result); // Underflow if ((bits & 0x7F800000) == 0 && (bits & 0x007FFFFF) != 0) { bits = 0; result = 0; psw_fud = 1; } // Operations other than compare if (!compare) { program[inst.reg2] = bits; if (result != full) // Precision degradation psw_fpr = 1; } // Common processing psw_cy = psw_s = bits >>> 31; psw_ov = 0; psw_z = bits == 0 ? 1 : 0; } // Proxy for IN and LD private void IN_LD(int type) { if (!read(program[inst.reg1] + inst.disp, type, -1)) program[inst.reg2] = access.value; } // Transfer program to another address private void jump(int address) { if (address != pc) { int level = psw_np != 0 ? 2 : psw_ep; jumpFrom[level] = pc; jumpTo [level] = address; } pc = address - inst.size; } // Proxy for OUT and ST private void OUT_ST(int type) { write(program[inst.reg1] + inst.disp, type, program[inst.reg2]); } // Arithmetic shift right private void shiftArithmetic(int value, int bits) { bits &= 31; psw_cy = bits == 0 ? 0 : value >> bits - 1 & 1; bitwise(value >> bits); } // Logical shift left private void shiftLeft(int value, int bits) { bits &= 31; psw_cy = bits == 0 ? 0 : value >> 32 - bits & 1; bitwise(value << bits); } // Logical shift right private void shiftRight(int value, int bits) { bits &= 31; psw_cy = bits == 0 ? 0 : value >> bits - 1 & 1; bitwise(value >>> bits); } // Integer subtraction private int subtract(int left, int right) { int result = left - right; psw_cy = Integer.compareUnsigned(result, left) > 0 ? 1 : 0; psw_s = result >>> 31; psw_ov = ((left ^ right) & (left ^ result)) >>> 31; psw_z = result == 0 ? 1 : 0; return result; } /////////////////////////////////////////////////////////////////////////// // Instruction Methods // /////////////////////////////////////////////////////////////////////////// // Add Immediate private void ADD_IMM() { program[inst.reg2] = add(program[inst.reg2], inst.imm); } // Add Register private void ADD_REG() { program[inst.reg2] = add(program[inst.reg2], program[inst.reg1]); } // Add Floating Short private void ADDF_S() { if (!floatReserved(true)) floatResult(false, (double) Float.intBitsToFloat(program[inst.reg2]) + (double) Float.intBitsToFloat(program[inst.reg1])); } // Add Immediate private void ADDI() { program[inst.reg2] = add(program[inst.reg1], inst.imm); } // And private void AND() { bitwise(program[inst.reg2] & program[inst.reg1]); } // And Immediate private void ANDI() { bitwise(program[inst.reg1] & inst.imm); } // Branch on Condition private void BCOND() { if (testCondition(inst.cond) == 0) return; cycles = 2; jump(pc + inst.disp); } // Compare and Exchange Interlocked private void CAXI() { int address = program[inst.reg1] + inst.disp; int left = program[inst.reg2]; // Retrieve the lock word if (read(address, Vue.S32, -1)) return; int lock = access.value; // Compare and exchange if (lock == left) access.value = program[30]; if (write(address, Vue.S32, access.value)) return; // Update CPU state subtract(left, lock); program[inst.reg2] = lock; } // Clear Interrupt Disable Flag private void CLI() { psw_id = 0; } // Compare Immediate private void CMP_IMM() { subtract(program[inst.reg2], inst.imm); } // Compare Register private void CMP_REG() { subtract(program[inst.reg2], program[inst.reg1]); } // Compare Floating Short private void CMPF_S() { if (!floatReserved(true)) floatResult(true, (double) Float.intBitsToFloat(program[inst.reg2]) - (double) Float.intBitsToFloat(program[inst.reg1])); } // Convert Short Floating to Word private void CVT_SW() { floatConvert(true); } // Convert Word Integer to Short private void CVT_WS() { int bits = program[inst.reg1]; float result = (float) bits; program[inst.reg2] = Float.floatToRawIntBits(result); if (result != bits) // Precision degradation psw_fpr = 1; psw_cy = psw_s = bits >>> 31; psw_ov = 0; psw_z = bits == 0 ? 1 : 0; } // Divide private void DIV() { int left = program[inst.reg2]; int right = program[inst.reg1]; // Zero division if (right == 0) { exception = 0xFF80; return; } // Special case if (left == 0x80000000 && right == 0xFFFFFFFF) { program[30] = 0; program[inst.reg2] = 0x80000000; psw_ov = 1; psw_s = 1; psw_z = 0; return; } // Regular case int result = left / right; program[30] = left % right; program[inst.reg2] = result; psw_ov = 0; psw_s = result >>> 31; psw_z = result == 0 ? 1 : 0; } // Divide Floating Short private void DIVF_S() { int left = program[inst.reg2]; int right = program[inst.reg1]; // Reserved operand if (floatReserved(true)) return; // An exception has occurred if (right == 0) { exception = left == 0 ? 0xFF70 : 0xFF68; return; } // Perform the operation floatResult(false, (double) Float.intBitsToFloat(left) / (double) Float.intBitsToFloat(right)); } // Divide Unsigned private void DIVU() { long left = program[inst.reg2] & 0xFFFFFFFFL; long right = program[inst.reg1] & 0xFFFFFFFFL; // Zero division if (right == 0) { exception = 0xFF80; return; } // Regular case int result = (int) (left / right); program[30] = (int) (left % right); program[inst.reg2] = result; psw_ov = 0; psw_s = result >>> 31; psw_z = result == 0 ? 1 : 0; } // Halt private void HALT() { stage = HALT; inst.size = 0; } // Input Byte from Port private void IN_B() { IN_LD(Vue.U8); } // Input Halfword from Port private void IN_H() { IN_LD(Vue.U16); } // Input Word from Port private void IN_W() { IN_LD(Vue.S32); } // Jump and Link private void JAL() { program[31] = pc + 4; jump(pc + inst.disp); } // Jump Register private void JMP() { jump(program[inst.reg1]); } // Jump Relative private void JR() { jump(pc + inst.disp); } // Load Byte private void LD_B() { IN_LD(Vue.S8); } // Load Halfword private void LD_H() { IN_LD(Vue.S16); } // Load Word private void LD_W() { IN_LD(Vue.S32); } // Load to System Register private void LDSR() { setSystemRegister(inst.imm & 31, program[inst.reg2], false); } // Move Immediate private void MOV_IMM() { program[inst.reg2] = inst.imm; } // Move Register private void MOV_REG() { program[inst.reg2] = program[inst.reg1]; } // Add private void MOVEA() { program[inst.reg2] = program[inst.reg1] + inst.imm; } // Add private void MOVHI() { program[inst.reg2] = program[inst.reg1] + (inst.imm << 16); } // Multiply Halfword private void MPYHW() { program[inst.reg2] *= program[inst.reg1] << 15 >> 15; } // Multiply private void MUL() { long full = (long) program[inst.reg2] * (long) program[inst.reg1]; int result = (int) full; program[30] = (int) (full >> 32); program[inst.reg2] = result; psw_ov = (long) result != full ? 1 : 0; psw_s = result >>> 31; psw_z = result == 0 ? 1 : 0; } // Multiply Floating Short private void MULF_S() { if (!floatReserved(true)) floatResult(false, (double) Float.intBitsToFloat(program[inst.reg2]) * (double) Float.intBitsToFloat(program[inst.reg1])); } // Multiply Unsigned private void MULU() { long full = (program[inst.reg2] & 0xFFFFFFFFL) * (program[inst.reg1] & 0xFFFFFFFFL); int result = (int) full; program[30] = (int) (full >> 32); program[inst.reg2] = result; psw_ov = full > 0xFFFFFFFFL ? 1 : 0; psw_s = result >>> 31; psw_z = result == 0 ? 1 : 0; } // Not private void NOT() { bitwise(~program[inst.reg1]); } // Or private void OR() { bitwise(program[inst.reg2] | program[inst.reg1]); } // Or Immediate private void ORI() { bitwise(program[inst.reg1] | inst.imm); } // Output Byte to Port private void OUT_B() { OUT_ST(Vue.U8); } // Output Halfword to Port private void OUT_H() { OUT_ST(Vue.U16); } // Output Word to Port private void OUT_W() { OUT_ST(Vue.S32); } // Return from Trap or Interrupt private void RETI() { if (psw_np == 1) { pc = fepc; setSystemRegister(Vue.PSW, fepsw, false); } else { pc = eipc; setSystemRegister(Vue.PSW, eipsw, false); } } // Reverse Bits in Word private void REV() { int value = program[inst.reg1]; value = value >> 16 & 0x0000FFFF | value << 16; value = value >> 8 & 0x00FF00FF | value << 8 & 0xFF00FF00; value = value >> 4 & 0x0F0F0F0F | value << 4 & 0xF0F0F0F0; value = value >> 2 & 0x33333333 | value << 2 & 0xCCCCCCCC; value = value >> 1 & 0x55555555 | value << 1 & 0xAAAAAAAA; program[inst.reg2] = value; } // Shift Arithmetic Right by Immediate private void SAR_IMM() { shiftArithmetic(program[inst.reg2], inst.imm); } // Shift Arithmetic Right by Register private void SAR_REG() { shiftArithmetic(program[inst.reg2], program[inst.reg1]); } // Set Interrupt Disable Flag private void SEI() { psw_id = 1; } // Set Flag Condition private void SETF() { program[inst.reg2] = testCondition(inst.imm & 15); } // Shift Logical Left by Immediate private void SHL_IMM() { shiftLeft(program[inst.reg2], inst.imm); } // Shift Logical Left by Register private void SHL_REG() { shiftLeft(program[inst.reg2], program[inst.reg1]); } // Shift Logical Right by Immediate private void SHR_IMM() { shiftRight(program[inst.reg2], inst.imm); } // Shift Logical Right by Register private void SHR_REG() { shiftRight(program[inst.reg2], program[inst.reg1]); } // Store Byte private void ST_B() { OUT_ST(Vue.S8); } // Store Halfword private void ST_H() { OUT_ST(Vue.S16); } // Store Word private void ST_W() { OUT_ST(Vue.S32); } // Store Contents of System Register private void STSR() { program[inst.reg2] = getSystemRegister(inst.imm & 31); } // Subtract private void SUB() { program[inst.reg2] = subtract(program[inst.reg2], program[inst.reg1]); } // Subtract Floating Short private void SUBF_S() { if (!floatReserved(true)) floatResult(false, (double) Float.intBitsToFloat(program[inst.reg2]) - (double) Float.intBitsToFloat(program[inst.reg1])); } // Trap private void TRAP() { exception = 0xFFA0 | inst.imm & 31; pc += 2; } // Truncate Short Floating to Word private void TRNC_SW() { floatConvert(false); } // Exchange Byte private void XB() { int value = program[inst.reg2]; program[inst.reg2] = value & 0xFFFF0000 | value >> 8 & 0xFF | (value & 0xFF) << 8; } // Exchange Halfword private void XH() { int value = program[inst.reg2]; program[inst.reg2] = value >> 16 & 0xFFFF | value << 16; } // Exclusive Or private void XOR() { bitwise(program[inst.reg2] ^ program[inst.reg1]); } // Exclusive Or Immediate private void XORI() { bitwise(program[inst.reg1] ^ inst.imm); } }