void test_VMSR_given_r0_0xe000ed88_should_get_FPSCR_0xe0000088()
{
  writeToCoreRegisters(0, 0xe000ed88);

  writeInstructionToMemoryGivenByAddress(0xeee10a10, 0x08000046);  // VMSR 	FPSCR, r0
  coreReg[PC] = 0x08000046;
  
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();
  
  TEST_ASSERT_EQUAL(0xe0000088, coreReg[fPSCR]);
  TEST_ASSERT_EQUAL(0x0800004a, coreReg[PC]); 
}
// VMOV r10, s3
void test_VMOV_should_move_the_correct_value_from_s3_into_r10()
{
  writeSinglePrecision(3, 0xbbbbbbbb);

  writeInstructionToMemoryGivenByAddress(0xee11aa90, 0x08000046);  // VMOV r10, s3
  coreReg[PC] = 0x08000046;
  
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();
  
  TEST_ASSERT_EQUAL(0xbbbbbbbb, coreReg[10] );
  TEST_ASSERT_EQUAL(0x0800004a, coreReg[PC]);
}
//test case which core register is xPSR
void test_VMRS_given_FPSCR_is_0x20000009f_should_get_xPSR_is_0x21000000()
{
  writeToCoreRegisters(fPSCR, 0x2000009f);

  writeInstructionToMemoryGivenByAddress(0xeef1fa10, 0x08000046);  // VMSR 	r15, FPSCR
  coreReg[PC] = 0x08000046;
  
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();

  TEST_ASSERT_EQUAL(0x21000000, coreReg[xPSR]);
  TEST_ASSERT_EQUAL(0x0800004a, coreReg[PC]); 
}
// VMOV s3, r10
void test_VMOV_should_move_the_correct_value_from_r10_into_s3()
{
  writeToCoreRegisters(10, 0xbbbbbbbb);

  writeInstructionToMemoryGivenByAddress(0xee01aa90, 0x08000046);  // VMOV s3, r10
  coreReg[PC] = 0x08000046;
  
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();
  
  TEST_ASSERT_EQUAL(0xbbbbbbbb00000000, fpuDoublePrecision[1]);
  TEST_ASSERT_EQUAL(0xbbbbbbbb, fpuSinglePrecision[3] );
  TEST_ASSERT_EQUAL(0x0800004a, coreReg[PC]);
}
// VMOV.32 d3[1], r9
void test_VMOV_should_move_the_correct_value_from_r9_into_upper16bits_of_d3()
{
  writeToCoreRegisters(9, 0xaaaaaaaa);

  writeInstructionToMemoryGivenByAddress(0xee239b10, 0x08000046);  // VMOV.32 d3[1], r9
  coreReg[PC] = 0x08000046;
  
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();
  
  TEST_ASSERT_EQUAL(0xaaaaaaaa00000000, fpuDoublePrecision[3]);
  TEST_ASSERT_EQUAL(0xaaaaaaaa, fpuSinglePrecision[7] );
  TEST_ASSERT_EQUAL(0x0800004a, coreReg[PC]);
}
/*  r0  = 0xffffffff
 *  Expected:
 *              r0  = 0x44fd
 *              PC  = 0x08000044
 */
