/** * Copyright 2012 Tobias Gierke <tobias.gierke@code-sourcery.de> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.codesourcery.jasm16.emulator; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import de.codesourcery.jasm16.Address; import de.codesourcery.jasm16.Register; import de.codesourcery.jasm16.Size; import de.codesourcery.jasm16.emulator.devices.DeviceDescriptor; import de.codesourcery.jasm16.emulator.devices.IDevice; import de.codesourcery.jasm16.emulator.memory.IMemory; public class EmulatorTest extends AbstractEmulatorTest { /* ========================== * ============= SET ======== * ========================== */ @Override protected void setUpHook() throws Exception { emulator.setOutput( ILogger.NOP_LOGGER ); } public void testRegisterSetImmediate() throws InterruptedException, TimeoutException { final String source = " SET a,0x0a\n"+ // 10 " SET b,1\n"+ " SET c,b10\n"+ // 2 " SET x,3\n"+ " SET y,4\n"+ " SET z,5\n"+ " SET i,6\n"+ " SET j,7\n"+ " HCF 0"; execute(source); assertRegA( 10 ); assertRegB( 1 ); assertRegC( 2 ); assertRegX( 3 ); assertRegY( 4 ); assertRegZ( 5 ); assertRegI( 6 ); assertRegJ( 7 ); } public void testRegisterSetRegisterIndirectWithNegativeOffset() throws Exception { final String source = "\n" + "SET a,label2\n" + "SET b,[a-1]\n" + "loop:\n" + "HCF 1\n" + ":label\n" + ".dat 0xbeef\n" + ":label2\n" + ".dat 0"; execute(source); assertRegB( 0xbeef ); } public void testRegisterSetRegisterIndirect() throws InterruptedException, TimeoutException { final String source = " SET a,value\n"+ // 10 " SET b,[a]\n"+ " SET c,[a]\n"+ " SET x,[a]\n"+ " SET y,[a]\n"+ " SET z,[a]\n"+ " SET i,[a]\n"+ " SET j,[a]\n"+ " HCF 0\n"+ // illegal opcode "value: .dat 0xbeef"; execute(source); assertRegB( 0xbeef ); assertRegC( 0xbeef ); assertRegX( 0xbeef ); assertRegY( 0xbeef ); assertRegZ( 0xbeef ); assertRegI( 0xbeef ); assertRegJ( 0xbeef ); } public void testRegisterSetRegisterIndirectWithOffset() throws InterruptedException, TimeoutException { final String source = " SET a,value\n"+ // 10 " SET b,[a+1]\n"+ " SET c,[a+1]\n"+ " SET x,[a+1]\n"+ " SET y,[a+1]\n"+ " SET z,[a+1]\n"+ " SET i,[a+1]\n"+ " SET j,[a+1]\n"+ " HCF 0\n"+ // illegal opcode "value: .dat 0\n"+ " .dat 0xbeef\n"; execute(source); assertRegB( 0xbeef ); assertRegC( 0xbeef ); assertRegX( 0xbeef ); assertRegY( 0xbeef ); assertRegZ( 0xbeef ); assertRegI( 0xbeef ); assertRegJ( 0xbeef ); } public void testRegisterSetIndirect() throws InterruptedException, TimeoutException { final String source = " SET a,[value]\n"+ // 10 " SET b,[value]\n"+ " SET c,[value]\n"+ " SET x,[value]\n"+ " SET y,[value]\n"+ " SET z,[value]\n"+ " SET i,[value]\n"+ " SET j,[value]\n"+ " HCF 0\n"+ // illegal opcode "value: .dat 0xbeef"; execute(source); assertRegA( 0xbeef ); assertRegB( 0xbeef ); assertRegC( 0xbeef ); assertRegX( 0xbeef ); assertRegY( 0xbeef ); assertRegZ( 0xbeef ); assertRegI( 0xbeef ); assertRegJ( 0xbeef ); } public void testRegisterSetFromStack() throws InterruptedException, TimeoutException { final String source = " SET PUSH,0xdead\n"+ // 10 " SET PUSH,1\n"+ // 10 " SET PUSH,2\n"+ // 10 " SET PUSH,3\n"+ // 10 " SET PUSH,4\n"+ // 10 " SET PUSH,5\n"+ // 10 " SET PUSH,6\n"+ // 10 " SET PUSH,7\n"+ // 10 " SET PUSH,8\n"+ // 10 " SET A,POP\n"+ " SET b,POP\n"+ " SET c,POP\n"+ " SET x,POP\n"+ " SET y,POP\n"+ " SET z,POP\n"+ " SET i,POP\n"+ " SET j,POP\n"+ " HCF 0\n"+ // illegal opcode "value: .dat 0xbeef"; execute(source); assertRegA( 8 ); assertRegB( 7 ); assertRegC( 6 ); assertRegX( 5 ); assertRegY( 4 ); assertRegZ( 3 ); assertRegI( 2 ); assertRegJ( 1 ); assertOnTopOfStack( 0xdead ); } public void testMemorySetRegisterIndirectImmediate() throws InterruptedException, TimeoutException { final String source = " SET a,value\n"+ " SET [a],0xbeef\n"+ // 10 " HCF 0\n"+ // illegal opcode "value: .dat 0"; execute(source); assertMemoryValue( 0xbeef, "value" ); } public void testSetStackImmediate() throws InterruptedException, TimeoutException { final String source = " SET PUSH,0xbeef\n"+ // 10 " HCF 0\n"; // illegal opcode execute(source); assertOnTopOfStack( 0xbeef ); } public void testSetFromPC() throws InterruptedException, TimeoutException { final String source = " SET a, 0x01\n" + " SET a,PC\n"+ " HCF 0\n"; // illegal opcode execute(source); assertRegA( 0x02 ); } public void testMemorySetRegisterIndirectWithOffsetImmediate() throws InterruptedException, TimeoutException { final String source = " SET a,value\n"+ " SET [a+1],0xbeef\n"+ // 10 " HCF 0\n"+ // illegal opcode "value: .dat 0\n"+ "value2: .dat 0"; execute(source); assertMemoryValue( 0xbeef, "value2" ); } public void testMemorySetIndirectImmediate() throws InterruptedException, TimeoutException { final String source = " SET [value],0xbeef\n"+ // 10 " HCF 0\n"+ // illegal opcode "value: .dat 0"; execute(source); assertMemoryValue( 0xbeef, "value" ); } public void testMemorySetIndirectIndirect() throws InterruptedException, TimeoutException { final String source = " SET [value2],[value1]\n"+ // 10 " HCF 0\n"+ // illegal opcode "value1: .dat 0xbeef\n"+ "value2: .dat 0"; execute(source); assertMemoryValue( 0xbeef, "value1" ); assertMemoryValue( 0xbeef, "value2" ); } public void testMemorySetIndirectFromRegisterWithOffset() throws InterruptedException, TimeoutException { final String source = " SET a,value1\n" + " SET [value2],[a+1]\n"+ // 10 " HCF 0\n"+ // illegal opcode "value1: .dat 0,0xbeef\n"+ "value2: .dat 0"; execute(source); assertMemoryValue( 0xbeef, "value2" ); } public void testMemorySetIndirectFromRegisterIndirect() throws InterruptedException, TimeoutException { final String source = " SET a,value1\n" + " SET [value2],[a]\n"+ // 10 " HCF 0\n"+ // illegal opcode "value1: .dat 0xbeef\n"+ "value2: .dat 0"; execute(source); assertMemoryValue( 0xbeef, "value2" ); } public void testMemorySetIndirectFromStack() throws InterruptedException, TimeoutException { final String source = " SET PUSH,0xbeef\n" + " SET [value],POP\n"+ // 10 " HCF 0\n"+ // illegal opcode "value: .dat 0"; execute(source); assertMemoryValue( 0xbeef, "value" ); } public void testMemorySetIndirectFromRegister() throws InterruptedException, TimeoutException { final String source = " SET a,0xbeef\n"+ " SET [value],a\n"+ // 10 " HCF 0\n"+ // illegal opcode "value: .dat 0"; execute(source); assertMemoryValue( 0xbeef, "value" ); } /* ========================== * ============= ADX ======== * ========================== */ public void testADX() throws InterruptedException, TimeoutException { final String source = " SET b,1\n"+ " SET a ,2\n"+ " SET ex,3\n"+ " ADX b,a\n"+ " HCF 0"; execute(source); // ADX b,a => sets b to b+a+EX, sets EX to 0x0001 if there is an over-flow, 0x0 otherwise assertRegA(2); assertRegEX(0); assertRegB(6); } public void testADXWithOverflow() throws InterruptedException, TimeoutException { final String source = " SET b,0\n"+ " SET a ,65535\n"+ " SET ex,3\n"+ " ADX b,a\n"+ " HCF 0"; execute(source); assertRegA(0xffff); assertRegEX(1); assertRegB((65535+3) & 0xffff ); } /* ========================== * ============= SBX ======== * ========================== */ public void testSBX() throws InterruptedException, TimeoutException { final String source = " SET b,6\n"+ " SET a ,2\n"+ " SET ex,3\n"+ " SBX b,a\n"+ " HCF 0"; execute(source); // sets b to b-a+EX, sets EX to 0xFFFF if there is an under-flow, 0x0001 if there's an overflow, 0x0 otherwise assertRegA(2); assertRegEX(0); assertRegB(7); } public void testSBXWithUnderflow() throws InterruptedException, TimeoutException { final String source = " SET b,0\n"+ " SET a ,1\n"+ " SET ex,3\n"+ " SBX b,a\n"+ " HCF 0"; execute(source); // sets b to b-a+EX, sets EX to 0xFFFF if there is an under-flow, 0x0001 if there's an overflow, 0x0 otherwise assertRegA( 1 ); assertRegEX(0xffff); assertRegB((65535+3) & 0xffff ); } public void testSBXWithOverflow() throws InterruptedException, TimeoutException { final String source = " SET b,0x7fff\n"+ " SET a ,0\n"+ " SET ex,0xffff\n"+ " SBX b,a\n"+ " HCF 0"; execute(source, 10 * 60 * 1000 ); // sets b to b-a+EX, sets EX to 0xFFFF if there is an under-flow, 0x0001 if there's an overflow, 0x0 otherwise assertRegA( 0 ); assertRegEX(1); assertRegB( 0x17ffe & 0xffff ); } /* ========================== * ============= ADD ======== * ========================== */ public void testRegisterAddImmediate() throws InterruptedException, TimeoutException { final String source = " SET a,0\n"+ " ADD a ,1\n"+ " HCF 0"; execute(source); assertRegA(1); assertRegEX(0); } public void testAddWithPC() throws InterruptedException, TimeoutException { final String source = " SET a,0\n"+ " ADD PC ,1\n"+ " HCF 0\n"+ " SET a,0x42\n"+ " HCF 0"; execute(source); assertRegA(0x42); assertRegEX(0); } public void testRegisterAddOverflow() throws InterruptedException, TimeoutException { final String source = " SET a,65535\n"+ " ADD a ,1\n"+ " HCF 0"; execute(source); assertRegA(0); assertRegEX(1); } public void testMemoryIndirectAddOverflow() throws InterruptedException, TimeoutException { final String source = " ADD [value] ,1\n"+ " HCF 0\n"+ "value: .dat 65535"; execute(source); assertMemoryValue( 0 , "value" ); assertRegEX(1); } public void testAddRegisterRegister() throws InterruptedException, TimeoutException { final String source = " SET a,0\n"+ " SET b,1\n"+ " ADD a ,b\n"+ " HCF 0"; execute(source); assertRegA(1); assertRegEX(0); } public void testRegisterAddIndirect() throws InterruptedException, TimeoutException { final String source = " SET a,0\n"+ " ADD a ,[value]\n"+ " HCF 0\n"+ "value: .dat 1"; execute(source); assertRegA(1); assertRegEX(0); } public void testRegisterAddRegisterRegisterIndirect() throws InterruptedException, TimeoutException { final String source = " SET a,0\n"+ " SET b,value\n"+ " ADD a ,[b]\n"+ " HCF 0\n"+ "value: .dat 1"; execute(source); assertRegA(1); assertRegEX(0); } public void testRegisterAddRegisterRegisterIndirectWithOffset() throws InterruptedException, TimeoutException { final String source = " SET a,0\n"+ " SET b,value\n"+ " ADD a ,[b+1]\n"+ " HCF 0\n"+ "value: .dat 0,1"; execute(source); assertRegA(1); assertRegEX(0); } public void testRegisterAddStack() throws InterruptedException, TimeoutException { final String source = " SET a,0\n" + " SET PUSH,1\n"+ " ADD a ,POP\n"+ " HCF 0\n"; execute(source); assertRegA(1); assertRegEX(0); } /* ========================== * ============= SUB ======== * ========================== */ public void testRegisterSubImmediate() throws InterruptedException, TimeoutException { final String source = " SET a,2\n" + " SUB a,1\n"+ " HCF 0\n"; execute(source); assertRegA(1); assertRegEX(0); } public void testRegisterSubImmediateWithUnderflow() throws InterruptedException, TimeoutException { final String source = " SET a,0\n" + " SUB a,1\n"+ " HCF 0\n"; execute(source); assertRegA(0xffff); assertRegEX(0xffff); } /* ========================== * ============= MUL ======== * ========================== */ public void testRegisterMulImmediate() throws InterruptedException, TimeoutException { final String source = " SET a,2\n" + " MUL a,3\n"+ " HCF 0\n"; execute(source); assertRegA(6); assertRegEX(0); } public void testRegisterMulImmediateWithOverflow() throws InterruptedException, TimeoutException { int a = 65535; int b = 3; final String source = " SET a,"+a+"\n" + " MUL a,"+b+"\n"+ " HCF 0\n"; execute(source); assertRegA(0xfffd); // sets EX to ((b*a)>>16) & 0xffff (treats b, a as unsigned) assertRegEX( ((b*a)>>16) & 0xffff ); } /* ========================== * ============= MLI ======== * ========================== */ public void testRegisterMLIImmediatePositiveResult() throws InterruptedException, TimeoutException { final String source = " SET a,2\n" + " MLI a,3\n"+ " HCF 0\n"; execute(source); assertRegA(6); assertRegEX(0); } public void testRegisterMLIImmediateNegativeResult() throws InterruptedException, TimeoutException { final String source = " SET a,-2\n" + " MLI a,3\n"+ " HCF 0\n"; execute(source); assertRegASigned(-6); assertRegEX( (( signExtend16(-2) * signExtend16(3) )>>16) & 0xffff); } public void testRegisterMLIImmediateWithOverflow() throws InterruptedException, TimeoutException { int a = 0b0111111111111111; int b = 3; final String source = " SET a,"+a+"\n" + " MLI a,"+b+"\n"+ " HCF 0\n"; execute(source); assertRegA(0x7ffd); // sets EX to ((b*a)>>16) & 0xffff (treats b, a as unsigned) assertRegEX( ((b*a)>>16) & 0xffff ); } /* ========================== * ============= DIV ======== * ========================== */ public void testRegisterDIVImmediateWithRemainder() throws InterruptedException, TimeoutException { final int b = 12; final int a = 7; final String source = " SET a,"+b+"\n" + " DIV a,"+a+"\n"+ " HCF 0\n"; execute(source); /* DIV b,a. * * Sets b to b/a, sets EX to ((b<<16)/a)&0xffff. * if a==0, sets b and EX to 0 instead. (treats b, a as unsigned) */ assertRegA(1); assertRegEX( ((b<<16)/a)&0xffff ); } public void testRegisterDIVImmediateWithoutRemainder() throws InterruptedException, TimeoutException { final int b = 12; final int a = 6; final String source = " SET a,"+b+"\n" + " DIV a,"+a+"\n"+ " HCF 0\n"; execute(source); /* DIV b,a. * * Sets b to b/a, sets EX to ((b<<16)/a)&0xffff. * if a==0, sets b and EX to 0 instead. (treats b, a as unsigned) */ assertRegA(2); assertRegEX( ((b<<16)/a)&0xffff ); } public void testRegisterDIVImmediateDivideByZero() throws InterruptedException, TimeoutException { final int b = 12; final int a = 0; final String source = " SET a,"+b+"\n" + " DIV a,"+a+"\n"+ " HCF 0\n"; execute(source); /* DIV b,a. * * Sets b to b/a, sets EX to ((b<<16)/a)&0xffff. * if a==0, sets b and EX to 0 instead. (treats b, a as unsigned) */ assertRegA(0); assertRegEX(0); } /* ========================== * ============= DVI ======== * ========================== */ public void testRegisterDVIImmediateWithRemainder() throws InterruptedException, TimeoutException { final int b = 12; final int a = 7; final String source = " SET a,"+b+"\n" + " DVI a,"+a+"\n"+ " HCF 0\n"; execute(source); /* DIV b,a. * * Sets b to b/a, sets EX to ((b<<16)/a)&0xffff. * if a==0, sets b and EX to 0 instead. (treats b, a as unsigned) */ assertRegA(1); assertRegEX( ((b<<16)/a)&0xffff ); } public void testRegisterDVIImmediateWithoutRemainder() throws InterruptedException, TimeoutException { final int b = 12; final int a = 6; final String source = " SET a,"+b+"\n" + " DVI a,"+a+"\n"+ " HCF 0\n"; execute(source); /* DIV b,a. * * Sets b to b/a, sets EX to ((b<<16)/a)&0xffff. * if a==0, sets b and EX to 0 instead. (treats b, a as unsigned) */ assertRegA(2); assertRegEX( ((b<<16)/a)&0xffff ); } public void testRegisterDVIImmediateDivideByZero() throws InterruptedException, TimeoutException { final int b = 12; final int a = 0; final String source = " SET a,"+b+"\n" + " DVI a,"+a+"\n"+ " HCF 0\n"; execute(source); /* DIV b,a. * * Sets b to b/a, sets EX to ((b<<16)/a)&0xffff. * if a==0, sets b and EX to 0 instead. (treats b, a as unsigned) */ assertRegA(0); assertRegEX(0); } public void testRegisterDVIImmediateNegativeResultWithoutRemainder() throws InterruptedException, TimeoutException { final int b = 12; final int a = -6; final String source = " SET a,"+b+"\n" + " DVI a,"+a+"\n"+ " HCF 0\n"; execute(source); /* DVI b,a. * * Like DIV, but treat b, a as signed. Rounds towards 0 */ assertRegASigned(-2); assertRegEX( (( signExtend16(b) << 16 ) / signExtend16(a) ) &0xffff ); } public void testRegisterDVIImmediateNegativeResultWithRemainderRoundsToZero() throws InterruptedException, TimeoutException { final int b = 24; final int a = -20; // 24 / -20 = -1.2 final String source = " SET a,"+b+"\n" + " DVI a,"+a+"\n"+ " HCF 0\n"; execute(source); /* DVI b,a. * * Like DIV, but treat b, a as signed. Rounds towards 0 */ assertRegASigned(-1); assertRegEX( (( signExtend16(b) << 16 ) / signExtend16(a) ) &0xffff ); } /* ========================== * ============= MOD ======== * ========================== */ public void testRegisterMODImmediateWithoutRemainder() throws InterruptedException, TimeoutException { final int b = 12; final int a = 6; final String source = " SET a,"+b+"\n" + " MOD a,"+a+"\n"+ " HCF 0\n"; execute(source); // sets b to b%a. if a==0, sets b to 0 instead. assertRegA( b % a ); } public void testRegisterMODImmediateWithRemainder() throws InterruptedException, TimeoutException { final int b = 12; final int a = 7; final String source = " SET a,"+b+"\n" + " MOD a,"+a+"\n"+ " HCF 0\n"; execute(source); assertRegA( b % a ); } public void testRegisterMODImmediateWithZero() throws InterruptedException, TimeoutException { final int b = 12; final int a = 0; final String source = " SET a,"+b+"\n" + " MOD a,"+a+"\n"+ " HCF 0\n"; execute(source); assertRegA( 0 ); } /* ========================== * ============= MDI ======== * ========================== */ public void testRegisterMDIImmediateWithoutRemainder() throws InterruptedException, TimeoutException { final int b = 12; final int a = 6; final String source = " SET a,"+b+"\n" + " MDI a,"+a+"\n"+ " HCF 0\n"; execute(source); // like MOD, but treat b, a as signed. (MDI -7, 16 == -7) assertRegASigned( b % a ); } public void testRegisterMDIImmediateWithRemainder() throws InterruptedException, TimeoutException { final int b = 12; final int a = 7; final String source = " SET a,"+b+"\n" + " MDI a,"+a+"\n"+ " HCF 0\n"; execute(source); assertRegASigned( b % a ); } public void testRegisterMDIImmediateWithZero() throws InterruptedException, TimeoutException { final int b = 12; final int a = 0; final String source = " SET a,"+b+"\n" + " MDI a,"+a+"\n"+ " HCF 0\n"; execute(source); assertRegASigned(0); } public void testRegisterMDIImmediateWithoutRemainderSigned() throws InterruptedException, TimeoutException { final int b = 12; final int a = -6; final String source = " SET a,"+b+"\n" + " MDI a,"+a+"\n"+ " HCF 0\n"; execute(source); // like MOD, but treat b, a as signed. (MDI -7, 16 == -7) assertRegASigned( b % a ); } public void testRegisterMDIImmediateWithRemainderSigned() throws InterruptedException, TimeoutException { final int b = 12; final int a = -7; final String source = " SET a,"+b+"\n" + " MDI a,"+a+"\n"+ " HCF 0\n"; execute(source); assertRegASigned( b % a ); } /* ========================== * ============= AND ======== * ========================== */ public void testRegisterANDImmediate() throws InterruptedException, TimeoutException { final String source = " SET a,b1010101010101010\n" + " AND a,b0101010101010101\n"+ " HCF 0\n"; execute(source); assertRegA( 0 ); } /* ========================== * ============= BOR ======== * ========================== */ public void testRegisterBORImmediate() throws InterruptedException, TimeoutException { final String source = " SET a,b1010101010101010\n" + " BOR a,b0101010101010101\n"+ " HCF 0\n"; execute(source); assertRegA( 0xffff ); } /* ========================== * ============= XOR ======== * ========================== */ public void testRegisterXORImmediate() throws InterruptedException, TimeoutException { final String source = " SET a,b1010101010101010\n" + " XOR a,b0101010101010101\n"+ " HCF 0\n"; execute(source); assertRegA( 0b1010101010101010 ^ 0b0101010101010101 ); } /* ========================== * ============= SHR ======== * ========================== */ public void testRegisterSHRImmediate1() throws InterruptedException, TimeoutException { int b = 0b1010101010101010; int a = 1; final String source = " SET a,"+b+"\n" + " SHR a,"+a+"\n"+ " HCF 0\n"; execute(source); // sets b to b>>>a, sets EX to ((b<<16)>>a)&0xffff (logical shift,MSB is populated with zero) assertRegA( 0b0101010101010101 ); assertRegEX( ((b<<16)>>a)&0xffff ); } public void testRegisterSHRImmediate2() throws InterruptedException, TimeoutException { int b = 0b1010101010101010; int a = 1; final String source = " SET a,"+b+"\n" + " SHR a,"+a+"\n"+ " HCF 0\n"; execute(source); // sets b to b>>>a, sets EX to ((b<<16)>>a)&0xffff (logical shift,MSB is populated with zero) assertRegA( 0b0101010101010101 ); assertRegEX( ((b<<16)>>a)&0xffff); } /* ========================== * ============= ASR ======== * ========================== */ public void testRegisterASRImmediate1() throws InterruptedException, TimeoutException { int a = 1; int b = -12; final String source = " SET a,"+b+"\n" + " ASR a,"+a+"\n"+ " HCF 0\n"; execute(source); // sets b to b>>a, sets EX to ((b<<16)>>>a) & 0xffff , (arithmetic shift) (treats b as signed) assertRegASigned( b >> a ); assertRegEX( ((signExtend16(b)<<16)>>>a) & 0xffff ); } public void testRegisterASRImmediate2() throws InterruptedException, TimeoutException { int a = 1; int b = -13; final String source = " SET a,"+b+"\n" + " ASR a,"+a+"\n"+ " HCF 0\n"; execute(source); // sets b to b>>a, sets EX to ((b<<16)>>>a) & 0xffff , (arithmetic shift) (treats b as signed) assertRegASigned( b >> a ); assertRegEX( ((signExtend16(b)<<16)>>>a) & 0xffff ); } /* ========================== * ============= SHL ======== * ========================== */ public void testRegisterSHLImmediate1() throws InterruptedException, TimeoutException { int a = 1; int b = 0b0101010101010101; final String source = " SET a,"+b+"\n" + " SHL a,"+a+"\n"+ " HCF 0\n"; execute(source); // sets b to b<<a, sets EX to ((b<<a)>>16)&0xffff assertRegA( 0b1010101010101010 ); assertRegEX( ((b<<a)>>16)&0xffff ); } public void testRegisterSHLImmediate2() throws InterruptedException, TimeoutException { int a = 1; int b = 0b1010101010101010; final String source = " SET a,"+b+"\n" + " SHL a,"+a+"\n"+ " HCF 0\n"; execute(source); assertRegA( 0b0101010101010100 ); assertRegEX( ((b<<a)>>16)&0xffff ); } /* ========================== * ============= IFB ======== * ========================== */ public void testRegisterIFBImmediateConditionTrue() throws InterruptedException, TimeoutException { final String source = " SET b,3\n" + " IFB b,2\n"+ " SET a,0xbeef\n"+ " HCF 0\n"; execute(source); // performs next instruction only if (b&a)!=0 assertRegA( 0xbeef ); } public void testRegisterIFBImmediateConditionFalse() throws InterruptedException, TimeoutException { final String source = " SET b,3\n" + " IFB b,4\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); assertRegA( 0 ); assertRegC( 0xdead ); } /* ========================== * ============= IFC ======== * ========================== */ public void testRegisterIFCImmediateConditionFalse() throws InterruptedException, TimeoutException { final String source = " SET b,3\n" + " IFC b,2\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); // performs next instruction only if (b&a)==0 assertRegA( 0 ); assertRegC( 0xdead ); } public void testRegisterIFBCImmediateConditionTrue() throws InterruptedException, TimeoutException { final String source = " SET b,3\n" + " IFC b,4\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); assertRegA( 0xbeef ); } /* ========================== * ============= IFE ======== * ========================== */ public void testRegisterIFEImmediateConditionFalse() throws InterruptedException, TimeoutException { final String source = " SET b,3\n" + " IFE b,2\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); // performs next instruction only if b==a assertRegA( 0 ); assertRegC( 0xdead ); } public void testRegisterIFECImmediateConditionTrue() throws InterruptedException, TimeoutException { final String source = " SET b,3\n" + " IFE b,3\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); assertRegA( 0xbeef ); } /* ========================== * ============= IFE ======== * ========================== */ public void testRegisterIFNImmediateConditionTrue() throws InterruptedException, TimeoutException { final String source = " SET b,3\n" + " IFN b,2\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); // performs next instruction only if b==a assertRegA( 0xbeef ); } public void testRegisterIFNImmediateConditionFalse() throws InterruptedException, TimeoutException { final String source = " SET b,3\n" + " IFN b,3\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); assertRegA( 0 ); assertRegC( 0xdead ); } /* ========================== * ============= IFG ======== * ========================== */ public void testRegisterIFGImmediateConditionTrue() throws InterruptedException, TimeoutException { final String source = " SET b,3\n" + " IFG b,2\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); // performs next instruction only if b>a assertRegA( 0xbeef ); } public void testRegisterIFGImmediateConditionFalse() throws InterruptedException, TimeoutException { final String source = " SET b,3\n" + " IFG b,3\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); assertRegA( 0 ); assertRegC( 0xdead ); } /* ========================== * ============= IFL ======== * ========================== */ public void testRegisterIFLImmediateConditionTrue() throws InterruptedException, TimeoutException { final String source = " SET b,2\n" + " IFL b,3\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); // performs next instruction only if b<a assertRegA( 0xbeef ); } public void testRegisterIFLImmediateConditionFalse() throws InterruptedException, TimeoutException { final String source = " SET b,3\n" + " IFL b,3\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); assertRegA( 0 ); assertRegC( 0xdead ); } /* ========================== * ============= IFU ======== * ========================== */ public void testRegisterIFUImmediateConditionTrue() throws InterruptedException, TimeoutException { final String source = " SET b,-3\n" + " IFU b,-2\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); // performs next instruction only if b < a (signed) assertRegA( 0xbeef ); } public void testRegisterIFUImmediateConditionFalse() throws InterruptedException, TimeoutException { final String source = " SET b,-2\n" + " IFU b,-3\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); assertRegA( 0 ); assertRegC( 0xdead ); } /* ========================== * ============= IFA ======== * ========================== */ public void testRegisterIFAImmediateConditionTrue() throws InterruptedException, TimeoutException { final String source = " SET b,-2\n" + " IFA b,-3\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); // performs next instruction only if b>a (signed) assertRegA( 0xbeef ); } public void testRegisterIFAImmediateConditionFalse() throws InterruptedException, TimeoutException { final String source = " SET b,-3\n" + " IFA b,-2\n"+ " SET a,0xbeef\n"+ " SET c,0xdead\n"+ " HCF 0\n"; execute(source); assertRegA( 0 ); assertRegC( 0xdead ); } /* ========================== * ============= JSR ======== * ========================== */ public void testJSR() throws InterruptedException, TimeoutException { final String source = " JSR subroutine\n" + " SET b,0xbeef\n"+ " HCF 0\n"+ "subroutine: SET a ,0xdead\n"+ " SET PC,POP"; execute(source); assertRegA( 0xdead ); assertRegB( 0xbeef ); } /* ========================== * ============= STI ======== * ========================== */ public void testSTI() throws InterruptedException, TimeoutException { final String source = " SET a,5\n" + " SET i , value1\n"+ " SET j , value2\n"+ "loop: \n"+ " STI [j],[i]\n"+ " SUB a,1\n"+ " IFN a,0\n"+ " SET PC,loop\n"+ " HCF 0\n"+ "value1: .dat 1,2,3,4,5\n"+ "value2: .dat 0,0,0,0,0"; execute(source); assertRegA( 0 ); int mem = getLabelAddress("value2").getWordAddressValue(); assertRegI( mem ); assertRegJ( mem+5 ); assertMemoryValue( 1 , Address.wordAddress(mem) ); assertMemoryValue( 2 , Address.wordAddress(mem).plus(Size.words(1), false ) ); assertMemoryValue( 3 , Address.wordAddress(mem).plus(Size.words(2), false ) ); assertMemoryValue( 4 , Address.wordAddress(mem).plus(Size.words(3), false ) ); assertMemoryValue( 5 , Address.wordAddress(mem).plus(Size.words(4), false ) ); assertMemoryValue( 0 , Address.wordAddress(mem).plus(Size.words(5), false ) ); } /* ========================== * ============= STI ======== * ========================== */ public void testSTD() throws InterruptedException, TimeoutException { final String source = " SET a,5\n" + " SET i , value1\n"+ " SET j , value2\n"+ "loop: \n"+ " STD [j],[i]\n"+ " SUB a,1\n"+ " IFN a,0\n"+ " SET PC,loop\n"+ " HCF 0\n"+ "check1:\n"+ " .dat 1,2,3,4\n"+ "value1:\n"+ " .dat 5 \n"+ "check2:\n"+ " .dat 0,0,0,0\n"+ "value2: \n"+ " .dat 0"; execute(source); assertRegA( 0 ); int mem = getLabelAddress("check2").getWordAddressValue(); assertRegI( getLabelAddress("check1").minus(Size.words(1)) ); assertRegJ( getLabelAddress("value1") ); assertMemoryValue( 1 , Address.wordAddress(mem) ); assertMemoryValue( 2 , Address.wordAddress(mem).plus(Size.words(1), false ) ); assertMemoryValue( 3 , Address.wordAddress(mem).plus(Size.words(2), false ) ); assertMemoryValue( 4 , Address.wordAddress(mem).plus(Size.words(3), false ) ); assertMemoryValue( 5 , Address.wordAddress(mem).plus(Size.words(4), false ) ); assertMemoryValue( 0 , Address.wordAddress(mem).plus(Size.words(5), false ) ); } /* ========================== * ============= IAS ======== * ========================== */ public void testIAS() throws InterruptedException, TimeoutException { final String source = " IAS subroutine\n" + " HCF 0\n"+ "subroutine:"; execute(source); assertRegIA( 0x02 ); } /* ========================== * ============= IAG ======== * ========================== */ public void testIAG() throws InterruptedException, TimeoutException { final String source = " IAS subroutine\n" + " IAG a\n"+ " HCF 0\n"+ "subroutine:"; execute(source); assertRegA( 0x3 ); } /* ========================== * ============= INT ======== * ========================== */ public void testINT1() throws InterruptedException, TimeoutException { final String source = " SET a,0x42\n"+ " IAS subroutine\n" + " INT 0xbeef\n"+ // trigger software interrupt with message 0xbeef "contlabel:\n"+ " SET b, 0xdead\n"+ // never reached " HCF 0\n"+ // never reached "subroutine:"+ " SET b,a\n"+ // a will be set to the interrupt message " HCF 0"; execute(source); final Address sp = emulator.getCPU().getSP(); assertRegB( 0xbeef ); /* Stack layout at start of interrupt handler * * +---------+ * | PC | * +---------+ * | A | <-- SP * +---------+ */ assertEquals( Address.wordAddress( 0xfffe ) , sp ); assertMemoryValue( 0x42 , sp ); // saved reg A value assertMemoryValue( getLabelAddress("contlabel") , sp.plus(Size.words(1), false ) ); // PC of instruction after INT } /* ========================== * ============= RFI ======== * ========================== */ public void testRFI() throws InterruptedException, TimeoutException { final String source = " SET a,0x42\n"+ " IAS subroutine\n" + " INT 0xbeef\n"+ // trigger software interrupt with message 0xbeef "contlabel:\n"+ " SET c, 0xdead\n"+ " HCF 0\n"+ "subroutine:"+ " SET b,a\n"+ // a will be set to the interrupt message " RFI 0"; execute(source); assertRegB( 0xbeef ); assertRegC( 0xdead ); /* Stack layout at start of interrupt handler * * +---------+ * | PC | * +---------+ * | A | <-- SP * +---------+ */ assertRegSP( 0 ); } /* ========================== * ============= IAQ ======== * ========================== */ public void testIAQEnableQueueing() throws InterruptedException, TimeoutException { final String source = " IAS subroutine\n" + " IAQ 1\n"+ // switch queuing on " INT 0x42\n"+ // software interrupt will be queued "contlabel:\n"+ " SET c, 0xbeef\n"+ " HCF 0\n"+ "subroutine:"+ " SET x, 0xdead\n"+ " HCF 0"; // a will be set to the interrupt message execute(source); /* IAQ a * * -> if a is nonzero, interrupts will be added to the queue instead of triggered. * -> if a is zero, interrupts will be triggered as normal again */ assertRegC( 0xbeef ); assertRegX( 0 ); /* Stack layout at start of interrupt handler * * +---------+ * | PC | * +---------+ * | A | <-- SP * +---------+ */ assertRegSP( 0 ); } public void testIAQDisableQueueing() throws InterruptedException, TimeoutException { final String source = " SET a,0x42\n"+ " IAS subroutine\n" + " IAQ 1\n"+ // switch queuing on " INT 0x42\n"+ // software interrupt will be queued " IAQ 0\n"+ // switch queuing off "contlabel:\n"+ " SET c, 0xbeef\n"+ " HCF 0\n"+ "subroutine:"+ " SET x, 0xdead\n"+ " HCF 0"; // a will be set to the interrupt message execute(source); /* IAQ a * * -> if a is nonzero, interrupts will be added to the queue instead of triggered. * -> if a is zero, interrupts will be triggered as normal again */ assertRegC( 0 ); assertRegX( 0xdead ); /* Stack layout at start of interrupt handler * * +---------+ * | PC | * +---------+ * | A | <-- SP * +---------+ */ Address sp = emulator.getCPU().getSP(); assertEquals( Address.wordAddress( 0xfffe ) , sp ); assertMemoryValue( 0x42 , sp ); // saved reg A value assertMemoryValue( getLabelAddress("contlabel") , sp.plus(Size.words(1), false ) ); // PC of instruction after INT } /* ========================== * ============= HWN ======== * ========================== */ public void testHWN() throws InterruptedException, TimeoutException { final String source = " HWN a\n"+ // " HCF 0\n"; // illegal opcode execute(source); // sets a to number of connected devices assertRegA( emulator.getDevices().size() ); } /* ========================== * ============= HWQ ======== * ========================== */ public void testHWQ() throws InterruptedException, TimeoutException { final MockDevice device = new MockDevice(); final int slotNo = emulator.addDevice( device ); final String source = " HWQ "+slotNo+"\n"+ // " HCF 0\n"; // illegal opcode try { execute(source); /* sets A, B, C, X, Y registers to information about hardware a * * A+(B<<16) is a 32 bit word identifying the hardware id * C is the hardware version * X+(Y<<16) is a 32 bit word identifying the manufacturer */ // sets a to number of connected devices final IReadOnlyCPU cpu = emulator.getCPU(); final long hardwareId = cpu.getRegisterValue( Register.A) + ( cpu.getRegisterValue( Register.B) << 16 ); final int hardwareVersion = cpu.getRegisterValue( Register.C ); final long manufacturer = cpu.getRegisterValue( Register.X) + ( cpu.getRegisterValue( Register.Y) << 16 ); assertEquals( "Hardware ID mismatch" , device.getDeviceDescriptor().getID() , hardwareId); assertEquals( "Hardware version mismatch" , device.getDeviceDescriptor().getVersion() , hardwareVersion ); assertEquals( "Manufacturer ID mismatch" , device.getDeviceDescriptor().getManufacturer() , manufacturer ); } finally { emulator.removeDevice( device ); } } /* ========================== * ============= HWI ======== * ========================== */ public void testHWI() throws InterruptedException, TimeoutException { final MockDevice device = new MockDevice(); final int slotNo = emulator.addDevice( device ); final String source = " HWI "+slotNo+"\n"+ // " HCF 0\n"; // illegal opcode try { execute(source); assertEquals( 1 , device.getInterruptCount() ); } finally { emulator.removeDevice( device ); } } protected static final class MockDevice implements IDevice { private final DeviceDescriptor desc = new DeviceDescriptor("mock_device", "A mock device", 0x123456, 0x42, 0x654321); private final AtomicInteger interruptCount = new AtomicInteger(0); public MockDevice() { } @Override public void afterAddDevice(IEmulator emulator) { } @Override public void reset() { } @Override public void beforeRemoveDevice(IEmulator emulator) { } @Override public DeviceDescriptor getDeviceDescriptor() { return desc; } public int getInterruptCount() { return interruptCount.get(); } @Override public int handleInterrupt(IEmulator emulator, ICPU cpu, IMemory memory) { interruptCount.incrementAndGet(); return 0; } @Override public boolean supportsMultipleInstances() { return false; } } }