diff --git a/src/asm/libsys/boards/sim/board.c b/src/asm/libsys/boards/sim/board.c new file mode 100644 index 0000000..54dcd09 --- /dev/null +++ b/src/asm/libsys/boards/sim/board.c @@ -0,0 +1,13 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +#include "board.h" + + +void board_init(void) +{ +} + diff --git a/src/asm/libsys/boards/sim/board.h b/src/asm/libsys/boards/sim/board.h new file mode 100644 index 0000000..674a752 --- /dev/null +++ b/src/asm/libsys/boards/sim/board.h @@ -0,0 +1,139 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: board.h + * Author: jens + * + * Created on 8. Januar 2017, 11:33 + */ + +#ifndef BOARD_H +#define BOARD_H + +#define CPU_FREQ_HZ 100000000 +#define UART_STDIO 0 +#define UART_DEBUGGER 1 + +// --------------------------------------------------------- +// IRQs +// --------------------------------------------------------- +#define SYS_INT_SOFT_0 0 +#define SYS_INT_SOFT_1 1 +#define SYS_INT_TIMER 2 +#define SYS_INT_UART0 3 +#define SYS_INT_UART1 4 +#define SYS_INT_FLASH 5 + +// --------------------------------------------------------- +// Memory-mapped registers +// --------------------------------------------------------- +#ifndef SYS_IO_BASE +#define SYS_IO_BASE 0xA0000000 +#endif +#ifndef SDRAM_BASE +#define SDRAM_BASE 0x40000000 +#endif +#ifndef FLASH_BASE_IO +#define FLASH_BASE_IO 0xA4000000 +#endif +#ifndef FLASH_BASE_MEM +#define FLASH_BASE_MEM 0x00000000 +#endif + +// Backwards compatibility +#define SYS_FLASH_IO FLASH_BASE_IO +#define SYS_FLASH_MEM FLASH_BASE_MEM + +// GPIO +#define SYS_GPIO_0_BASE (SYS_IO_BASE + 0) +#define SYS_GPIO_0_DATA (SYS_GPIO_0_BASE + 0) +#define SYS_GPIO_0_DIR (SYS_GPIO_0_BASE + 4) + +#define GPIO_0_DFLT_DIR 0x00000000 // Inputs +#define GPIO_0_DFLT_DATA 0x00000000 + +#define GPIO_0_MASK_LED 0x000000FF +#define GPIO_0_ALIGN_LED 0 + +#define GPIO_0_MASK_DIP 0x0000000F +#define GPIO_0_ALIGN_DIP 8 + +#define GPIO_0_MASK_BTN 0x0000001F +#define GPIO_0_ALIGN_BTN 24 + +// RTC +#define SYS_TIMER_USEC (SYS_IO_BASE + 0x8) +#define SYS_TIMER_SEC (SYS_IO_BASE + 0xC) + +// TIMERs +#define SYS_ITIM_CTRL (SYS_IO_BASE + 0x18) +#define SYS_ITIM_STAT (SYS_IO_BASE + 0x1C) +#define SYS_ITIM0_CNT (SYS_IO_BASE + 0x20) +#define SYS_ITIM1_CNT (SYS_IO_BASE + 0x24) +#define SYS_ITIM2_CNT (SYS_IO_BASE + 0x28) +#define SYS_ITIM3_CNT (SYS_IO_BASE + 0x2C) +#define SYS_ITIM0_CMP (SYS_IO_BASE + 0x30) +#define SYS_ITIM1_CMP (SYS_IO_BASE + 0x34) +#define SYS_ITIM2_CMP (SYS_IO_BASE + 0x38) +#define SYS_ITIM3_CMP (SYS_IO_BASE + 0x3C) + +// UARTs +#define SYS_UART_BIT_TX_HALFFULL 0x00000001 +#define SYS_UART_BIT_TX_FULL 0x00000002 +#define SYS_UART_BIT_RX_HALFFULL 0x00000004 +#define SYS_UART_BIT_RX_FULL 0x00000008 +#define SYS_UART_BIT_RX_AVAIL 0x00000010 +#define SYS_UART_BIT_TX_INTEN 0x00000020 +#define SYS_UART_BIT_RX_INTEN 0x00000040 +#define SYS_UART_BIT_TX_IRQ 0x00000100 +#define SYS_UART_BIT_RX_IRQ 0x00000200 +#define SYS_UART_DATA SYS_UART0_DATA +#define SYS_UART_STAT SYS_UART0_STAT +#define SYS_UART_BAUD SYS_UART0_BAUD +#define SYS_UART0_DATA (SYS_IO_BASE + 0x10000) +#define SYS_UART0_STAT (SYS_IO_BASE + 0x10004) +#define SYS_UART0_BAUD (SYS_IO_BASE + 0x10008) +#define SYS_UART1_DATA (SYS_IO_BASE + 0x30000) +#define SYS_UART1_STAT (SYS_IO_BASE + 0x30004) +#define SYS_UART1_BAUD (SYS_IO_BASE + 0x30008) + +// SPI +#define SYS_SPI_STAT (SYS_IO_BASE + 0x20000) +// Read +#define SPI_STAT_CMDRDY (0x01) +#define SPI_STAT_DINRDY (0x02) +#define SPI_STAT_DOUTRDY (0x04) +#define SPI_STAT_CMD_FIFO_FULL (0x0100) +#define SPI_STAT_CMD_FIFO_EMPTY (0x0200) +#define SPI_STAT_WRITE_FIFO_FULL (0x0400) +#define SPI_STAT_WRITE_FIFO_EMPTY (0x0800) +#define SPI_STAT_READ_FIFO_FULL (0x1000) +#define SPI_STAT_READ_FIFO_EMPTY (0x2000) +#define SPI_STAT_RX_VALID (0x4000) +#define SPI_STAT_SPI_HOLD (0x8000) + +// Write +#define SPI_STAT_COMMIT (1) + +#define SYS_SPI_XFER_SIZE (SYS_IO_BASE + 0x20004) +#define SYS_SPI_DATA_SIZE (SYS_IO_BASE + 0x20008) +#define SYS_SPI_DATA (SYS_IO_BASE + 0x2000C) +#define SYS_SPI_CTRL (SYS_IO_BASE + 0x20010) + +#ifdef __cplusplus +extern "C" { +#endif + + + + +#ifdef __cplusplus +} +#endif + +#endif /* BOARD_H */ + diff --git a/src/asm/tests/test_endianess.c b/src/asm/tests/test_endianess.c new file mode 100644 index 0000000..b4ec6ac --- /dev/null +++ b/src/asm/tests/test_endianess.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include "libsys.h" + +UINT8 g_pattern8[] = {0x01, 0x02, 0x03, 0x4, 0x05, 0x06, 0x07, 0x08}; +UINT16 g_pattern16[sizeof(g_pattern8)/2] = {0}; +UINT32 g_pattern32[sizeof(g_pattern8)/4] = {0}; +UINT8 _g_bytes[4] = {0x12, 0x34, 0x56, 0x78}; +UINT8 _g_bytes2[4] = {0}; + +void MakePattern(void) +{ + + int i; + + UINT16 *pPat16 = (UINT16*)g_pattern8; + UINT32 *pPat32 = (UINT32*)g_pattern8; + + + for (i=0; i < sizeof(g_pattern16)/2; i++) + { + g_pattern16[i] = pPat16[i]; + } + + for (i=0; i < sizeof(g_pattern32)/4; i++) + { + g_pattern32[i] = pPat32[i]; + } +} + +void PrintPattern(void) +{ + + int i; + + printf("Pattern 8bit:\n"); + for (i=0; i < sizeof(g_pattern8); i++) + { + printf("%02X ", g_pattern8[i]); + } + printf("\n"); + + printf("Pattern 16bit:\n"); + for (i=0; i < sizeof(g_pattern16)/2; i++) + { + printf("%04X ", g_pattern16[i]); + } + printf("\n"); + + printf("Pattern 32bit:\n"); + for (i=0; i < sizeof(g_pattern32)/4; i++) + { + printf("%08X ", g_pattern32[i]); + } + printf("\n"); +} + +int IsEndianBig(void) +{ + int i, result; + + UINT8 *pBuf8; + UINT16 *pBuf16; + UINT32 *pBuf32; + UINT16 halve; + UINT32 word; + + + halve = 0x1234; + word = 0x12345678; + + result = -1; + + for (i=0; i < 4; i++) + _g_bytes2[i] = _g_bytes[i]; + + pBuf8 = (UINT8*)&word; + if (((*pBuf8+0) == 0x12) && (*(pBuf8+1) == 0x34) && (*(pBuf8+2) == 0x56) && (*(pBuf8+3) == 0x78)) + { + pBuf8 = (UINT8*)&halve; + if (((*pBuf8+0) == 0x12) && (*(pBuf8+1) == 0x34)) + { + result = 1; + } + } + + pBuf8 = (UINT8*)&word; + if (((*pBuf8+0) == 0x78) && (*(pBuf8+1) == 0x56) && (*(pBuf8+2) == 0x34) && (*(pBuf8+3) == 0x12)) + { + pBuf8 = (UINT8*)&halve; + if (((*pBuf8+0) == 0x34) && (*(pBuf8+1) == 0x12)) + { + result = 0; + } + } + return result; +} + +void PrintCPUinfo(void) +{ + int result, rev_id; + int cache_size, cache_line; + int eb; + + char *cpu_type_str[7] = {"invalid", "R2000", "R3000", "R6000", "R4000", "reserved", "R6000A"}; + + // Print Status register + result = CP0_SR_read(); + + printf("--------------------------------------------------\n"); + printf("Status : %8.8X\n", result); + + // Print Revision + result = CP0_PRID_read(); + rev_id = (result >> 8) & 0xFF; + printf("CPU type : MIPS "); + if ((rev_id > 0) && (rev_id < 0x07)) + { + printf(cpu_type_str[rev_id]); + printf(" Rev. "); + rev_id = result & 0xFF; + printf("%d", rev_id); + } + else + printf("Unknown"); + + eb = IsEndianBig(); + if (eb > 0) + printf(" [Big-endian]\n"); + if (eb == 0) + printf(" [Little-endian]\n"); + if (eb < 0) + printf(" [Unknown endian]\n"); + + printf("--------------------------------------------------\n"); + +} + +int main (void) +{ + int eb; + + setbuf(stdout, NULL); + CP0_SR_write(CP0_SR_read() & ~(1 << 25)); + + PrintCPUinfo(); + + if (IsEndianBig() == 1) + printf("Endian is big\n"); + if (IsEndianBig() == 0) + printf("Endian is little\n"); + + PrintBuffer8(_g_bytes2, 8, 4); + MakePattern(); + PrintPattern(); + + memset(g_pattern16, 0, sizeof(g_pattern16)); + memset(g_pattern32, 0, sizeof(g_pattern32)); + + CP0_SR_write(CP0_SR_read() | (1 << 25)); + eb = IsEndianBig(); + + MakePattern(); + + CP0_SR_write(CP0_SR_read() & ~(1 << 25)); + if (eb == 1) + printf("Endian is big\n"); + if (eb == 0) + printf("Endian is little\n"); + PrintBuffer8(_g_bytes2, 8, 4); + + PrintPattern(); + + return 0; +} + diff --git a/src/asm/tests/test_endianess_sim.c b/src/asm/tests/test_endianess_sim.c new file mode 100644 index 0000000..d5b02b2 --- /dev/null +++ b/src/asm/tests/test_endianess_sim.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include "libsys.h" + +#define TEST_SIZE 32768 +int main (void) +{ + int i; + UINT16 *ram16; + UINT32 sr; + UINT32 volatile *pReg = (UINT32*)SYS_LED_PORT; + + *pReg = 0; + + sr = CP0_SR_read(); + + ram16 = (UINT16*)calloc(TEST_SIZE/2,sizeof(UINT16)); + + CP0_SR_write(sr | (1 << 25)); + + for (i=0; i < TEST_SIZE/2; i++) + ram16[i] = (UINT16)i; + + for (i=TEST_SIZE/2-1; i >= 0; i--) + if (ram16[i] != (UINT16)i) + break; + + i++; + if (i) + *pReg = 0xFFFFFFFF; + else + *pReg = 1; + + + free(ram16); + + ram16 = (UINT16*)calloc(TEST_SIZE/2,sizeof(UINT16)); + + *pReg = 0; + CP0_SR_write(sr & ~(1 << 25)); + + for (i=0; i < TEST_SIZE/2; i++) + ram16[i] = (UINT16)i; + + for (i=TEST_SIZE/2-1; i >= 0; i--) + if (ram16[i] != (UINT16)i) + break; + + i++; + if (i) + *pReg = 0xFFFFFFFF; + else + *pReg = 1; + + + free(ram16); + + +// sputs("Status : ");print_word(sr);sputs("\n"); + + return 0; +} + diff --git a/src/asm/tests/test_exception_sim.c b/src/asm/tests/test_exception_sim.c new file mode 100644 index 0000000..7c9872e --- /dev/null +++ b/src/asm/tests/test_exception_sim.c @@ -0,0 +1,330 @@ +#include +#include +#include +#include +#include "xcpt.h" +#define MAX_NUM_EXCEPTIONS 10 + +void *g_fp_badsubs[MAX_NUM_EXCEPTIONS]; + +void _exc_break(void) +{ + __asm + ( + ".set noreorder\n" + "break 0x9\n" + ".set reorder\n" + + ); +} + +void _exc_syscall(uint32_t code, uint32_t arg) +{ + __asm + ( + "move $v0, %[code]\n" + "move $a0, %[arg]\n" + "syscall\n" + : + : [code] "r" (code), [arg] "r" (arg) + : "v0", "a0" + + ); +} + +void _exc_arith(void) +{ + __asm + ( + ".set noreorder\n" + " li $t0, 0x7FFFFFFF\n" + " addi $t1, $t0, 2\n" + ".set reorder\n" + + ); +} + +void _exc_store_err(void) +{ + __asm + ( + ".set noreorder\n" + " li $t0, 0x40000000\n" + " sw $0, 1($t0)\n" + ".set reorder\n" + + ); + +} + +void _exc_load_err(void) +{ + __asm + ( + ".set noreorder\n" + " li $t0, 0x80000000\n" + " li $t1, 0x80000000\n" + " lw $t1, 0($t1)\n" + " lw $t0, 2($t0)\n" + " lw $t1, 4($t0)\n" + "nop\n" + ".set reorder\n" + + ); + +} + +void _exc_kaddr_err(void) +{ + __asm + ( + ".set noreorder\n" + " li $t0, 0x80000000\n" + " jr $t0\n" + "nop\n" + ".set reorder\n" + + ); + +} + +void _exc_dtlbl_err(void) +{ + __asm + ( + ".set noreorder\n" + " li $t0, 0x00000000\n" + " lw $zero, 0($t0)\n" + "nop\n" + ".set reorder\n" + + ); + +} + +void _exc_dtlbs_err(void) +{ + __asm + ( + ".set noreorder\n" + " li $t0, 0x00000000\n" + " sw $zero, 0($t0)\n" + ".set reorder\n" + + ); + +} + +void _exc_itlbl_err(void) +{ + __asm + ( + ".set noreorder\n" + " li $t0, 0x80000000\n" + " jr $t0\n" + "nop\n" + ".set reorder\n" + + ); + +} + +void _exc_iaddr_daddr_err(void) +{ + __asm + ( + ".set noreorder\n" + " li $t0, 0x80000003\n" + " li $t1, 0x80000002\n" + " jr $t0\n" + " lw $t1, 0($t1)\n" + "nop\n" + ".set reorder\n" + + ); + +} + +void _exc_daddr_iaddr_err(void) +{ + __asm + ( + ".set noreorder\n" + " li $t0, 0x80000003\n" + " li $t1, 0x80000002\n" + " lw $t1, 0($t1)\n" + " jr $t0\n" + "nop\n" + ".set reorder\n" + + ); + +} + +void _exc_iaddr_err(void) +{ + __asm + ( + ".set noreorder\n" + " li $t0, 0x80000003\n" + " jr $t0\n" + "nop\n" + ".set reorder\n" + + ); + +} + +void _exc_ri(void) +{ + __asm + ( + ".set noreorder\n" + ".word 0x9c563442\n" + ".set reorder\n" + + ); + +} + +void _exc_ibe(void) +{ + __asm + ( + ".set noreorder\n" + " li $t1, 0x10000000\n" + " jr $t1\n" + "nop\n" + ".set reorder\n" + + ); + +} + +void _exc_dbe(void) +{ + __asm + ( + ".set noreorder\n" + " li $t1, 0x10000000\n" + " lw $t0, 0($t1)\n" + "nop\n" + " jr $t0\n" + "nop\n" + ".set reorder\n" + + ); + +} + +void handler0(struct xcptcontext *xcp) +{ + sputs("Interrupt 0\n"); + interrupt_clr(0); +} + +void handler1(struct xcptcontext *xcp) +{ + sputs("Interrupt 1\n"); + interrupt_clr(1); +} + +int xcp_handler(struct xcptcontext * xcp) +{ + sputs("----------------------------------------\n"); + sputs("Exception Type: ");xcpt_exctype_print(xcp);sputs("\n"); + sputs("----------------------------------------\n"); + xcpt_registers_print(xcp); + sputs("\n"); + + if (xcpt_get_type(xcp) == EXC_INT) + { + interrupt_disable(0); + interrupt_disable(1); + } + else + { + // Skip instruction that caused exception + xcp->epc += 4; + if (xcp->cr & 0x80000000) + { + xcp->epc += 4; + } + } + + return 0; +} + +int main(void) +{ + int buf[256]; + int i, sel; + + xcpt_register(EXC_INT, xcp_handler); + xcpt_register(EXC_RI, xcp_handler); + xcpt_register(EXC_OV, xcp_handler); + xcpt_register(EXC_BP, xcp_handler); + xcpt_register(EXC_SYSCALL, xcp_handler); + xcpt_register(EXC_TLBL, xcp_handler); + xcpt_register(EXC_TLBS, xcp_handler); + + interrupt_register(0, handler0); + interrupt_enable(0); + interrupt_register(1, handler1); + interrupt_enable(1); + + sputs("11 : SW-interrupt 0\n"); + interrupt_set(0); + sputs("12 : SW-interrupt 1\n"); + interrupt_set(1); + + sputs(" 4 : Syscall\n"); + _exc_syscall(4, (uint32_t)((char*)"Hallo Syscall (")); + _exc_syscall(1, 12345678); + _exc_syscall(4, (uint32_t)((char*)")\n")); + + sputs(" 5 : Breakpoint\n"); + _exc_break(); + + sputs(" 3 : Arithmetic overflow\n"); + _exc_arith(); + + sputs(" 1 : Reserved instruction\n"); + _exc_ri(); + + sputs(" 2 : DTLBS (BadVAddr = 0x00000000)\n"); + _exc_dtlbs_err(); + + sputs(" 2 : DTLBL (BadVAddr = 0x00000000)\n"); + _exc_dtlbl_err(); + + return 0; + + sputs(" 2 : Privileged address (BadVAddr = 0x80000000)\n"); + _exc_kaddr_err(); + + sputs(" 6 : Load error on instruction (BadVAddr = 0x40000003)\n"); + _exc_iaddr_err(); + + sputs(" 7 : Load error on data (BadVAddr = 0x40000002)\n"); + _exc_load_err(); + + sputs(" 8 : Store error on data (BadVAddr = 0x40000001)\n"); + _exc_store_err(); + +// sputs(" 9 : Bus error on instruction\n"); +// sputs("IBE: Exception not implemented in current CPU!\nPush reset to restart!\n"); +// _exc_ibe(); + +// sputs("10 : Bus error on data\n"); +// sputs("DBE: Exception not implemented in current CPU!\nPush reset to restart!\n"); +// _exc_dbe(); + + sputs("13 : Load error on instruction and Load error on data (BadVAddr = 0x40000003)\n"); + _exc_iaddr_daddr_err(); + + sputs("14 : Load error on data and Load error on instruction (BadVAddr = 0x40000002)\n"); + _exc_daddr_iaddr_err(); + + return 0; +} diff --git a/src/asm/tests/test_tlb_sim.c b/src/asm/tests/test_tlb_sim.c new file mode 100644 index 0000000..9271895 --- /dev/null +++ b/src/asm/tests/test_tlb_sim.c @@ -0,0 +1,131 @@ +#include +#include +#include "libsys.h" +#include "xcpt.h" + +#define MAX_NUM_EXCEPTIONS 10 +void *g_fp_badsubs[MAX_NUM_EXCEPTIONS]; + +void _exc_dtlbl_err(UINT32 vaddr) +{ + __asm + ( + ".set noreorder\n" + " move $v0, %[vaddr]\n" + " lw $zero, 0($v0)\n" + "nop\n" + ".set reorder\n" + : + : [vaddr] "r" (vaddr) + : "v0" + + ); + +} + +void _exc_dtlbs_err(UINT32 vaddr, UINT32 data) +{ + __asm + ( + ".set noreorder\n" + " move $a0, %[data]\n" + " move $v0, %[vaddr]\n" + " sw $a0, 0($v0)\n" + ".set reorder\n" + : + : [vaddr] "r" (vaddr), [data] "r" (data) + : "v0", "a0" + + ); + +} + +void _exc_itlbl_err(UINT32 vaddr) +{ + __asm + ( + ".set noreorder\n" + " move $v0, %[vaddr]\n" + " jr $v0\n" + "nop\n" + ".set reorder\n" + : + : [vaddr] "r" (vaddr) + : "v0" + + ); + +} + +int xcp_handler(struct xcptcontext * xcp) +{ + sputs("----------------------------------------\n"); + sputs("Exception Type: ");xcpt_exctype_print(xcp);sputs("\n"); + sputs("----------------------------------------\n"); + xcpt_registers_print(xcp); + sputs("\n"); + + sputs("CP0(ENTRY_HI) = "); print_word(CP0_read(10)); sputs("\n"); + sputs("CP0(ENTRY_LO) = "); print_word(CP0_read(2)); sputs("\n"); + + xcp->epc += 4; + if (xcp->cr & 0x80000000) + { + xcp->epc += 4; + } + + interrupt_clr(0); + interrupt_clr(1); + + return 0; +} + +int main(void) +{ + int buf[256]; + int i, sel; + int *pMem; + + xcpt_register(EXC_MOD, xcp_handler); + xcpt_register(EXC_TLBL, xcp_handler); + xcpt_register(EXC_TLBS, xcp_handler); + + // Tell CP0 we want to access D-TLB + CP0_write(3, 0x00000001); + + // Write 1. TLB entry + CP0_write(0, 0x00000800); + CP0_write(10, 0x3110A540); + CP0_write(2, 0x00008300); + CP0_TLBWI; + + // Write 2. TLB entry + CP0_write(0, 0x00000900); + CP0_write(10, 0x3220B540); + CP0_write(2, 0x00009300); + CP0_TLBWI; + + CP0_write(0, 0x00000800); + CP0_TLBR; + sputs("CP0(INDEX) = "); print_word(CP0_read(0)); sputs("\n"); + sputs("CP0(ENTRY_HI) = "); print_word(CP0_read(10)); sputs("\n"); + sputs("CP0(ENTRY_LO) = "); print_word(CP0_read(2)); sputs("\n"); + CP0_write(0, 0x00000900); + CP0_TLBR; + sputs("CP0(INDEX) = "); print_word(CP0_read(0)); sputs("\n"); + sputs("CP0(ENTRY_HI) = "); print_word(CP0_read(10)); sputs("\n"); + sputs("CP0(ENTRY_LO) = "); print_word(CP0_read(2)); sputs("\n"); + + + sputs(" 1 : DTLBS (BadVAddr = 0x3110A234)\n"); + _exc_dtlbs_err(0x3110A234, 0xDECAFED); + + sputs(" 2 : DTLBL (BadVAddr = 0x3220B234)\n"); + _exc_dtlbl_err(0x3220B234); + + sputs(" 3 : ITLBL (BadVAddr = 0x3220B234)\n"); + _exc_itlbl_err(0x3220B234); + + return 0; + +}