void test_LDRSHLiteral_given_instruction_0xf99f0008_should_get_expected_result(void)
{
  coreReg[0]  = 0xffffffff;
  coreReg[PC] = 0x0800003e;
  memoryBlock[ virtualMemToPhysicalMem(0x08000048) ] = 0xfd;
  memoryBlock[ virtualMemToPhysicalMem(0x08000049) ] = 0x44;
  writeInstructionToMemoryGivenByAddress(0xf9bf0008, 0x0800003e);  //LDRSH r0,[PC,#8]

  //execute
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();

  TEST_ASSERT_EQUAL( 0x44fd, coreReg[0]);
  TEST_ASSERT_EQUAL( 0x08000042, coreReg[PC]);
}
/*
  This function will initialize the general status register, floating point status register and all the other core
  registers.

  
  Below shows the bit assignment of the general status register:
  
  31 30 29 28 27 26  25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
 |N |Z |C |V |Q|IT[1:0]|T|  Reserved  |  GE[3:0]  |      IT[7:2]    |      Reserved     |

  [31]	N
        Negative or less than flag:
                                      1 = result negative
                                      0 = result positive.

  [30]	Z
        Zero flag:
                    1 = result of 0
                    0 = nonzero result.

  [29]	C	(unsigned overflow)
        Carry or borrow flag:
                                1 = carry true or borrow false
                                0 = carry false or borrow true.

  [28]	V	(signed overflow)
        Overflow flag:
                        1 = overflow
                        0 = no overflow.

  [24]  T     indicator to show whether in ARM/Thumb state, 1 for Thumb, 0 for ARM

  IT[7:5]     encodes the base condition (that is, the top 3 bits of the condition specified by the IT instruction) for
              the current IT block, if any. It contains 0b000 when no IT block is active.

  IT[4:0]     encodes the number of instructions that are due to be conditionally executed, and whether the
              condition for each is the base condition code or the inverse of the base condition code.
              It contains 0b00000 when no IT block is active.
  
  
  
  
  
  
  
  Below shows the bits assignment of the floating point status register:
  
  31 30 29 28 27  26 25 24 23 22 21  -----    8  7  6 5  4   3   2   1   0
 |N |Z |C |V |  |AHP|DN|FZ|RMode|   Reserved   |IDC|   |IXC|UFC|OFC|DZC|IOC|



  N, bit[31]                Negative condition code flag. Floating-point comparison operations update this flag.
  
  Z, bit[30]                Zero condition code flag. Floating-point comparison operations update this flag.
  
  C, bit[29]                Carry condition code flag. Floating-point comparison operations update this flag.
  
  V, bit[28]                Overflow condition code flag. Floating-point comparison operations update this flag.
  
  Bit[27]                   Reserved.
  
  AHP, bit[26]              Alternative half-precision control bit:
                            0     IEEE 754-2008 half-precision format selected.
                            1     Alternative half-precision format selected.
                    
                            For more information see Floating-point half-precision formats on page A2-42.
                    
  DN, bit[25]               Default NaN mode control bit:
                            0     NaN operands propagate through to the output of a floating-point operation.
                            1     Any operation involving one or more NaNs returns the Default NaN.
                    
                            For more information, see NaN handling and the Default NaN on page A2-44.
                    
  FZ, bit[24]               Flush-to-zero mode control bit:
                            0     Flush-to-zero mode disabled. Behavior of the floating-point system is fully
                                  compliant with the IEEE 754 standard.
                            1     Flush-to-zero mode enabled.
                    
                            For more information, see Flush-to-zero on page A2-43.
                    
  RMode, bits[23:22]        Rounding Mode control field. The encoding of this field is:
                              0b00 Round to Nearest (RN) mode.
                              0b01 Round towards Plus Infinity (RP) mode.
                              0b10 Round towards Minus Infinity (RM) mode.
                              0b11 Round towards Zero (RZ) mode.
                              The specified rounding mode is used by almost all floating-point instructions.
  
  Bits[21:8]                Reserved.

  IDC, bit[7]               Input Denormal cumulative exception bit.
                            This bit is set to 1 to indicate that the corresponding exception has occurred since 0 was last
                            written to it. For more information about the exception indicated by this bit see
                            Floating-point exceptions on page A2-44.
                            
  Bits[6:5]                 Reserved.
  
  IXC, bit[4]               Inexact cumulative exception bit.
                            This bit is set to 1 to indicate that the corresponding exception has occurred since 0 was last
                            written to it. For more information about the exceptions indicated by this bit see
                            Floating-point exceptions on page A2-44.
                            
  UFC, bit[3]               Underflow cumulative exception bit.
                            This bit is set to 1 to indicate that the corresponding exception has occurred since 0 was last
                            written to it. For more information about the exceptions indicated by this bit see
                            Floating-point exceptions on page A2-44.
                            
  OFC, bit[2]               Overflow cumulative exception bit.
                            This bit is set to 1 to indicate that the corresponding exception has occurred since 0 was last
                            written to it. For more information about the exceptions indicated by this bit see
                            Floating-point exceptions on page A2-44.
                            
  DZC, bit[1]               Division by Zero cumulative exception bit.
                            This bit is set to 1 to indicate that the corresponding exception has occurred since 0 was last
                            written to it. For more information about the exceptions indicated by this bit see
                            Floating-point exceptions on page A2-44.
                            
  IOC, bit[0]               Invalid Operation cumulative exception bit.
                            This bit is set to 1 to indicate that the corresponding exception has occurred since 0 was last
                            written to it. For more information about the exceptions indicated by this bit see
                            Floating-point exceptions on page A2-44.
  
  
  Writes to the FPSCR can have side-effects on various aspects of processor operation. All of these side-effects are
  synchronous to the FPSCR write. This means they are guaranteed not to be visible to earlier instructions in the
  execution stream, and they are guaranteed to be visible to later instructions in the execution stream.
  
  
*/
void initCoreRegister()
{
  int i;
  
  //initialize ARM Core registers which are R0-R15 and APSCR and FPSCR
  for(i = 0; i < NUM_OF_CORE_Register; i++)
  {
    if(i == SP)
      coreReg[i] = SP_INIT_VALUE;
    else if(i == LR)
      coreReg[i] = LR_INIT_VALUE;
    else if(i == xPSR)
      coreReg[i] = 0x01000000;
    else
      coreReg[i] = 0x0;   //FPSCR
  }
  
  //initialize floating point double precision registers
  for(i = 0; i < NUM_OF_FPUD_Register; i++)
  {
    fpuDoublePrecision[i] = 0;
  }
  
  //initialize floating point single precision registers
  for(i = 0; i < NUM_OF_FPUS_Register; i++)
  {
    fpuSinglePrecision[i] = 0;
  }
  
  //initialize system control block (SCB) registers (initialize values refer to ARMRegisters.h)
  writeByteToMemory(FPCCR, FPCCR_INIT_VALUE, 4);
  writeByteToMemory(CPACR, CPACR_INIT_VALUE, 4);
  writeByteToMemory(FPDSCR, FPDSCR_INIT_VALUE, 4);    
  writeByteToMemory(AIRCR, AIRCR_INIT_VALUE, 4);     
  writeByteToMemory(CCR, CCR_INIT_VALUE, 4);
}
/*  r0  = 0xffffffff
 *  Expected:
 *              r0  = 0x4f
 *              PC  = 0x08000044
 */
void test_LDRHLiteral_given_negative_index_should_get_expected_result(void)
{
  coreReg[0]  = 0xffffffff;
  coreReg[PC] = 0x0800003e;
  memoryBlock[ virtualMemToPhysicalMem(0x08000026) ] = 0x4f;
  memoryBlock[ virtualMemToPhysicalMem(0x08000027) ] = 0xf0;
  writeInstructionToMemoryGivenByAddress(0xf83f001a, 0x0800003e);  //LDRH r0,[PC,#-26]

  //execute
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();

  TEST_ASSERT_EQUAL( 0xf04f, coreReg[0]);
  TEST_ASSERT_EQUAL( 0x08000042, coreReg[PC]);
}
/*  r0  = 0xffffffff
 *  r12 = 0x0800001c
 *  Expected:
 *              r0  = 0x3677
 *              PC  = 0x08000044
 */
void test_LDRHT_given_minimum_index_should_get_expected_result(void)
{
  coreReg[0]  = 0xffffffff;
  coreReg[12] = 0x0800001c;
  coreReg[PC] = 0x08000040;
  memoryBlock[ virtualMemToPhysicalMem(0x0800001c) ] = 0x77;
  memoryBlock[ virtualMemToPhysicalMem(0x0800001d) ] = 0x36;
  writeInstructionToMemoryGivenByAddress(0xf83c0e00, 0x08000040);  //ldrht r0, [r12, #0]

  //execute
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();
 
  TEST_ASSERT_EQUAL( 0x3677, coreReg[0]);
  TEST_ASSERT_EQUAL( 0x08000044, coreReg[PC]);
}
/*  r0  = 0xffffffff
 *  r12 = 0x0800011a
 *  Expected:
 *              r0 = 0x77f0
 */
void test_LDRHImmediateT3_given_offindex_should_get_expected_result(void)
{
  coreReg[0]  = 0xffffffff;
  coreReg[12] = 0x0800011a;
  coreReg[PC] = 0x0800003e;
  memoryBlock[ virtualMemToPhysicalMem(0x0800001b) ] = 0xf0;
  memoryBlock[ virtualMemToPhysicalMem(0x0800001c) ] = 0x77;
  writeInstructionToMemoryGivenByAddress(0xf83c0cff, 0x0800003e);  //ldrh r0, [r12,#-255]

  //execute
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();
 
  TEST_ASSERT_EQUAL( 0x77f0, coreReg[0]);
  TEST_ASSERT_EQUAL( 0x08000042, coreReg[PC]);
}
//test maximum index, 255
// LDRSHT.W r1,[r0,#255]
void test_LDRSHT_given_instruction_0xf9301eff_should_load_0x11ef_into_R1()
{
  //create test fixture
  memoryBlock[ virtualMemToPhysicalMem(0x08000060) ] = 0xef;
  memoryBlock[ virtualMemToPhysicalMem(0x08000061) ] = 0xe1;
  memoryBlock[ virtualMemToPhysicalMem(0x08000062) ] = 0x22;
  memoryBlock[ virtualMemToPhysicalMem(0x08000063) ] = 0x08;
  coreReg[0] = 0x7ffff61;
  writeInstructionToMemoryGivenByAddress(0xf9301eff, 0x08000040);  // LDRSHT.W r1,[r0,#255]
  coreReg[PC] = 0x08000040;
  
  //test
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();

  TEST_ASSERT_EQUAL(0xffffe1ef, coreReg[1]);
  TEST_ASSERT_EQUAL(0x08000044, coreReg[PC]);
  TEST_ASSERT_EQUAL(0x01000000, coreReg[xPSR]);
}
//test offset addressing
// LDRSH.W r1,[r0,#-20]
void test_LDRSHImmediateT2_given_instruction_0xf9301c14_should_load_0x3eee_into_R1()
{
  //create test fixture
  memoryBlock[ virtualMemToPhysicalMem(0x08000038) ] = 0xee;
  memoryBlock[ virtualMemToPhysicalMem(0x08000039) ] = 0x3e;
  memoryBlock[ virtualMemToPhysicalMem(0x0800003a) ] = 0x0a;
  memoryBlock[ virtualMemToPhysicalMem(0x0800003b) ] = 0x48;
  coreReg[0] = 0x800004c;
  writeInstructionToMemoryGivenByAddress(0xf9301c14, 0x0800003c);  // LDRSH.W r1,[r0,#-20]
  coreReg[PC] = 0x0800003c;
  
  //test
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();

  TEST_ASSERT_EQUAL(0x3eee, coreReg[1]);
  TEST_ASSERT_EQUAL(0x08000040, coreReg[PC]);
  TEST_ASSERT_EQUAL(0x01000000, coreReg[xPSR]);
}
//test maximum index, 4095
// LDRSH.W r1,[r0,#4095]
void test_LDRSHImmediateT1_given_instruction_0xf9901fff_should_load_0x08000007_into_R1()
{
  //create test fixture
  memoryBlock[ virtualMemToPhysicalMem(0x08000068) ] = 0x00;
  memoryBlock[ virtualMemToPhysicalMem(0x08000069) ] = 0x10;
  memoryBlock[ virtualMemToPhysicalMem(0x0800006a) ] = 0x00;
  memoryBlock[ virtualMemToPhysicalMem(0x0800006b) ] = 0x20;
  coreReg[0] = 0x07fff069;
  writeInstructionToMemoryGivenByAddress(0xf9b01fff, 0x08000040);  // LDRSH.W r1,[r0,#4095]
  coreReg[PC] = 0x08000040;
  
  //test
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();

  TEST_ASSERT_EQUAL(0x00001000, coreReg[1]);
  TEST_ASSERT_EQUAL(0x08000044, coreReg[PC]);
  TEST_ASSERT_EQUAL(0x01000000, coreReg[xPSR]);
}
//test with maximum shifting, 3
// ldrsh.w r5, [r4, r1, lsl #3]
void test_LDRSHRegisterT2_given_instruction_0xf9345031_should_load_0x00ef_into_r5()
{
  //create test fixture
  memoryBlock[ virtualMemToPhysicalMem(0x08000060) ] = 0xef;
  memoryBlock[ virtualMemToPhysicalMem(0x08000061) ] = 0x00;
  memoryBlock[ virtualMemToPhysicalMem(0x08000062) ] = 0x00;
  memoryBlock[ virtualMemToPhysicalMem(0x08000063) ] = 0x08;
  coreReg[4] = 0x0;
  coreReg[1] = 0x100000c;
  writeInstructionToMemoryGivenByAddress(0xf9345031, 0x0800003c);  // ldrsh.w r5, [r4, r1, lsl #3]
  coreReg[PC] = 0x0800003c;
  
  //test
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();
  
  TEST_ASSERT_EQUAL(0x00ef, coreReg[5]);
  TEST_ASSERT_EQUAL(0x08000040, coreReg[PC]);
  TEST_ASSERT_EQUAL(0x01000000, coreReg[xPSR]);
}
// LDRH.W r0,[r1,#4095]
void test_LDRHImmediateT2_given_0xf8b10fff_should_get_R0_is_0xbeef()
{
  //create test fixture
  memoryBlock[ virtualMemToPhysicalMem(0x08000060) ] = 0xef;
  memoryBlock[ virtualMemToPhysicalMem(0x08000061) ] = 0xbe;
  memoryBlock[ virtualMemToPhysicalMem(0x08000062) ] = 0xad;
  memoryBlock[ virtualMemToPhysicalMem(0x08000063) ] = 0xde;
  coreReg[0] = 0xffffffff;
  coreReg[1] = 0x7fff061;
  writeInstructionToMemoryGivenByAddress(0xf8b10fff, 0x08000040);  // LDRH.W r0,[r1,#4095]
  coreReg[PC] = 0x08000040;
  
  //test
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();

  TEST_ASSERT_EQUAL(0xbeef, coreReg[0]);
  TEST_ASSERT_EQUAL(0x08000044, coreReg[PC]);
  TEST_ASSERT_EQUAL(0x01000000, coreReg[xPSR]);
}
//test Post-indexed addressing, positive index
// LDRSH.W r1,[r0], #20
void test_LDRSHImmediateT2_given_instruction_0xf9301b14_should_load_0x4414_into_R1_and_R0_is_0x08000060()
{
  //create test fixture
  memoryBlock[ virtualMemToPhysicalMem(0x0800004c) ] = 0x14;
  memoryBlock[ virtualMemToPhysicalMem(0x0800004d) ] = 0x44;
  memoryBlock[ virtualMemToPhysicalMem(0x0800004e) ] = 0xc8;
  memoryBlock[ virtualMemToPhysicalMem(0x0800004f) ] = 0x2f;
  coreReg[0] = 0x800004c;
  writeInstructionToMemoryGivenByAddress(0xf9301b14, 0x0800003c);  // LDRSH.W r1,[r0], #20
  coreReg[PC] = 0x0800003c;
  
  //test
  writeByteToMemory(CPACR, 0x00F00000, 4);  // enable floating point
  armStep();

  TEST_ASSERT_EQUAL(0x4414, coreReg[1]);
  TEST_ASSERT_EQUAL(0x08000060, coreReg[0]);
  TEST_ASSERT_EQUAL(0x08000040, coreReg[PC]);
  TEST_ASSERT_EQUAL(0x01000000, coreReg[xPSR]);
}
Пример #17
0
int main(void)
{
	int i = 0;
	char x = 0;
	char buf[2], recv;

	unsigned char data;
	unsigned int addr;

	LCD_Init();
	SIO_Init();

	/*set output mode 0*/
	PA_CONTROL = 0x0F;

	/* set 8255 all outputs */
	PIO1_8255_CONTROL = 0x80;
	PIO2_8255_CONTROL = 0x80;
	PIO3_8255_CONTROL = 0x80;

	while(1) {
		LCD_ClearScreen();
		LCD_DispString("mu he he            ", 20);

		SIO_SendString("Z80 Alive...\r\n", 14);
		x = SIO_A_CMD;
		LCD_ShowBin(x);		

		if((x & SIO_DATA_READY) == 1) {
		//Received a character
			recv = SIO_A_DATA;
			SIO_SendString("Received character: ", 20);	
			SIO_SendChar(recv);

			SIO_SendChar(' ');
			charToHexStr(recv, buf);
			SIO_SendString(buf, 2);

			SIO_SendChar('\r');
			SIO_SendChar('\n');

			switch(recv) {
				case 'D':
					writeBufferToMemory(0x4064, "JOU", 3);
					SIO_DumpMemory(0x4000, 128);
					break;

				case 'q':
					PIO3_8255_PB = 0xFF;
					PIO2_8255_PB = 0x00;
					break;

				case 'a':
					PIO3_8255_PB = 0x00;
					PIO2_8255_PB = 0xFF;
					break;

				case 'w':
					addr = getUserInputAddress();
					data = getUserInputData();
					writeByteToMemory(addr, data);
					break;

				case 'r':
					addr = getUserInputAddress();
					data = readByteFromMemory(addr);
					SIO_SendChar(data);
					break;

				default:
					SIO_SendString("WTF?\r\n", 6);
					break;
			}

		}


		PA = 0x55;
		//PIO1_8255_PB = 0x55;
		delay_ms(500);
		PA = 0xAA;
		//PIO1_8255_PB = 0xAA;
		delay_ms(500);

		
		if(i%17 == 0) {
			PIO1_8255_PB = 0x08;
		} else if(i%13 == 0) {
			PIO2_8255_PB = 0x08;
		} else if(i%11 == 0) {
			PIO3_8255_PB = 0x08;
		}

		delay_ms(50);

		if(i%23 == 0) {
			PIO1_8255_PB = 0x00;
		} else if(i%29 == 0) {
			PIO2_8255_PB = 0x00;
		} else if(i%31 == 0) {
			PIO3_8255_PB = 0x00;
		}

		i++;

	}

}
void writeSCBRegisters(uint32_t registerName, uint32_t valueToWrite)
{
  return writeByteToMemory(registerName, valueToWrite, 4);
}