- refactored libsys into common

git-svn-id: http://moon:8086/svn/mips@198 a8ebac50-d88d-4704-bea3-6648445a41b3
This commit is contained in:
2021-11-23 18:09:11 +00:00
parent 2c4a6af07b
commit 015deb2ace
38 changed files with 7638 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
# environment vaiables read:
# BOARD = {ml402, denano, sim}
# TLB = {no, yes}
# ENDIANESS = {eb, el}
# DEBUGGER = {gdb, mips, rom}
BOARD ?= ml402
WITH_TLB ?= n
ENDIANESS ?= eb
DEBUGGER ?= mips
include $(MIPS_HOME)/make/mips_lib.mk
OBJS-ml402=$(addprefix $(BUILD_DIR)/, libsys.o xcpt.o syscalls.o cop0.o irq.o $(DBG_OBJ) console.o uart.o board.o gpio.o mips_ps2.o mips_gfx.o screen.o debugger.o)
OBJS-denano=$(addprefix $(BUILD_DIR)/, libsys.o xcpt.o syscalls.o cop0.o irq.o $(DBG_OBJ) console.o uart.o board.o gpio.o debugger.o)
OBJS-sim=$(addprefix $(BUILD_DIR)/, libsys.o xcpt.o syscalls.o cop0.o irq.o console.o uart.o board.o gpio.o)
all: $(BUILD_DIR) $(BUILD_DIR)/libsys.a
$(BUILD_DIR)/%.o : %.c
$(CC) $(CFLAGS) -G 0 -c -o $@ $<
$(BUILD_DIR)/%.o : %.S
$(CC) $(CFLAGS) -G 0 -c -o $@ $<
$(BUILD_DIR)/board.o : boards/$(BOARD)/board.c
$(CC) $(CFLAGS) -G 0 -c -o $@ $<
$(BUILD_DIR)/debugger.o : boards/debugger.c
$(CC) $(CFLAGS) -G 0 -c -o $@ $<
$(BUILD_DIR)/libsys.a: $(OBJS-$(BOARD))
$(AR) -r $(BUILD_DIR)/libsys.a $(OBJS-$(BOARD))
$(CC) $(CFLAGS) -G 0 -c -o $(BUILD_DIR)/startup.o asm/startup.S
$(CC) $(CFLAGS) -G 0 -c -o $(BUILD_DIR)/kernel.o asm/kernel.S
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
clean:
rm -rf $(BUILD_DIR)/*.a $(BUILD_DIR)/*.o > /dev/null
mrproper:
rm -rf $(BUILD_DIR)
+187
View File
@@ -0,0 +1,187 @@
#include "regdef.h"
#include "xcpt_asm.h"
.text
.section .exc_vect, "ax"
.align 2
_xcpt_vector_tbl:
j _xcpt_handler
nop
.text
LEAF(_xcpt_handler)
.set noreorder
.set noat
/* Note: exceptions do not save and restore registers k0 and k1.
* on entry, k1 = exception class.
*/
/* allocate exception stack frame (on 8-byte boundary) */
li k1, XCP_SIZE
subu k1, sp, k1
srl k1, 3 /* shift right/left -> alligned on boundary */
sll k1, 3
/* save enough registers to get by */
sw AT, XCP_AT(k1)
sw v0, XCP_V0(k1)
sw v1, XCP_V1(k1)
sw a0, XCP_A0(k1)
sw a1, XCP_A1(k1)
sw a2, XCP_A2(k1)
sw a3, XCP_A3(k1)
sw sp, XCP_SP(k1)
sw ra, XCP_RA(k1)
/* get coprocessor 0 exception state */
mfc0 a0, CP0_CR
mfc0 a1, CP0_SR
mfc0 a2, CP0_BADDR
mfc0 a3, CP0_EPC
/* we can safely use AT now */
.set at
/* switch to using sp to point at exception frame */
move sp, k1
/* nothing sensible to store for k0/k1, store zero */
sw zero, XCP_K0(sp)
sw zero, XCP_K1(sp)
/* we are now interruptible: dump all remaining state
* into the exception stack frame.
*/
/* coprocessor exception state */
sw a0, XCP_CR(sp)
sw a1, XCP_SR(sp)
sw a2, XCP_BADDR(sp)
sw a3, XCP_EPC(sp)
/* mdhi and mdlo */
mfhi v0
mflo v1
sw v0, XCP_MDHI(sp)
sw v1, XCP_MDLO(sp)
/* Save all the other general registers.
* We save zero, s0-s7 and s8 as well, as instruction emulators (e.g. FP
* operations) and debuggers rely on all registers stored together in
* well-defined structure.
*/
sw zero, XCP_ZERO(sp)
sw t0, XCP_T0(sp)
sw t1, XCP_T1(sp)
sw t2, XCP_T2(sp)
sw t3, XCP_T3(sp)
sw t4, XCP_T4(sp)
sw t5, XCP_T5(sp)
sw t6, XCP_T6(sp)
sw t7, XCP_T7(sp)
sw s0, XCP_S0(sp)
sw s1, XCP_S1(sp)
sw s2, XCP_S2(sp)
sw s3, XCP_S3(sp)
sw s4, XCP_S4(sp)
sw s5, XCP_S5(sp)
sw s6, XCP_S6(sp)
sw s7, XCP_S7(sp)
sw t8, XCP_T8(sp)
sw t9, XCP_T9(sp)
sw gp, XCP_GP(sp)
sw s8, XCP_S8(sp)
/* I don't know what the following does. [rb] */
/* load our _gp pointer */
# la gp, _gp
/* and call the C exception handler */
move a0, sp # arg1 = &xcp
subu sp, 16 # (arg save area)
j _xcpt_call
move ra, zero # fake return address
/* This strange call to _xcpt_call with zero return address is to
* help exception-aware debuggers to trace back over the exception event.
* We are basically interposing a bogus stackframe (with a zero return
* address) between the C exception handler and the actual machine
* exception.
*/
$xcptrest:
.set noat
add AT, sp, 16
/* at points to exception frame */
$xcptrestother:
/* restore all state */
/* restore most general registers */
lw t0, XCP_T0(AT)
lw t1, XCP_T1(AT)
lw t2, XCP_T2(AT)
lw t3, XCP_T3(AT)
lw t4, XCP_T4(AT)
lw t5, XCP_T5(AT)
lw t6, XCP_T6(AT)
lw t7, XCP_T7(AT)
lw s0, XCP_S0(AT)
lw s1, XCP_S1(AT)
lw s2, XCP_S2(AT)
lw s3, XCP_S3(AT)
lw s4, XCP_S4(AT)
lw s5, XCP_S5(AT)
lw s6, XCP_S6(AT)
lw s7, XCP_S7(AT)
lw t8, XCP_T8(AT)
lw t9, XCP_T9(AT)
lw gp, XCP_GP(AT)
lw s8, XCP_S8(AT)
/* mdhi and mdlo */
lw v0, XCP_MDHI(AT)
lw v1, XCP_MDLO(AT)
mthi v0
mtlo v1
/* remaining general registers */
lw a0, XCP_A0(AT)
lw a1, XCP_A1(AT)
lw a2, XCP_A2(AT)
lw a3, XCP_A3(AT)
lw ra, XCP_RA(AT)
/* restore the exception-time status register */
.set noreorder
lw v0, XCP_SR(AT)
nop
mtc0 v0, CP0_SR
lw v1, XCP_V1(AT)
lw v0, XCP_V0(AT)
lw sp, XCP_SP(AT)
/* we are not uninterruptible and can use k1 safely */
lw k1, XCP_EPC(AT)
lw AT, XCP_AT(AT)
mtc0 k1, CP0_EPC
j k1
rfe
.set reorder
.set at
END(_xcpt_handler)
LEAF(_xcpt_call)
/* on entry: a0 == &xcp */
subu sp, 24
sw ra, 16(sp)
/* punt out to _xcpt_deliver */
jal _xcpt_deliver
nop
lw ra, 16(sp)
addu sp, 24
beqz ra, $xcptrest
nop
j ra
nop
END(_xcpt_call)
+81
View File
@@ -0,0 +1,81 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1985 MIPS Computer Systems, Inc.
* Copyright (C) 1994, 95, 99, 2003 by Ralf Baechle
* Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc.
*/
#ifndef _ASM_REGDEF_H
#define _ASM_REGDEF_H
/*
* Symbolic register names for 32 bit ABI
*/
#define zero $0 /* wired zero */
#define AT $1 /* assembler temp - uppercase because of ".set at" */
#define v0 $2 /* return value */
#define v1 $3
#define a0 $4 /* argument registers */
#define a1 $5
#define a2 $6
#define a3 $7
#define t0 $8 /* caller saved */
#define t1 $9
#define t2 $10
#define t3 $11
#define t4 $12
#define t5 $13
#define t6 $14
#define t7 $15
#define s0 $16 /* callee saved */
#define s1 $17
#define s2 $18
#define s3 $19
#define s4 $20
#define s5 $21
#define s6 $22
#define s7 $23
#define t8 $24 /* caller saved */
#define t9 $25
#define jp $25 /* PIC jump register */
#define k0 $26 /* kernel scratch */
#define k1 $27
#define gp $28 /* global pointer */
#define sp $29 /* stack pointer */
#define fp $30 /* frame pointer */
#define s8 $30 /* same like fp! */
#define ra $31 /* return address */
/* CP0 registers */
#define CP0_INDEX $0 /* R3000 available */
#define CP0_RANDOM $1 /* R3000 available */
#define CP0_ENTRYLO $2 /* R3000 available */
#define CP0_CONTEXT $4 /* R3000 available */
#define CP0_BADDR $8 /* R3000 available */
#define CP0_ENTRYHI $10 /* R3000 available */
#define CP0_SR $12 /* R3000 available */
#define CP0_CR $13 /* R3000 available */
#define CP0_EPC $14 /* R3000 available */
#define CP0_PRID $15 /* R3000 available */
/* Status register masks */
#define SR_MASK_IEC 0x00000001
#define SR_MASK_KUC 0x00000002
#define SR_MASK_IEP 0x00000004
#define SR_MASK_KUP 0x00000008
#define SR_MASK_IEO 0x00000010
#define SR_MASK_KUO 0x00000020
#define SR_MASK_IM 0x0000FF00
#define SR_MASK_DS 0x00FF0000
#define SR_MASK_RE 0x01000000
#define SR_MASK_CU 0xF0000000
/* Cause register masks */
#define CR_MASK_EXC 0x0000007C
#define CR_MASK_IP 0x0000FF00
#define CR_MASK_CE 0x40000000
#define CR_MASK_BD 0x80000000
#endif /* _ASM_REGDEF_H */
+51
View File
@@ -0,0 +1,51 @@
#include "regdef.h"
.file "startup.S"
.section .rodata
.data
argv0: .asciz "\"This-MIPS-program\""
argv: .word argv0
.text
.section .start, "ax"
.extern board_init
.align 2
.set noreorder
_start:
la sp, stack_ptr
la gp, _gp
nop
_zero_bss:
# zero bss
la $8, __bss_start
la $9, _end
$_zeroise:
sw $0, 0($8)
bne $8, $9, $_zeroise
addiu $8, 4
_board_init:
# Call board_init
la k0, board_init
jalr k0
nop
# Set environment
li a0, 1
la a1, argv
# Call main
la k0, main
jalr k0
nop
# Terminate after main returns
_terminate:
nop
la t0, exit
jalr t0
move a0, v0
.set reorder
+69
View File
@@ -0,0 +1,69 @@
#ifndef XCPT_ASM_H
#define XCPT_ASM_H
/* LEAF - declare leaf routine */
#define LEAF(symbol) \
.globl symbol; \
.align 2; \
.type symbol, @function; \
.ent symbol, 0; \
symbol: .frame sp, 0, ra
/* END - mark end of function */
#define END(function) \
.end function; \
.size function, .-function
/* Exception stack size */
#ifndef XCP_SIZE
#define XCP_SIZE 65536
#endif
/* save location for registers */
#define XCP_SR 0
#define XCP_CR 4
#define XCP_EPC 8
#define XCP_BADDR 12
#define XCP_ZERO 16
#define XCP_AT 20
#define XCP_V0 24
#define XCP_V1 28
#define XCP_A0 32
#define XCP_A1 36
#define XCP_A2 40
#define XCP_A3 44
#define XCP_T0 48
#define XCP_T1 52
#define XCP_T2 56
#define XCP_T3 60
#define XCP_T4 64
#define XCP_T5 68
#define XCP_T6 72
#define XCP_T7 76
#define XCP_S0 80
#define XCP_S1 84
#define XCP_S2 88
#define XCP_S3 92
#define XCP_S4 96
#define XCP_S5 100
#define XCP_S6 104
#define XCP_S7 108
#define XCP_T8 112
#define XCP_T9 116
#define XCP_JP 116
#define XCP_K0 120
#define XCP_K1 124
#define XCP_GP 128
#define XCP_SP 132
#define XCP_S8 136
#define XCP_FP 136
#define XCP_RA 140
#define XCP_MDLO 144
#define XCP_MDHI 148
#define XCP_COUNT 152
#define XCP_COMPARE 156
#define XCP_PREV 160
#define XCP_CLASS 164
#endif /* XCPT_ASM_H */
+88
View File
@@ -0,0 +1,88 @@
/*
* 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 <stddef.h>
#include "board.h"
#include "../debugger.h"
#include "../../irq.h"
#include "../../uart.h"
#include "../../console.h"
#include "../../asm/regdef.h"
#include "../../syscalls.h"
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
// ---------------------------------------------------------------------------------
// Uart
// ---------------------------------------------------------------------------------
const uart_if_t uart_if[] =
{
{(uint32_t*)SYS_UART0_STAT, (uint32_t*)SYS_UART0_DATA, (uint32_t*)SYS_UART0_BAUD},
{(uint32_t*)SYS_UART1_STAT, (uint32_t*)SYS_UART1_DATA, (uint32_t*)SYS_UART1_BAUD}
};
// ---------------------------------------------------------------------------------
// Console
// ---------------------------------------------------------------------------------
const con_if_entry_t con_if_entry[] =
{
{0, "stdin", &uart_if[0], NULL, NULL, UART_readchar, NULL},
{1, "stdout", &uart_if[0], NULL, NULL, NULL, UART_writechar},
{2, "stderr", &uart_if[0], NULL, NULL, NULL, UART_writechar},
{3, "UART-0", &uart_if[0], NULL, NULL, UART_readchar, UART_writechar},
{4, "UART-1", &uart_if[1], NULL, NULL, UART_readchar, UART_writechar}
};
const con_if_t con_if =
{
con_if_entry, ARRAYSIZE(con_if_entry)
};
void board_init(void)
{
uint32_t volatile *pITIM_ctrl = (uint32_t*)SYS_ITIM_CTRL;
// Disable interrupts
interrupt_global_disable();
// Disable timers
*pITIM_ctrl = 0;
// Setup syscall support
syscalls_init();
// Setup debugger
debugger_init();
// Setup interrupt support
interrupt_init();
// Enable interrupts
interrupt_global_enable();
}
void dbg_putchar(char c)
{
if (c == 0x0A)
{
UART_writechar(&uart_if[UART_DEBUGGER], 0x0D);
}
UART_writechar(&uart_if[UART_DEBUGGER], c);
}
char dbg_getchar()
{
int c;
// busy read
do
{
c = UART_readchar(&uart_if[UART_DEBUGGER]);
} while(c < 0);
return (char)c;
}
+139
View File
@@ -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 50000000
#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 */
+89
View File
@@ -0,0 +1,89 @@
/*
* 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 <stddef.h>
#include "board.h"
#include "../debugger.h"
#include "../../irq.h"
#include "../../uart.h"
#include "../../console.h"
#include "../../asm/regdef.h"
#include "../../syscalls.h"
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
// ---------------------------------------------------------------------------------
// Uart
// ---------------------------------------------------------------------------------
const uart_if_t uart_if[] =
{
{(uint32_t*)SYS_UART0_STAT, (uint32_t*)SYS_UART0_DATA, (uint32_t*)SYS_UART0_BAUD},
{(uint32_t*)SYS_UART1_STAT, (uint32_t*)SYS_UART1_DATA, (uint32_t*)SYS_UART1_BAUD}
};
// ---------------------------------------------------------------------------------
// Console
// ---------------------------------------------------------------------------------
const con_if_entry_t con_if_entry[] =
{
{0, "stdin", &uart_if[0], NULL, NULL, UART_readchar, NULL},
{1, "stdout", &uart_if[0], NULL, NULL, NULL, UART_writechar},
{2, "stderr", &uart_if[0], NULL, NULL, NULL, UART_writechar},
{3, "UART-0", &uart_if[0], NULL, NULL, UART_readchar, UART_writechar},
{4, "UART-1", &uart_if[1], NULL, NULL, UART_readchar, UART_writechar}
};
const con_if_t con_if =
{
con_if_entry, ARRAYSIZE(con_if_entry)
};
void board_init(void)
{
uint32_t volatile *pITIM_ctrl = (uint32_t*)SYS_ITIM_CTRL;
// Disable interrupts
interrupt_global_disable();
// Disable timers
*pITIM_ctrl = 0;
// Setup syscall support
syscalls_init();
// Setup debugger
debugger_init();
// Setup interrupt support
interrupt_init();
// Enable interrupts
interrupt_global_enable();
}
void dbg_putchar(char c)
{
if (c == 0x0A)
{
UART_writechar(&uart_if[UART_DEBUGGER], 0x0D);
}
UART_writechar(&uart_if[UART_DEBUGGER], c);
}
char dbg_getchar()
{
int c;
// busy read
do
{
c = UART_readchar(&uart_if[UART_DEBUGGER]);
} while(c < 0);
return (char)c;
}
+257
View File
@@ -0,0 +1,257 @@
/*
* 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 0
// ---------------------------------------------------------
// IRQs
// ---------------------------------------------------------
#define SYS_INT_TIMER 7
#define SYS_INT_PS2 6
#define SYS_INT_EMAC 6
#define SYS_INT_VGA 5
#define SYS_INT_AC97 5
#define SYS_INT_USB 4
#define SYS_INT_UART 3
#define SYS_INT_DBG 2
#define SYS_INT_SOFT_1 1
#define SYS_INT_SOFT_0 0
// ---------------------------------------------------------
// 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 0x000001FF
#define GPIO_0_ALIGN_LED 0
#define GPIO_0_MASK_USB 0x00000003
#define GPIO_0_ALIGN_USB 12
#define GPIO_0_USB_RST 0x00000001
#define GPIO_0_USB_INTEN 0x00000002
#define GPIO_0_MASK_AC97 0x00000001
#define GPIO_0_ALIGN_AC97 15
#define GPIO_0_AC97_INTEN 0x00000001
#define GPIO_0_MASK_DIP 0x000000FF
#define GPIO_0_ALIGN_DIP 16
#define GPIO_0_MASK_BTN 0x0000001F
#define GPIO_0_ALIGN_BTN 24
#define GPIO_0_MASK_MDIO 0x00000007
#define GPIO_0_ALIGN_MDIO 29
#define GPIO_0_MDIO_INTEN 0x00000001 // ToDo: better grouping
#define GPIO_0_MDIO_RST 0x00000001
#define GPIO_0_MDIO_MDC 0x00000002
#define GPIO_0_MDIO_MDIO 0x00000004
// 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 + 0x10100)
#define SYS_UART1_STAT (SYS_IO_BASE + 0x10104)
#define SYS_UART1_BAUD (SYS_IO_BASE + 0x10108)
// PS2s
#define SYS_PS2_BIT_TX_EMPTY 0x00000001
#define SYS_PS2_BIT_RX_AVAIL 0x00000004
#define SYS_PS2_BIT_PIN_CLOCK 0x00000008
#define SYS_PS2_BIT_PIN_DATA 0x00000010
#define SYS_PS2_BIT_TX_INTEN 0x00000020
#define SYS_PS2_BIT_RX_INTEN 0x00000040
#define SYS_PS2_BIT_TX_IRQ 0x00000100
#define SYS_PS2_BIT_RX_IRQ 0x00000200
#define SYS_PS2_BIT_RX_ERR_PAR 0x00000800
#define SYS_PS2_BIT_RX_ERR_FLAG 0x00008000
#define SYS_PS2_0_DATA (SYS_IO_BASE + 0x10200)
#define SYS_PS2_0_STAT (SYS_IO_BASE + 0x10204)
#define SYS_PS2_1_DATA (SYS_IO_BASE + 0x10300)
#define SYS_PS2_1_STAT (SYS_IO_BASE + 0x10304)
// USB
#define SYS_USB_DATA (SYS_IO_BASE + 0x20000)
#define SYS_USB_MBX (SYS_IO_BASE + 0x20004)
#define SYS_USB_ADDR (SYS_IO_BASE + 0x20008)
#define SYS_USB_STATUS (SYS_IO_BASE + 0x2000C)
// VGA
#define SYS_VGA_CTRL (SYS_IO_BASE + 0x30000) // R/W
#define SYS_VGA_BIT_CGRDY 0x00000001 // RO
#define SYS_VGA_BIT_MSTEN 0x00000002 // R/W
#define SYS_VGA_BIT_BUFCHG_INTEN 0x00000004 // RO
#define SYS_VGA_BIT_BUFCHG_FLAG 0x00000008 // RO
#define SYS_VGA_BIT_CLRSCR 0x00000010 // WO
#define SYS_VGA_BIT_CLRLINE 0x00000020 // WO
#define SYS_VGA_BIT_BLIT_REQ 0x00000100 // R/W
#define SYS_VGA_BIT_BLIT_BSY 0x00000100 // R/W
#define SYS_VGA_BIT_BLIT_FIN 0x00000200 // R/W
#define SYS_VGA_BIT_BLIT_FIN_ACK 0x00000200 // R/W
#define SYS_VGA_BIT_BLIT_FIN_INTEN 0x00000400 // R/W
#define SYS_VGA_BIT_BLIT_EMPTY 0x00000800 // R/W
#define SYS_VGA_BIT_BLIT_EMPTY_ACK 0x00000800 // R/W
#define SYS_VGA_BIT_BLIT_EMPTY_INTEN 0x00001000 // R/W
#define SYS_VGA_BIT_BLIT_OP_CONSTCOL 0x00010000 // R/W
#define SYS_VGA_BIT_BLIT_ACTIVE 0x80000000 // RO
#define SYS_VGA_ASCII (SYS_IO_BASE + 0x30004) // R/W
#define SYS_VGA_POSX (SYS_IO_BASE + 0x30008) // R/W
#define SYS_VGA_POSY (SYS_IO_BASE + 0x3000C) // R/W
#define SYS_VGA_CGCOL (SYS_IO_BASE + 0x30010) // R/W
#define SYS_VGA_RES (SYS_IO_BASE + 0x30014) // RO
#define SYS_VGA_FB_FRONT (SYS_IO_BASE + 0x30018) // R/W
#define SYS_VGA_FB_BACK (SYS_IO_BASE + 0x3001C) // R/W
#define SYS_VGA_BLIT_SRC0_ADDR (SYS_IO_BASE + 0x30020) // R/W
#define SYS_VGA_BLIT_SRC0_DIMX (SYS_IO_BASE + 0x30024) // R/W
#define SYS_VGA_BLIT_SRC1_ADDR (SYS_IO_BASE + 0x30030) // R/W
#define SYS_VGA_BLIT_SRC1_DIMX (SYS_IO_BASE + 0x30034) // R/W
#define SYS_VGA_BLIT_DST_ADDR (SYS_IO_BASE + 0x30040) // R/W
#define SYS_VGA_BLIT_DST_DIMX (SYS_IO_BASE + 0x30044) // R/W
#define SYS_VGA_BLIT_NX (SYS_IO_BASE + 0x30050) // R/W
#define SYS_VGA_BLIT_NY (SYS_IO_BASE + 0x30054) // R/W
#define SYS_VGA_BLIT_COLOR (SYS_IO_BASE + 0x30058) // R/W
// AC'97
#define SYS_AC97_STAT (SYS_IO_BASE + 0x40000)
#define SYS_AC97_CTRL (SYS_IO_BASE + 0x40000)
#define SYS_AC97_ACSTAT (SYS_IO_BASE + 0x40400)
#define SYS_AC97_ACCTRL (SYS_IO_BASE + 0x40600)
#define SYS_AC97_PCM (SYS_IO_BASE + 0x40800)
#define SYS_AC97_WAVIN SYS_AC97_PCM
#define SYS_AC97_WAVOUT SYS_AC97_PCM
// Ethernet MAC
#define SYS_EMAC_RX_CTRL (SYS_IO_BASE + 0x50000)
#define EMAC_RX_CTRL_RESET (1 << 31)
#define EMAC_RX_CTRL_GIGABIT (1 << 30)
#define EMAC_RX_CTRL_FCS_CHECK (1 << 29)
#define EMAC_RX_CTRL_PROMISCIOUS (1 << 23)
#define EMAC_RX_CTRL_PKT_REQ (1 << 17)
#define EMAC_RX_CTRL_PKT_FREE (1 << 16)
#define EMAC_RX_CTRL_INTEN (1 << 4)
#define SYS_EMAC_RX_STAT SYS_EMAC_RX_CTRL
#define EMAC_RX_STAT_RESET (1 << 31)
#define EMAC_RX_STAT_GIGABIT (1 << 30)
#define EMAC_RX_STAT_FCS_CHECK (1 << 29)
#define EMAC_RX_STAT_PROMISCIOUS (1 << 23)
#define EMAC_RX_STAT_PKT_BCAST (1 << 19)
#define EMAC_RX_STAT_PKT_MACOK (1 << 18)
#define EMAC_RX_STAT_PKT_VALID (1 << 17)
#define EMAC_RX_STAT_PKT_AVAIL (1 << 16)
#define EMAC_RX_STAT_INTEN (1 << 4)
#define SYS_EMAC_RX_SIZE (SYS_IO_BASE + 0x50004)
#define SYS_EMAC_TX_CTRL (SYS_IO_BASE + 0x50008)
#define EMAC_TX_CTRL_RESET (1 << 31)
#define EMAC_TX_CTRL_GIGABIT (1 << 30)
#define EMAC_TX_CTRL_FCS_APPEND (1 << 29)
#define EMAC_TX_CTRL_PKT_ALLOC (1 << 17)
#define EMAC_TX_CTRL_PKT_COMMIT (1 << 16)
#define EMAC_TX_CTRL_INTEN (1 << 4)
#define SYS_EMAC_TX_STAT SYS_EMAC_TX_CTRL
#define EMAC_TX_STAT_RESET (1 << 31)
#define EMAC_TX_STAT_GIGABIT (1 << 30)
#define EMAC_TX_STAT_FCS_APPEND (1 << 29)
#define EMAC_TX_STAT_PKT_DONE (1 << 24)
#define EMAC_TX_STAT_PKT_ALLOC_BSY (1 << 17)
#define EMAC_TX_STAT_PKT_ARMED (1 << 16)
#define EMAC_TX_STAT_INTEN (1 << 4)
#define SYS_EMAC_TX_SIZE (SYS_IO_BASE + 0x5000C)
#define SYS_EMAC_MADDR (SYS_IO_BASE + 0x50018)
#define SYS_EMAC_MADDR_0 SYS_EMAC_MADDR_0
#define SYS_EMAC_MADDR_1 (SYS_IO_BASE + 0x5001C)
#define SYS_EMAC_DATA (SYS_IO_BASE + 0x58000)
#define SYS_EMAC_RX_DATA SYS_EMAC_DATA
#define SYS_EMAC_TX_DATA SYS_EMAC_DATA
#define SYS_EMAC_DATA_CACHED (SYS_IO_BASE + 0x10008000)
// Sync. SRAM
#define SYS_SSRAM_IO 0xA8000000
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H */
+63
View File
@@ -0,0 +1,63 @@
/*
* 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 <stddef.h>
#include "board.h"
#include "../../irq.h"
#include "../../uart.h"
#include "../../console.h"
#include "../../asm/regdef.h"
#include "../../syscalls.h"
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
// ---------------------------------------------------------------------------------
// Uart
// ---------------------------------------------------------------------------------
const uart_if_t uart_if[] =
{
{(uint32_t*)SYS_UART0_STAT, (uint32_t*)SYS_UART0_DATA, (uint32_t*)SYS_UART0_BAUD},
{(uint32_t*)SYS_UART1_STAT, (uint32_t*)SYS_UART1_DATA, (uint32_t*)SYS_UART1_BAUD}
};
// ---------------------------------------------------------------------------------
// Console
// ---------------------------------------------------------------------------------
const con_if_entry_t con_if_entry[] =
{
{0, "stdin", &uart_if[0], NULL, NULL, UART_readchar, NULL},
{1, "stdout", &uart_if[0], NULL, NULL, NULL, UART_writechar},
{2, "stderr", &uart_if[0], NULL, NULL, NULL, UART_writechar},
{3, "UART-0", &uart_if[0], NULL, NULL, UART_readchar, UART_writechar},
{4, "UART-1", &uart_if[1], NULL, NULL, UART_readchar, UART_writechar}
};
const con_if_t con_if =
{
con_if_entry, ARRAYSIZE(con_if_entry)
};
void board_init(void)
{
uint32_t volatile *pITIM_ctrl = (uint32_t*)SYS_ITIM_CTRL;
// Disable interrupts
interrupt_global_disable();
// Disable timers
*pITIM_ctrl = 0;
// Setup syscall support
syscalls_init();
// Setup interrupt support
interrupt_init();
// Enable interrupts
interrupt_global_enable();
}
+139
View File
@@ -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 */
+141
View File
@@ -0,0 +1,141 @@
/*
* 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 <assert.h>
#include <stddef.h>
#include <string.h>
#include "console.h"
extern const con_if_t con_if;
// Funcs
con_if_entry_t const* con_getInterface(int file)
{
con_if_entry_t const *result = NULL;
for (int i=0; i < con_if.length; i++)
{
if (file == con_if.con_if_entry[i].fd)
{
result = &con_if.con_if_entry[i];
break;
}
}
return result;
}
con_if_entry_t const* con_getInterfaceByName(char const *pName)
{
void const *result = NULL;
for (int i=0; i < con_if.length; i++)
{
if (!strcmp(pName, con_if.con_if_entry[i].pName))
{
result = &con_if.con_if_entry[i];
break;
}
}
return result;
}
void const* con_getInstanceByName(char const *pName)
{
void const *result = NULL;
for (int i=0; i < con_if.length; i++)
{
if (!strcmp(pName, con_if.con_if_entry[i].pName))
{
result = con_if.con_if_entry[i].pInst;
break;
}
}
return result;
}
int con_open(char const *pName)
{
if(pName)
{
for (int i=0; i < con_if.length; i++)
{
if (!strcmp(pName, con_if.con_if_entry->pName))
{
if (con_if.con_if_entry->openFunc)
{
con_if.con_if_entry->openFunc(&con_if.con_if_entry[i].pInst);
return i;
}
}
}
}
return -1;
}
int con_close(int fd)
{
}
void con_flush(int fd)
{
int c;
con_if_entry_t const *pIF = con_getInterface(fd);
if (pIF && pIF->readchar)
{
do
{
c = pIF->readchar(pIF->pInst);
} while(c > 0);
}
}
int con_readchar(con_if_entry_t const *pIF)
{
int c = -1;
if (pIF && pIF->readchar)
{
// busy read
do
{
c = pIF->readchar(pIF->pInst);
} while(c < 0);
}
return c;
}
void con_writechar(con_if_entry_t const *pIF, char c)
{
if (pIF && pIF->writechar)
{
pIF->writechar(pIF->pInst, c);
}
}
// ---------------------------------------------------------------------------------
int readchar(int fd)
{
return con_readchar(con_getInterface(fd));
}
void writechar(int fd, char c)
{
con_writechar(con_getInterface(fd), c);
}
void _putchar(int fd, char c)
{
if (c == 0x0A)
{
writechar(fd, 0x0D);
}
writechar(fd, c);
}
char _getchar()
{
return readchar(0);
}
+68
View File
@@ -0,0 +1,68 @@
/*
* 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: console.h
* Author: jens
*
* Created on 8. Januar 2017, 14:25
*/
#ifndef CONSOLE_H
#define CONSOLE_H
#include <stddef.h>
#include <stdint.h>
typedef int (*read_func_t)(void const *pInst);
typedef void (*write_func_t)(void const *pInst, char c);
typedef void (*open_func_t)(void const *pInst);
typedef void (*close_func_t)(void const *pInst);
typedef struct _scon_if_entry_t
{
int fd;
char const *pName;
void const *pInst;
open_func_t openFunc;
close_func_t closeFunc;
read_func_t readchar;
write_func_t writechar;
} con_if_entry_t;
typedef struct _scon_if_t
{
con_if_entry_t const *con_if_entry;
size_t length;
} con_if_t;
#ifdef __cplusplus
extern "C" {
#endif
// ---------------------------------------------------------------------------------
// Forward declarations
// ---------------------------------------------------------------------------------
int con_open(char const *pName);
int con_close(int fd);
void con_flush(int file);
con_if_entry_t const* con_getInterface(int file);
con_if_entry_t const* con_getInterfaceByName(char const *pName);
void const* con_getInstanceByName(char const *pName);
int con_readchar(con_if_entry_t const *pIF);
void con_writechar(con_if_entry_t const *pIF, char c);
int readchar(int file);
void writechar(int file, char c);
char _getchar();
void _putchar(int file, char c);
#ifdef __cplusplus
}
#endif
#endif /* CONSOLE_H */
+150
View File
@@ -0,0 +1,150 @@
/*
* 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 "cop0.h"
// ---------------------------------------------------------------------------------
// MIPS specific
// ---------------------------------------------------------------------------------
uint32_t CP0_SR_read(void)
{
uint32_t result;
__asm__
(
"mfc0 %[val], $12\n"
: [val] "=r" (result)
);
return result;
}
void CP0_SR_write(uint32_t val)
{
__asm__
(
"mtc0 %[val], $12\n"
: /* no output */
: [val] "r" (val)
);
}
uint32_t CP0_CR_read(void)
{
uint32_t result;
__asm__
(
"mfc0 %[val], $13\n"
: [val] "=r" (result)
);
return result;
}
void CP0_CR_write(uint32_t val)
{
__asm__
(
"mtc0 %[val], $13\n"
:
: [val] "r" (val)
);
}
uint32_t CP0_TR_read(void)
{
uint32_t result;
__asm__
(
"mfc0 %[val], $31\n"
: [val] "=r" (result)
);
return result;
}
void CP0_TR_write(uint32_t val)
{
__asm__
(
"mtc0 %[val], $31\n"
:
: [val] "r" (val)
);
}
uint32_t CP0_PRID_read(void)
{
uint32_t result;
__asm__
(
"mfc0 %[val], $15\n"
: [val] "=r" (result)
);
return result;
}
void CP0_TR_write_ptr(uint32_t* pPtr)
{
__asm__
(
"swc0 $31, 0(%[pPtr])\n"
:
: [pPtr] "r" (pPtr)
);
}
void CP0_TR_read_ptr(uint32_t* pPtr)
{
__asm__
(
"lwc0 $31, 0(%[pPtr])\n"
:
: [pPtr] "r" (pPtr)
);
}
void ICACHE_invalidate_all(void)
{
__asm__
(
"cop0 32\n"
);
}
void ICACHE_invalidate_at(uint32_t* pPtr)
{
__asm__
(
"mtc0 %[pPtr], $31\n"
"cop0 33\n"
:
: [pPtr] "r" (pPtr)
);
}
void DCACHE_invalidate_all(void)
{
__asm__
(
"cop0 34\n"
);
}
void DCACHE_invalidate_at(uint32_t* pPtr)
{
__asm__
(
"mtc0 %[pPtr], $31\n"
"cop0 35\n"
:
: [pPtr] "r" (pPtr)
);
}
+96
View File
@@ -0,0 +1,96 @@
/*
* 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: cop0.h
* Author: jens
*
* Created on 12. Januar 2017, 16:07
*/
#ifndef COP0_H
#define COP0_H
#include <stdint.h>
// ---------------------------------------------------------
// Chip registers
// ---------------------------------------------------------
// COP0 registers
#define COP0_REG_INVAT_POINTER 31
// COP0 instructions
#define COP0_INSTR_INVALL_ICACHE 32
#define COP0_INSTR_INVAT_ICACHE 33
#define COP0_INSTR_INVALL_DCACHE 34
#define COP0_INSTR_INVAT_DCACHE 35
#define CP0_read(idx) \
({ \
uint32_t result; \
__asm__ __volatile__ \
( \
"mfc0\t%0,$"#idx"\n" \
: "=r" (result) \
); \
result; \
})
#define CP0_write(idx, val) \
({ \
__asm__ __volatile__ \
( \
"mtc0\t%0,$"#idx"\n" \
"nop\n" \
: /* no output */ \
: "r" (val) \
); \
})
#define CP0_TLBR \
({ \
__asm__ __volatile__ \
( \
"tlbr\n" \
: /* no output */ \
: /* no input */ \
); \
})
#define CP0_TLBWI \
({ \
__asm__ __volatile__ \
( \
"tlbwi\n" \
: /* no output */ \
: /* no input */ \
); \
})
#ifdef __cplusplus
extern "C" {
#endif
uint32_t CP0_SR_read(void);
void CP0_SR_write(uint32_t val);
uint32_t CP0_CR_read(void);
void CP0_CR_write(uint32_t val);
uint32_t CP0_PRID_read(void);
uint32_t CP0_TR_read(void);
void CP0_TR_write(uint32_t val);
void CP0_TR_write_ptr(uint32_t* pPtr);
void CP0_TR_read_ptr(uint32_t* pPtr);
void ICACHE_invalidate_all(void);
void ICACHE_invalidate_at(uint32_t* pPtr);
void DCACHE_invalidate_all(void);
void DCACHE_invalidate_at(uint32_t* pPtr);
#ifdef __cplusplus
}
#endif
#endif /* COP0_H */
+642
View File
@@ -0,0 +1,642 @@
/****************************************************************************
THIS SOFTWARE IS NOT COPYRIGHTED
HP offers the following for use in the public domain. HP makes no
warranty with regard to the software or it's performance and the
user accepts the software "AS IS" with all faults.
HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
****************************************************************************/
/****************************************************************************
* Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
*
* Module name: remcom.c $
* Revision: 1.34 $
* Date: 91/03/09 12:29:49 $
* Contributor: Lake Stevens Instrument Division$
*
* Description: low level support for gdb debugger. $
*
* Considerations: only works on target hardware $
*
* Written by: Glenn Engel $
* ModuleState: Experimental $
*
* NOTES: See Below $
*
* Modified for SPARC by Stu Grossman, Cygnus Support.
*
* This code has been extensively tested on the Fujitsu SPARClite demo board.
*
* To enable debugger support, two things need to happen. One, a
* call to set_debug_traps() is necessary in order to allow any breakpoints
* or error conditions to be properly intercepted and reported to gdb.
* Two, a breakpoint needs to be generated to begin communication. This
* is most easily accomplished by a call to breakpoint(). Breakpoint()
* simulates a breakpoint by executing a trap #1.
*
*************
*
* The following gdb commands are supported:
*
* command function Return value
*
* g return the value of the CPU registers hex data or ENN
* G set the value of the CPU registers OK or ENN
*
* mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
* MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
*
* c Resume at current address SNN ( signal NN)
* cAA..AA Continue at address AA..AA SNN
*
* s Step one instruction SNN
* sAA..AA Step one instruction from AA..AA SNN
*
* k kill
*
* ? What was the last sigval ? SNN (signal NN)
*
* All commands and responses are sent with a packet which includes a
* checksum. A packet consists of
*
* $<packet info>#<checksum>.
*
* where
* <packet info> :: <characters representing the command or response>
* <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
*
* When a packet is received, it is first acknowledged with either '+' or '-'.
* '+' indicates a successful transfer. '-' indicates a failed transfer.
*
* Example:
*
* Host: Reply:
* $m0,10#2a +$00010203040506070809101112131415#42
*
****************************************************************************/
#include <string.h>
#include <signal.h>
/************************************************************************
*
* external low-level support routines
*/
extern void dbg_putchar(char c); /* write a single character */
extern char dbg_getchar(); /* read and return a single char */
extern void ICACHE_invalidate_all();
extern int sputs(char const *pStr);
extern void print_byte(char byte);
extern void print_word(int word);
void putDebugChar(char c)
{
dbg_putchar(c);
}
int getDebugChar()
{
return (int)dbg_getchar();
}
void flush_i_cache()
{
ICACHE_invalidate_all();
}
void dbg_strcpy(char *pDst, const char *pSrc)
{
while(*pSrc)
{
*(pDst++) = *(pSrc++);
}
*pDst = *pSrc;
}
void* dbg_memset(void *pDst, int value, size_t size)
{
char *dst = (char*)pDst;
while(size)
{
*(dst++) = (char)value;
size--;
}
return (void*)dst;
}
void* dbg_memcpy(void *pDst, const void *pSrc, size_t size )
{
char *dst = (char*)pDst;
char *src = (char*)pSrc;
while(size)
{
*(dst++) = *(src++);
size--;
}
return (void*)dst;
}
/************************************************************************/
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
/* at least NUMREGBYTES*2 are needed for register packets */
#define BUFMAX 2048
const char hexchars[]="0123456789abcdef";
#define NUMREGS 72
/* Number of bytes of registers. */
#define NUMREGBYTES (NUMREGS * 4)
enum regnames
{
START_CPU_REGS = 0,
SR = START_CPU_REGS,
CR,
PC,
BV,
R00,
R01,
R02,
R03,
R04,
R05,
R06,
R07,
R08,
R09,
R10,
R11,
R12,
R13,
R14,
R15,
R16,
R17,
R18,
R19,
R20,
R21,
R22,
R23,
R24,
R25,
R26,
R27,
R28,
R29,
R30,
R31,
LO,
HI,
NUM_REGS
};
/* Convert ch from a hex digit to an int */
static int
hex (unsigned char ch)
{
if (ch >= 'a' && ch <= 'f')
return ch-'a'+10;
if (ch >= '0' && ch <= '9')
return ch-'0';
if (ch >= 'A' && ch <= 'F')
return ch-'A'+10;
return -1;
}
/* scan for the sequence $<data>#<checksum> */
unsigned char *
getpacket (unsigned char *buffer)
{
unsigned char checksum;
unsigned char xmitcsum;
int count;
char ch;
while (1)
{
/* wait around for the start character, ignore all other characters */
while ((ch = getDebugChar ()) != '$')
;
retry:
checksum = 0;
xmitcsum = -1;
count = 0;
/* now, read until a # or end of buffer is found */
while (count < BUFMAX - 1)
{
ch = getDebugChar ();
if (ch == '$')
goto retry;
if (ch == '#')
break;
checksum = checksum + ch;
buffer[count] = ch;
count = count + 1;
}
buffer[count] = 0;
if (ch == '#')
{
ch = getDebugChar ();
xmitcsum = hex (ch) << 4;
ch = getDebugChar ();
xmitcsum += hex (ch);
#ifdef WITH_CHECKSUM_CHECK
if (checksum != xmitcsum)
{
putDebugChar ('-'); /* failed checksum */
}
else
#endif
{
putDebugChar ('+'); /* successful transfer */
/* if a sequence char is present, reply the sequence ID */
if (buffer[2] == ':')
{
putDebugChar (buffer[0]);
putDebugChar (buffer[1]);
return &buffer[3];
}
return &buffer[0];
}
}
}
}
/* send the packet in buffer. */
static void
putpacket (unsigned char *buffer)
{
unsigned char checksum;
int count;
unsigned char ch;
/* $<packet info>#<checksum>. */
do
{
putDebugChar('$');
checksum = 0;
count = 0;
while (ch = buffer[count])
{
putDebugChar(ch);
checksum += ch;
count += 1;
}
putDebugChar('#');
putDebugChar(hexchars[checksum >> 4]);
putDebugChar(hexchars[checksum & 0xf]);
} while (getDebugChar() != '+');
}
/* Indicate to caller of mem2hex or hex2mem that there has been an
error. */
const int mem_err = 0;
/* Convert the memory pointed to by mem into hex, placing result in buf.
* Return a pointer to the last char put in buf (null), in case of mem fault,
* return 0.
* If MAY_FAULT is non-zero, then we will handle memory faults by returning
* a 0, else treat a fault like any other fault in the stub.
*/
static unsigned char *
mem2hex (unsigned char *mem, unsigned char *buf, int count, int may_fault)
{
unsigned char ch;
while (count-- > 0)
{
ch = *mem++;
if (mem_err)
return 0;
*buf++ = hexchars[ch >> 4];
*buf++ = hexchars[ch & 0xf];
}
*buf = 0;
return buf;
}
/* convert the hex array pointed to by buf into binary to be placed in mem
* return a pointer to the character AFTER the last byte written */
static char *
hex2mem (unsigned char *buf, unsigned char *mem, int count, int may_fault)
{
int i;
unsigned char ch;
for (i=0; i<count; i++)
{
ch = hex(*buf++) << 4;
ch |= hex(*buf++);
*mem++ = ch;
if (mem_err)
return 0;
}
return mem;
}
/* This table contains the mapping between SPARC hardware trap types, and
signals, which are primarily what GDB understands. It also indicates
which hardware traps we need to commandeer when initializing the stub. */
struct hard_trap_info_t
{
unsigned long tt; /* Trap type code for SPARClite */
unsigned long signo; /* Signal that we map this trap into */
};
const struct hard_trap_info_t hard_trap_info[] =
{
{0, SIGINT}, /* Interrupt (Int) */
{1, SIGSEGV}, /* TLB modification (Mod) */
{2, SIGSEGV}, /* TLB load (TLBL) */
{3, SIGSEGV}, /* TLB store (TLBS) */
{4, SIGSEGV}, /* Address error load (ADEL) */
{5, SIGSEGV}, /* Address error store (ADES) */
{6, SIGBUS}, /* Bus error on instruction (IBE) */
{7, SIGBUS}, /* Bus error on data (DBE) */
{8, SIGUSR1}, /* Syscall instruction called (Syscall) */
{9, SIGTRAP}, /* Breakpoint instruction called (Breakpoint) */
{10, SIGILL}, /* Reserved instruction (RI) */
{11, SIGXCPU}, /* Coprocessor unusable (CpU) */
{12, SIGFPE}, /* Arithmetic overflow (Ov) */
{0, 0} /* Must be last */
};
/* Convert the SPARC hardware trap type code to a unix signal number. */
static unsigned long
computeSignal (unsigned long tt)
{
// Determine linux signal from CPU specific exception code
struct hard_trap_info_t *ht;
for (ht = (struct hard_trap_info_t *)hard_trap_info; ht->signo != 0; ht++)
{
if (ht->tt == tt)
{
return ht->signo;
}
}
return SIGHUP; /* default for things we don't know about */
}
/*
* While we find nice hex chars, build an int.
* Return number of chars processed.
*/
static int
hexToInt(char **ptr, unsigned long *intValue)
{
unsigned long numChars = 0;
int hexValue;
*intValue = 0;
while (**ptr)
{
hexValue = hex(**ptr);
if (hexValue < 0)
break;
*intValue = (*intValue << 4) | hexValue;
numChars ++;
(*ptr)++;
}
return (numChars);
}
int isBreak(unsigned long instr)
{
return ((instr & 0xFC00003F) == 0x0000000D);
}
/*
* This function does all command procesing for interfacing to gdb. It
* returns 1 if you should skip the instruction at the trap address, 0
* otherwise.
*/
void
handle_exception (unsigned long *registers)
{
char remcomInBuffer[BUFMAX];
char remcomOutBuffer[BUFMAX];
sputs("Entry\n");
unsigned long tt; /* Trap type */
unsigned long sigval;
unsigned long addr;
unsigned long length;
char *ptr;
unsigned long *sp;
addr = *((unsigned long *)registers[PC]);
// is break
if (isBreak(addr))
{
registers[PC] += 4;
}
sp = (unsigned long *)&registers[R29];
tt = (registers[CR] >> 2) & 0x1f;
/* reply to host that an exception has occurred */
sigval = computeSignal(tt);
ptr = remcomOutBuffer;
*ptr++ = 'T';
*ptr++ = hexchars[sigval >> 4];
*ptr++ = hexchars[sigval & 0xf];
*ptr++ = hexchars[37 >> 4];
*ptr++ = hexchars[37 & 0xf];
*ptr++ = ':';
ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
*ptr++ = ';';
*ptr++ = hexchars[29 >> 4];
*ptr++ = hexchars[29 & 0xf];
*ptr++ = ':';
ptr = mem2hex((char *)sp, ptr, 4, 0);
*ptr++ = ';';
*ptr++ = 0;
putpacket(remcomOutBuffer);
while (1)
{
remcomOutBuffer[0] = 0;
ptr = getpacket(remcomInBuffer);
switch (*ptr++)
{
case '?':
sputs("?\n");
remcomOutBuffer[0] = 'S';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval & 0xf];
remcomOutBuffer[3] = 0;
break;
case 'd': /* toggle debug flag */
sputs("d\n");
break;
case 'g': /* return the value of the CPU registers */
{
sputs("g\n");
ptr = remcomOutBuffer;
/* R00 .. R31 */
ptr = mem2hex((char *)&registers[R00], ptr, 4*32, 0);
/* SR, HI, LO, BADVADDR, CR, PC */
ptr = mem2hex((char *)&registers[SR], ptr, 4, 0);
ptr = mem2hex((char *)&registers[HI], ptr, 4, 0);
ptr = mem2hex((char *)&registers[LO], ptr, 4, 0);
ptr = mem2hex((char *)&registers[BV], ptr, 4, 0);
ptr = mem2hex((char *)&registers[CR], ptr, 4, 0);
ptr = mem2hex((char *)&registers[PC], ptr, 4, 0);
/* Floating point F00 .. F31*/
dbg_memset(ptr, '0', 8 * 32);
ptr += 8*32;
/* FCSR, FIR, RESTART*/
dbg_memset(ptr, '0', 8 * 3);
ptr += 8*3;
*ptr = 0;
}
break;
case 'G': /* set the value of the CPU registers - return OK */
{
sputs("G\n");
unsigned long *newsp, sr;
sr = registers[SR];
hex2mem(ptr, (char *)&registers[R00], 4*32, 0); /* R00 .. R31 */
ptr += 4*32 * 2;
/* SR, HI, LO, BADVADDR, CR, PC */
hex2mem(ptr, (char *)&registers[SR], 4, 0);
ptr += 4 * 2;
hex2mem(ptr, (char *)&registers[HI], 4, 0);
ptr += 4 * 2;
hex2mem(ptr, (char *)&registers[LO], 4, 0);
ptr += 4 * 2;
hex2mem(ptr, (char *)&registers[BV], 4, 0);
ptr += 4 * 2;
hex2mem(ptr, (char *)&registers[CR], 4, 0);
ptr += 4 * 2;
hex2mem(ptr, (char *)&registers[PC], 4, 0);
ptr += 4 * 2;
*ptr = 0;
dbg_strcpy(remcomOutBuffer,"OK");
}
break;
case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
sputs("m\n");
/* Try to read %x,%x. */
if (hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length))
{
if (mem2hex((char *)addr, remcomOutBuffer, length, 1))
{
break;
}
dbg_strcpy (remcomOutBuffer, "E03");
}
else
{
dbg_strcpy(remcomOutBuffer,"E01");
}
sputs("m:"); print_word(addr); sputs(",");print_word(length); sputs("\n");
break;
case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
/* Try to read '%x,%x:'. */
if (hexToInt(&ptr, &addr) && *ptr++ == ',' && hexToInt(&ptr, &length) && *ptr++ == ':')
{
if (hex2mem(ptr, (char *)addr, length, 1))
{
dbg_strcpy(remcomOutBuffer, "OK");
}
else
{
dbg_strcpy(remcomOutBuffer, "E03");
}
}
else
{
dbg_strcpy(remcomOutBuffer, "E02");
}
sputs("M:"); print_word(addr); sputs(",");print_word(length); sputs("\n");
break;
case 'c': /* cAA..AA Continue at address AA..AA(optional) */
/* try to read optional parameter, pc unchanged if no parm */
sputs("c: PC="); print_word(registers[PC]);sputs("\n");
if (hexToInt(&ptr, &addr))
{
registers[PC] = addr;
sputs("c: addr="); print_word(addr);sputs("\n");
}
/* Need to flush the instruction cache here, as we may have deposited a
breakpoint, and the icache probably has no way of knowing that a data ref to
some location may have changed something that is in the instruction cache.
*/
flush_i_cache();
return;
/* kill the program */
case 'k' : /* do nothing */
sputs("Kill\n");
break;
#if 0
case 't': /* Test feature */
break;
#endif
case 'r': /* Reset */
// Perform reset
sputs("Reset\n");
break;
} /* switch */
/* reply to the request */
putpacket(remcomOutBuffer);
}
sputs("Exit\n");
}
+34
View File
@@ -0,0 +1,34 @@
#include "libsys.h"
#include "gpio.h"
// ---------------------------------------------------------
void gpio_init(gpio_if_t *pObj, uint32_t base_addr, uint32_t mask, uint32_t shift)
{
pObj->pBase = (uint32_t*)base_addr;
pObj->mask = mask;
pObj->mask_shifted = mask << shift;
pObj->shift = shift;
}
void gpio_write(gpio_if_t *pObj, uint32_t value)
{
*pObj->pBase = (value & pObj->mask) << pObj->shift;
}
uint32_t gpio_read(gpio_if_t *pObj)
{
uint32_t result = (*pObj->pBase >> pObj->shift) & pObj->mask;
return result;
}
void gpio_set(gpio_if_t *pObj, uint32_t value)
{
*pObj->pBase |= (value & pObj->mask) << pObj->shift;
}
void gpio_clr(gpio_if_t *pObj, uint32_t value)
{
*pObj->pBase &= ~((value | pObj->mask) << pObj->shift);
}
// ---------------------------------------------------------
+24
View File
@@ -0,0 +1,24 @@
#ifndef GPIO_H
#define GPIO_H
// ---------------------------------------------------------
// Types
// ---------------------------------------------------------
typedef struct _sgpio_if_t
{
volatile uint32_t *pBase;
volatile uint32_t mask;
volatile uint32_t mask_shifted;
volatile uint32_t shift;
} gpio_if_t;
void gpio_init(gpio_if_t *pObj, uint32_t base_addr, uint32_t mask, uint32_t shift);
void gpio_write(gpio_if_t *pObj, uint32_t value);
uint32_t gpio_read(gpio_if_t *pObj);
void gpio_set(gpio_if_t *pObj, uint32_t value);
void gpio_clr(gpio_if_t *pObj, uint32_t value);
#endif // GPIO_H
+107
View File
@@ -0,0 +1,107 @@
#include <stddef.h>
#include <stdint.h>
#include "asm/regdef.h"
#include "xcpt.h"
#include "irq.h"
#include <cop0.h>
static fp_irq_t g_irq_handler[MAX_NUM_IRQ] = {NULL};
int _irq_dispatch(struct xcptcontext * xcp)
{
int i, ip, cause;
cause = xcp->cr & xcp->sr;
ip = (cause >> 8) & 0xFF;
for (i=0; i < MAX_NUM_IRQ; i++)
{
if (ip & 1)
if (g_irq_handler[i])
(g_irq_handler[i])(xcp);
ip >>= 1;
}
return 0;
}
void interrupt_register(int irq_num, fp_irq_t fp)
{
if ((irq_num >= 0) && (irq_num < MAX_NUM_IRQ))
g_irq_handler[irq_num] = fp;
}
void interrupt_enable(int irq_num)
{
reg_t reg, im;
if ((irq_num >= 0) && (irq_num < MAX_NUM_IRQ))
{
im = 1 << irq_num;
reg = CP0_SR_read();
reg |= (SR_MASK_IM & (im << 8));
CP0_SR_write(reg);
}
}
void interrupt_disable(int irq_num)
{
reg_t reg, im;
if ((irq_num >= 0) && (irq_num < MAX_NUM_IRQ))
{
im = 1 << irq_num;
reg = CP0_SR_read();
reg &= ~(SR_MASK_IM & (im << 8));
CP0_SR_write(reg);
}
}
void interrupt_global_enable()
{
uint32_t reg = CP0_SR_read() | SR_MASK_IEC;
CP0_SR_write(reg);
}
void interrupt_global_disable()
{
uint32_t reg = CP0_SR_read() & ~SR_MASK_IEC;
CP0_SR_write(reg);
}
void interrupt_set(int irq_num)
{
reg_t reg, ip;
if ((irq_num >= 0) && (irq_num < MAX_NUM_IRQ))
{
ip = 1 << irq_num;
reg = CP0_CR_read();
reg |= (CR_MASK_IP & (ip << 8));
CP0_CR_write(reg);
}
}
void interrupt_clr(int irq_num)
{
reg_t reg, ip;
if ((irq_num >= 0) && (irq_num < MAX_NUM_IRQ))
{
ip = 1 << irq_num;
reg = CP0_CR_read();
reg &= ~(CR_MASK_IP & (ip << 8));
CP0_CR_write(reg);
}
}
void interrupt_init(void)
{
// register interrupt dispatcher
xcpt_register(EXC_INT, _irq_dispatch);
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef IRQ_H
#define IRQ_H
#include "xcpt.h"
#define MAX_NUM_IRQ 8
typedef void (*fp_irq_t)(struct xcptcontext * xcp);
void interrupt_init(void);
int _irq_dispatch(struct xcptcontext * xcp);
void interrupt_register(int irq_num, fp_irq_t fp);
void interrupt_enable(int irq_num);
void interrupt_disable(int irq_num);
void interrupt_global_enable();
void interrupt_global_disable();
void interrupt_set(int irq_num);
void interrupt_clr(int irq_num);
#endif // IRQ_H
+392
View File
@@ -0,0 +1,392 @@
#include <sys/times.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "libsys.h"
#include "asm/regdef.h"
static uint32_t critical_nesting_counter = 0;
void enter_critical()
{
if (critical_nesting_counter == 0)
{
interrupt_global_disable();
}
critical_nesting_counter++;
}
void exit_critical()
{
if (critical_nesting_counter > 0)
{
critical_nesting_counter--;
if (critical_nesting_counter == 0)
{
interrupt_global_enable();
}
}
}
void _exit (int exitcode)
{
fflush(stdout);
fflush(stderr);
while(1);
}
void sleep(unsigned ms)
{
unsigned stop;
struct tms t;
times(&t);
stop = t.tms_utime + ms;
do
{
times(&t);
} while (t.tms_utime < stop);
}
void usleep(unsigned us)
{
unsigned stop_us, stop_s, curr_us, curr_s;
struct timeval t;
if (!us)
return;
gettimeofday(&t, NULL);
stop_s = (unsigned)t.tv_sec;
stop_us = (unsigned)t.tv_usec + us;
if (stop_us >= 1E6)
{
stop_us -= 1E6;
stop_s++;
}
do
{
gettimeofday(&t, NULL);
curr_s = (unsigned)t.tv_sec;
curr_us = (unsigned)t.tv_usec;
} while ((curr_s < stop_s) || (curr_us < stop_us));
}
int getrusage(int who, struct rusage *usage)
{
volatile long *pReg_usec = (long*)SYS_TIMER_USEC;
volatile long *pReg_sec = (long*)SYS_TIMER_SEC;
// who: RUSAGE_SELF or RUSAGE_CHILDREN
usage->ru_utime.tv_usec = *pReg_usec;
usage->ru_utime.tv_sec = *pReg_sec;
usage->ru_stime.tv_usec = *pReg_usec;
usage->ru_stime.tv_sec = *pReg_sec;
}
clock_t times(struct tms *buffer)
{
volatile long *pReg_usec = (long*)SYS_TIMER_USEC;
volatile long *pReg_sec = (long*)SYS_TIMER_SEC;
long sec;
long usec;
sec = *pReg_sec;
usec = *pReg_usec;
if (buffer)
{
buffer->tms_utime = sec*1000 + usec/1000;
buffer->tms_stime = 0;
buffer->tms_cutime = 0;
buffer->tms_cstime = 0;
}
return (clock_t)sec;
}
int gettimeofday(struct timeval *tp, void *tzp)
{
volatile long *pReg_usec = (long*)SYS_TIMER_USEC;
volatile long *pReg_sec = (long*)SYS_TIMER_SEC;
if (tp)
{
tp->tv_sec = *pReg_sec;
tp->tv_usec = *pReg_usec;
}
return 0;
}
int settimeofday(const struct timeval *tp, const struct timezone *tzp)
{
volatile long *pReg_usec = (long*)SYS_TIMER_USEC;
volatile long *pReg_sec = (long*)SYS_TIMER_SEC;
div_t res;
res = div(tp->tv_usec, 1E6);
if (tp)
{
*pReg_usec = res.rem;
*pReg_sec = tp->tv_sec + res.quot;
}
return 0;
}
caddr_t sbrk(int incr)
{
extern char end;
extern char stack_ptr;
static char *heap_end;
char *prev_heap_end;
if (heap_end == 0)
{
heap_end = &end;
}
prev_heap_end = heap_end;
if (heap_end + incr > &stack_ptr)
{
// sputs("Heap and stack collision\n");
// sputs("Stack Ptr = ");print_word(&stack_ptr);sputs("\n");
// sputs("Heap end = ");print_word(heap_end);sputs("\n");
// sputs("Increment = ");print_word(incr);sputs("\n");
exit(1);
}
heap_end += incr;
return (caddr_t) prev_heap_end;
}
int fstat(int file, struct stat *st)
{
// sputs("fstat ("); print_word(file); sputs(")\n");
st->st_mode = S_IFCHR;
st->st_blksize = 0;
return 0;
}
int lseek(int file, int ptr, int dir)
{
// sputs("lseek ("); print_word(file); sputs(")\n");
errno = ESPIPE;
return -1;
}
int open(const char *name, int flags, int mode)
{
return con_open(name);
}
int close(int file)
{
return con_close(file);
}
int read(int file, char *ptr, int len)
{
int i;
char c;
int fd_out = file;
if (file == 0)
{
fd_out = 1;
}
i = 0;
while (i < len)
{
c = readchar(file);
if (c == 0x04)
break;
if ((c == 0x0D) || (c == 0x0A))
{
writechar(fd_out, 0x0D);
ptr[i++] = 0x0D;
writechar(fd_out, 0x0A);
ptr[i++] = 0x0A;
break;
}
writechar(fd_out, c);
ptr[i++] = c;
}
return i;
}
int write(int file, char *ptr, int len)
{
int i = 0;
// sputs("write ("); print_word(file); sputs(")\n");
for (i=0; i < len; i++)
_putchar(file, *ptr++);
return i;
}
int isatty(int file)
{
// sputs("isatty ("); print_word(file); sputs(")\n");
return 1;
}
int getpid(void)
{
return 1;
}
#include <errno.h>
#undef errno
extern int errno;
int kill(int pid, int sig)
{
errno = EINVAL;
return -1;
}
#include <errno.h>
#undef errno
extern int errno;
int link(char *old, char *new)
{
errno = EMLINK;
return -1;
}
#include <errno.h>
#undef errno
extern int errno;
int unlink(char *name)
{
errno = ENOENT;
return -1;
}
int sputs(char const *pStr)
{
char const *start = pStr;
while(*pStr)
_putchar(1, *(pStr++));
return pStr - start;
}
void print_byte(char byte)
{
int i;
unsigned char c, nibble;
for (i=0; i < 2; i++)
{
nibble = (char)((byte >> 4) & 0xF);
byte <<= 4;
if (nibble < 10)
c = nibble + '0';
else
c = nibble + 'A' - 10;
_putchar(1, c);
}
}
void print_word(int word)
{
int i;
unsigned char c, nibble;
for (i=0; i < 4; i++)
{
c = (char) (word >> 24);
print_byte(c);
word <<= 8;
}
}
// ---------------------------------------------------------------------------------
// PrintBuffer8()
// Prints byte buffer as hex and ascii interpretation
// ---------------------------------------------------------------------------------
// _Parameters :
// pBuf: : IN: Buffer to display
// nbpr : Number of bytes per row to display
// len : Length of input buffer
// _Return: none
//
// ---------------------------------------------------------------------------
void PrintBuffer8(uint8_t *pBuf, int nbpr, int len)
{
memdump(pBuf, 1, nbpr, len);
}
void memdump(uint8_t *pBuf, int print_offset_only, int num_bytes_per_row, int len)
{
int i, j, cnt_hex, cnt_asc, base;
unsigned char c;
i = j = 0;
cnt_hex = len;
cnt_asc = len;
base = 0;
if (!print_offset_only)
base = (int)pBuf;
do
{
print_word(base + i);
sputs(": ");
for (j=0; j < num_bytes_per_row; j++)
{
if (cnt_hex)
{
print_byte(pBuf[i+j]);
sputs(" ");
cnt_hex--;
}
else
{
sputs(" ");
}
}
sputs(" ");
for (j=0; j < num_bytes_per_row; j++)
{
if (cnt_asc)
{
c = pBuf[i+j];
if((c < 0x20) || (c > 0x7F))
c = '.';
_putchar(1, c);
cnt_asc--;
}
else
{
sputs(" ");
}
}
sputs("\n");
i += num_bytes_per_row;
} while (cnt_hex);
}
+33
View File
@@ -0,0 +1,33 @@
#ifndef LIBSYS_H
#define LIBSYS_H
#include <stdint.h>
#include <board.h>
// ---------------------------------------------------------
// Types
// ---------------------------------------------------------
#define NO_ERROR LSYS_SUCCESS
#define ERROR LSYS_ERR_BASE
#define LSYS_SUCCESS 0
#define LSYS_ERR_BASE 0x80000000
#define IS_ERROR(e) ((e & LSYS_ERR_BASE) == LSYS_ERR_BASE)
void enter_critical();
void exit_critical();
int write(int file, char *ptr, int len);
int sputs(char const *pStr);
void print_byte(char byte);
void print_word(int word);
void _exit (int exitcode);
void sleep(unsigned ms);
void usleep(unsigned us);
void PrintBuffer8(uint8_t *pBuf, int nbpr, int len);
void memdump(uint8_t *pBuf, int print_offset_only, int num_bytes_per_row, int len);
#endif // LIBSYS_H
+738
View File
@@ -0,0 +1,738 @@
#include <sys/times.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "libsys.h"
// ---------------------------------------------------------------------------------
// Forward declarations
// ---------------------------------------------------------------------------------
void flush(UINT32 port);
UINT32 GetPort(int file);
// ---------------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------------
void libsys_init(void)
{
UINT32 volatile *pITIM_ctrl = (UINT32*)SYS_ITIM_CTRL;
// Disable timers
*pITIM_ctrl = 0;
// Initialzie syscall support
syscalls_init();
// Initialzie interrupt support
interrupt_init();
// flush stdin
flush(GetPort(0));
// Do some initializations here
}
enum
{
PORT_IN_UART_0 = 0,
PORT_IN_UART_1
};
enum
{
PORT_OUT_UART0 = 0,
PORT_OUT_UART1
};
UINT32 GetPort(int file)
{
if (file == 0) // STDIN
return PORT_IN_UART_0;
if (file == 1) // STDOUT
return PORT_OUT_UART0;
if (file == 2) // STDERR
return PORT_OUT_UART0;
if (file == 10) // AUX0
return PORT_IN_UART_1;
if (file == 11) // AUX1
return PORT_OUT_UART1;
}
enum
{
IF_TYPE_INVALID = 0,
IF_TYPE_UART
};
typedef struct _suart_if_t
{
volatile UINT32 *pCTRL;
volatile UINT32 *pDATA;
volatile UINT32 *pBAUD;
} uart_if_t;
typedef struct _scon_if_in_t
{
UINT32 type;
void *pIF;
} con_if_in_t;
typedef struct _scon_if_out_t
{
UINT32 type;
void *pIF;
} con_if_out_t;
// ---------------------------------------------------------------------------------
// Globals
// ---------------------------------------------------------------------------------
static uart_if_t uart_if[2] =
{
{(UINT32*)SYS_UART0_STAT, (UINT32*)SYS_UART0_DATA, (UINT32*)SYS_UART0_BAUD},
{(UINT32*)SYS_UART1_STAT, (UINT32*)SYS_UART1_DATA, (UINT32*)SYS_UART1_BAUD}
};
static con_if_in_t con_if_in[] =
{
{IF_TYPE_UART, &uart_if[0]},
{IF_TYPE_UART, &uart_if[1]},
{IF_TYPE_INVALID, NULL}
};
static con_if_out_t con_if_out[] =
{
{IF_TYPE_UART, &uart_if[0]},
{IF_TYPE_UART, &uart_if[1]},
{IF_TYPE_INVALID, NULL}
};
// ---------------------------------------------------------------------------------
// MIPS specific
// ---------------------------------------------------------------------------------
UINT32 CP0_SR_read(void)
{
UINT32 result;
__asm__
(
"mfc0 %[val], $12\n"
: [val] "=r" (result)
);
return result;
}
void CP0_SR_write(UINT32 val)
{
__asm__
(
"mtc0 %[val], $12\n"
: /* no output */
: [val] "r" (val)
);
}
UINT32 CP0_CR_read(void)
{
UINT32 result;
__asm__
(
"mfc0 %[val], $13\n"
: [val] "=r" (result)
);
return result;
}
void CP0_CR_write(UINT32 val)
{
__asm__
(
"mtc0 %[val], $13\n"
:
: [val] "r" (val)
);
}
UINT32 CP0_TR_read(void)
{
UINT32 result;
__asm__
(
"mfc0 %[val], $31\n"
: [val] "=r" (result)
);
return result;
}
void CP0_TR_write(UINT32 val)
{
__asm__
(
"mtc0 %[val], $31\n"
:
: [val] "r" (val)
);
}
UINT32 CP0_PRID_read(void)
{
UINT32 result;
__asm__
(
"mfc0 %[val], $15\n"
: [val] "=r" (result)
);
return result;
}
void CP0_TR_write_ptr(UINT32* pPtr)
{
__asm__
(
"swc0 $31, 0(%[pPtr])\n"
:
: [pPtr] "r" (pPtr)
);
}
void CP0_TR_read_ptr(UINT32* pPtr)
{
__asm__
(
"lwc0 $31, 0(%[pPtr])\n"
:
: [pPtr] "r" (pPtr)
);
}
void ICACHE_invalidate_all(void)
{
__asm__
(
"cop0 32\n"
);
}
void ICACHE_invalidate_at(UINT32* pPtr)
{
__asm__
(
"mtc0 %[pPtr], $31\n"
"cop0 33\n"
:
: [pPtr] "r" (pPtr)
);
}
void DCACHE_invalidate_all(void)
{
__asm__
(
"cop0 34\n"
);
}
void DCACHE_invalidate_at(UINT32* pPtr)
{
__asm__
(
"mtc0 %[pPtr], $31\n"
"cop0 35\n"
:
: [pPtr] "r" (pPtr)
);
}
// ------------------------------------
// Low-level I/O
// ------------------------------------
int UART_readchar(uart_if_t *pIF)
{
if (!pIF)
return -1;
if (SYS_UART_BIT_RX_AVAIL & *pIF->pCTRL)
return (*pIF->pDATA & 0xFF);
return -1;
}
void UART_writechar(uart_if_t *pIF, char c)
{
if (!pIF)
return;
while((SYS_UART_BIT_TX_HALFFULL & *pIF->pCTRL) != 0);
*pIF->pDATA = (UINT32)c;
}
// ---------------------------------------------------------------------------------
void flush(UINT32 port)
{
int c;
con_if_in_t *pIF;
pIF = &con_if_in[port];
do
{
switch(pIF->type)
{
case IF_TYPE_UART:
c = UART_readchar((uart_if_t*)pIF->pIF);
break;
default:
break;
}
} while(c > 0);
}
char readchar(UINT32 port)
{
int c;
con_if_in_t *pIF;
pIF = &con_if_in[port];
do
{
switch(pIF->type)
{
case IF_TYPE_UART:
c = UART_readchar((uart_if_t*)pIF->pIF);
break;
default:
break;
}
} while(c < 0);
return (char)c;
}
void writechar(UINT32 port, char c)
{
con_if_out_t *pIF;
pIF = &con_if_out[port];
switch(pIF->type)
{
case IF_TYPE_UART:
UART_writechar((uart_if_t*)pIF->pIF, c);
break;
default:
break;
}
}
void _putchar(UINT32 port, char c)
{
con_if_out_t *pIF;
pIF = &con_if_out[port];
switch(pIF->type)
{
case IF_TYPE_UART:
if (c == 0x0A)
UART_writechar((uart_if_t*)pIF->pIF, 0x0D);
UART_writechar((uart_if_t*)pIF->pIF, c);
break;
default:
break;
}
}
char _getchar(void)
{
return readchar(GetPort(0));
}
void _exit (int exitcode)
{
fflush(stdout);
fflush(stderr);
while(1);
}
void sleep(unsigned ms)
{
unsigned stop;
struct tms t;
times(&t);
stop = t.tms_utime + ms;
do
{
times(&t);
} while (t.tms_utime < stop);
}
void usleep(unsigned us)
{
unsigned stop_us, stop_s, curr_us, curr_s;
struct timeval t;
if (!us)
return;
gettimeofday(&t, NULL);
stop_s = (unsigned)t.tv_sec;
stop_us = (unsigned)t.tv_usec + us;
if (stop_us >= 1E6)
{
stop_us -= 1E6;
stop_s++;
}
do
{
gettimeofday(&t, NULL);
curr_s = (unsigned)t.tv_sec;
curr_us = (unsigned)t.tv_usec;
} while ((curr_s < stop_s) || (curr_us < stop_us));
}
int getrusage(int who, struct rusage *usage)
{
volatile long *pReg_usec = (long*)SYS_TIMER_USEC;
volatile long *pReg_sec = (long*)SYS_TIMER_SEC;
// who: RUSAGE_SELF or RUSAGE_CHILDREN
usage->ru_utime.tv_usec = *pReg_usec;
usage->ru_utime.tv_sec = *pReg_sec;
usage->ru_stime.tv_usec = *pReg_usec;
usage->ru_stime.tv_sec = *pReg_sec;
}
clock_t times(struct tms *buffer)
{
volatile long *pReg_usec = (long*)SYS_TIMER_USEC;
volatile long *pReg_sec = (long*)SYS_TIMER_SEC;
long sec;
long usec;
sec = *pReg_sec;
usec = *pReg_usec;
if (buffer)
{
buffer->tms_utime = sec*1000 + usec/1000;
buffer->tms_stime = 0;
buffer->tms_cutime = 0;
buffer->tms_cstime = 0;
}
return (clock_t)sec;
}
int gettimeofday(struct timeval *tp, void *tzp)
{
volatile long *pReg_usec = (long*)SYS_TIMER_USEC;
volatile long *pReg_sec = (long*)SYS_TIMER_SEC;
if (tp)
{
tp->tv_sec = *pReg_sec;
tp->tv_usec = *pReg_usec;
}
return 0;
}
int settimeofday(const struct timeval *tp, const struct timezone *tzp)
{
volatile long *pReg_usec = (long*)SYS_TIMER_USEC;
volatile long *pReg_sec = (long*)SYS_TIMER_SEC;
div_t res;
res = div(tp->tv_usec, 1E6);
if (tp)
{
*pReg_usec = res.rem;
*pReg_sec = tp->tv_sec + res.quot;
}
return 0;
}
caddr_t sbrk(int incr)
{
extern char end;
extern char stack_ptr;
static char *heap_end;
char *prev_heap_end;
if (heap_end == 0)
{
heap_end = &end;
}
prev_heap_end = heap_end;
if (heap_end + incr > &stack_ptr)
{
// sputs("Heap and stack collision\n");
// sputs("Stack Ptr = ");print_word(&stack_ptr);sputs("\n");
// sputs("Heap end = ");print_word(heap_end);sputs("\n");
// sputs("Increment = ");print_word(incr);sputs("\n");
exit(1);
}
heap_end += incr;
return (caddr_t) prev_heap_end;
}
int fstat(int file, struct stat *st)
{
// sputs("fstat ("); print_word(file); sputs(")\n");
st->st_mode = S_IFCHR;
st->st_blksize = 0;
return 0;
}
int lseek(int file, int ptr, int dir)
{
// sputs("lseek ("); print_word(file); sputs(")\n");
errno = ESPIPE;
return -1;
}
int open(const char *name, int flags, int mode)
{
// sputs("open (\""); sputs(name); sputs("\")\n");
errno = EIO;
return -1;
}
int close(int file)
{
// sputs("close ("); print_word(file); sputs(")\n");
return 0;
}
int read(int file, char *ptr, int len)
{
UINT32 port;
int i;
char c;
// sputs("read (file="); print_word(file); sputs(", len ="); print_word(len); sputs(")\n");
i = 0;
port = GetPort(file);
while (i < len)
{
c = readchar(port);
if (c == 0x04)
break;
if ((c == 0x0D) || (c == 0x0A))
{
writechar(port, 0x0D);
ptr[i++] = 0x0D;
writechar(port, 0x0A);
ptr[i++] = 0x0A;
break;
}
writechar(port, c);
ptr[i++] = c;
}
return i;
}
int write(int file, char *ptr, int len)
{
UINT32 port;
int i = 0;
// sputs("write ("); print_word(file); sputs(")\n");
port = GetPort(file);
for (i=0; i < len; i++)
_putchar(port, *ptr++);
return i;
}
int isatty(int file)
{
// sputs("isatty ("); print_word(file); sputs(")\n");
return 1;
}
int getpid(void)
{
return 1;
}
#include <errno.h>
#undef errno
extern int errno;
int kill(int pid, int sig)
{
errno = EINVAL;
return -1;
}
#include <errno.h>
#undef errno
extern int errno;
int link(char *old, char *new)
{
errno = EMLINK;
return -1;
}
#include <errno.h>
#undef errno
extern int errno;
int unlink(char *name)
{
errno = ENOENT;
return -1;
}
int sputs(char *pStr)
{
char *start;
start = pStr;
while(*pStr)
_putchar(GetPort(1), *(pStr++));
return pStr - start;
}
void print_byte(char byte)
{
int i;
unsigned char c, nibble;
for (i=0; i < 2; i++)
{
nibble = (char)((byte >> 4) & 0xF);
byte <<= 4;
if (nibble < 10)
c = nibble + '0';
else
c = nibble + 'A' - 10;
_putchar(GetPort(1), c);
}
}
void print_word(int word)
{
int i;
unsigned char c, nibble;
for (i=0; i < 4; i++)
{
c = (char) (word >> 24);
print_byte(c);
word <<= 8;
}
}
// ---------------------------------------------------------------------------------
// PrintBuffer8()
// Prints byte buffer as hex and ascii interpretation
// ---------------------------------------------------------------------------------
// _Parameters :
// pBuf: : IN: Buffer to display
// nbpr : Number of bytes per row to display
// len : Length of input buffer
// _Return: none
//
// ---------------------------------------------------------------------------
void PrintBuffer8(UINT8 *pBuf, int nbpr, int len)
{
memdump(pBuf, 1, nbpr, len);
}
void memdump(UINT8 *pBuf, int print_offset_only, int num_bytes_per_row, int len)
{
int i, j, cnt_hex, cnt_asc, base;
unsigned char c;
i = j = 0;
cnt_hex = len;
cnt_asc = len;
base = 0;
if (!print_offset_only)
base = (int)pBuf;
do
{
print_word(base + i);
sputs(": ");
for (j=0; j < num_bytes_per_row; j++)
{
if (cnt_hex)
{
print_byte(pBuf[i+j]);
sputs(" ");
cnt_hex--;
}
else
{
sputs(" ");
}
}
sputs(" ");
for (j=0; j < num_bytes_per_row; j++)
{
if (cnt_asc)
{
c = pBuf[i+j];
if((c < 0x20) || (c > 0x7F))
c = '.';
_putchar(GetPort(1), c);
cnt_asc--;
}
else
{
sputs(" ");
}
}
sputs("\n");
i += num_bytes_per_row;
} while (cnt_hex);
}
+626
View File
@@ -0,0 +1,626 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xcpt.h"
#include "libsys.h"
#include "mips_dis.h"
#include "cop0.h"
extern int instr_info(unsigned iword, instr_info_t *pInfo);
extern int tdisasm(char *buffer, unsigned address, unsigned iword, unsigned char ext, unsigned *regmask, unsigned *symbol_value, unsigned *ls_register);
#define DBG_PRINT_REG_CHG(tag_str, reg, reg_last) \
dbg_puts(tag_str); \
dbg_print_word(reg); \
dbg_puts(reg != reg_last ? "*" : " "); \
dbg_puts(" ");
#define MAX_USER_BP 16
#define BP_MASK_ID 0x00FFF
#define BP_MASK_TYPE 0xFF000
#define BP_GET_ID(bp) ((bp >> 6) & 0xFFF)
#define BP_USER_BASE 0x10000
#define BP_USER(id) (((BP_USER_BASE + id) << 6) | 0x0D)
#define BP_MGMT_BASE_SS 0x20000
#define BP_MGMT_SS(id) (((BP_MGMT_BASE_SS + id) << 6) | 0x0D)
#define BP_MGMT_BASE_RU 0x30000
#define BP_MGMT_RU(id) (((BP_MGMT_BASE_RU + id) << 6) | 0x0D)
static char g_buf[80];
static int DEBUG_PRINT = 0;
static int SHOW_NUM_INSTR = 5;
enum
{
STATE_INIT = 0,
STATE_RUN,
STATE_STEP_SINGLE,
STATE_STEP_PROC,
STATE_NUM_ENTRIES
};
static int g_state = STATE_INIT;
static char *g_state_names[STATE_NUM_ENTRIES] = {"Init", "Run", "Single step", "Precedure step"};
typedef struct _sbp_t
{
uint32_t *pAddr;
uint32_t instr;
} bp_t;
static EXCEPTION_CONTEXT xcp_last;
static bp_t user_bp[MAX_USER_BP];
static bp_t mgmt_bp_ss[2];
static bp_t mgmt_bp_ru[2];
static int g_is_ss;
static int g_bp_count;
extern void dbg_putchar(char c);
extern char dbg_getchar();
void dbg_puts(const char *buffer)
{
while(*buffer)
{
dbg_putchar(*buffer);
buffer++;
}
}
void dbg_print_byte(char byte)
{
int i;
unsigned char c, nibble;
for (i=0; i < 2; i++)
{
nibble = (char)((byte >> 4) & 0xF);
byte <<= 4;
if (nibble < 10)
c = nibble + '0';
else
c = nibble + 'A' - 10;
dbg_putchar(c);
}
}
void dbg_print_word(int word)
{
int i;
unsigned char c;
for (i=0; i < 4; i++)
{
c = (char) (word >> 24);
dbg_print_byte(c);
word <<= 8;
}
}
int dbg_gets(char *buffer, size_t size)
{
size_t len = 0;
while(size)
{
char c = dbg_getchar();
if (c == 0x0A || c == 0x0D)
{
if (len)
{
break;
}
}
else
{
buffer[len++] = c;
dbg_putchar(c);
if (len == size)
{
break;
}
}
}
buffer[len] = 0;
dbg_putchar(0x0D);
dbg_putchar(0x0A);
return len;
}
void dbg_puts_d(const char *buffer)
{
if (DEBUG_PRINT)
{
dbg_puts(buffer);
}
}
void dbg_print_word_d(int word)
{
if (DEBUG_PRINT)
{
dbg_print_word(word);
}
}
void dbg_strcpy(char *pDst, const char *pSrc)
{
while(*pSrc)
{
*(pDst++) = *(pSrc++);
}
*pDst = *pSrc;
}
void* dbg_memset(void *pDst, int value, size_t size)
{
char *dst = (char*)pDst;
while(size)
{
*(dst++) = (char)value;
size--;
}
return (void*)dst;
}
void* dbg_memcpy(void *pDst, const void *pSrc, size_t size )
{
char *dst = (char*)pDst;
char *src = (char*)pSrc;
while(size)
{
*(dst++) = *(src++);
size--;
}
return (void*)dst;
}
int IsBreak(uint32_t instr)
{
return ((instr & 0xFC00003F) == 0x0000000D);
}
uint32_t BreakGetType(uint32_t instr)
{
return (instr >> 6) & BP_MASK_TYPE;
}
void print_regs(struct xcptcontext * xcp, struct xcptcontext * xcp_last)
{
DBG_PRINT_REG_CHG(" Status : ", xcp->sr, xcp_last->sr);
DBG_PRINT_REG_CHG(" Cause : ", xcp->cr, xcp_last->cr);
DBG_PRINT_REG_CHG(" EPC : ", xcp->epc, xcp_last->epc);
DBG_PRINT_REG_CHG("BadAddr : ", xcp->baddr, xcp_last->baddr);
dbg_puts("\n");
DBG_PRINT_REG_CHG(" MDLO : ", xcp->mdlo, xcp_last->mdlo);
DBG_PRINT_REG_CHG(" MDHI : ", xcp->mdhi, xcp_last->mdhi);
dbg_puts("\n");
dbg_puts("Registers:\n");
DBG_PRINT_REG_CHG(" 0 (ze) : ", xcp->regs[0], xcp_last->regs[0]);
DBG_PRINT_REG_CHG(" 1 (at) : ", xcp->regs[1], xcp_last->regs[1]);
DBG_PRINT_REG_CHG(" 2 (v0) : ", xcp->regs[2], xcp_last->regs[2]);
DBG_PRINT_REG_CHG(" 3 (v1) : ", xcp->regs[3], xcp_last->regs[3]);
dbg_puts("\n");
DBG_PRINT_REG_CHG(" 4 (a0) : ", xcp->regs[4], xcp_last->regs[4]);
DBG_PRINT_REG_CHG(" 5 (a1) : ", xcp->regs[5], xcp_last->regs[5]);
DBG_PRINT_REG_CHG(" 6 (a2) : ", xcp->regs[6], xcp_last->regs[6]);
DBG_PRINT_REG_CHG(" 7 (a3) : ", xcp->regs[7], xcp_last->regs[7]);
dbg_puts("\n");
DBG_PRINT_REG_CHG(" 8 (t0) : ", xcp->regs[8], xcp_last->regs[8]);
DBG_PRINT_REG_CHG(" 9 (t1) : ", xcp->regs[9], xcp_last->regs[9]);
DBG_PRINT_REG_CHG("10 (t2) : ", xcp->regs[10], xcp_last->regs[10]);
DBG_PRINT_REG_CHG("11 (t3) : ", xcp->regs[11], xcp_last->regs[11]);
dbg_puts("\n");
DBG_PRINT_REG_CHG("12 (t4) : ", xcp->regs[12], xcp_last->regs[12]);
DBG_PRINT_REG_CHG("13 (t5) : ", xcp->regs[13], xcp_last->regs[13]);
DBG_PRINT_REG_CHG("14 (t6) : ", xcp->regs[14], xcp_last->regs[14]);
DBG_PRINT_REG_CHG("15 (t7) : ", xcp->regs[15], xcp_last->regs[15]);
dbg_puts("\n");
DBG_PRINT_REG_CHG("16 (s0) : ", xcp->regs[16], xcp_last->regs[16]);
DBG_PRINT_REG_CHG("17 (s1) : ", xcp->regs[17], xcp_last->regs[17]);
DBG_PRINT_REG_CHG("18 (s2) : ", xcp->regs[18], xcp_last->regs[18]);
DBG_PRINT_REG_CHG("19 (s3) : ", xcp->regs[19], xcp_last->regs[19]);
dbg_puts("\n");
DBG_PRINT_REG_CHG("20 (s4) : ", xcp->regs[20], xcp_last->regs[20]);
DBG_PRINT_REG_CHG("21 (s5) : ", xcp->regs[21], xcp_last->regs[21]);
DBG_PRINT_REG_CHG("22 (s6) : ", xcp->regs[22], xcp_last->regs[22]);
DBG_PRINT_REG_CHG("23 (s7) : ", xcp->regs[23], xcp_last->regs[23]);
dbg_puts("\n");
DBG_PRINT_REG_CHG("24 (t8) : ", xcp->regs[24], xcp_last->regs[24]);
DBG_PRINT_REG_CHG("25 (t9) : ", xcp->regs[25], xcp_last->regs[25]);
DBG_PRINT_REG_CHG("26 (k0) : ", xcp->regs[26], xcp_last->regs[26]);
DBG_PRINT_REG_CHG("27 (k1) : ", xcp->regs[27], xcp_last->regs[27]);
dbg_puts("\n");
DBG_PRINT_REG_CHG("28 (gp) : ", xcp->regs[28], xcp_last->regs[28]);
DBG_PRINT_REG_CHG("29 (sp) : ", xcp->regs[29], xcp_last->regs[29]);
DBG_PRINT_REG_CHG("30 (fp) : ", xcp->regs[30], xcp_last->regs[30]);
DBG_PRINT_REG_CHG("31 (ra) : ", xcp->regs[31], xcp_last->regs[31]);
dbg_puts("\n");
}
void set_mgmt_break(uint32_t *pAddr_break, int index)
{
mgmt_bp_ss[index].pAddr = NULL;
mgmt_bp_ss[index].instr = 0;
dbg_puts_d("Set management break at ");dbg_print_word_d((long)pAddr_break);dbg_puts_d("\n");
// Don't overwrite user breaks
if (IsBreak(*pAddr_break) && (BreakGetType(*pAddr_break) == BP_USER_BASE))
{
dbg_puts_d("Instruction at address ");dbg_print_word_d((long)pAddr_break);dbg_puts_d(" is user break\n");
}
else
{
// Save original instruction
mgmt_bp_ss[index].pAddr = pAddr_break;
mgmt_bp_ss[index].instr = *(mgmt_bp_ss[index].pAddr);
// Replace instruction with managment breakpoint
*(mgmt_bp_ss[index].pAddr) = BP_MGMT_SS(index+1);
ICACHE_invalidate_at(mgmt_bp_ss[index].pAddr);
}
}
void singlestep(struct xcptcontext * xcp, uint32_t *pAddr_curr, uint32_t is_branch_shadow)
{
int junk;
uint32_t branch_addr, reg, bp_type;
uint32_t *pInstr, *pAddr_prev, *pAddr_next;
instr_info_t info;
int set_break_at_jump_target = 0;
pAddr_prev = pAddr_curr - 1;
pAddr_next = pAddr_curr + 1;
mgmt_bp_ss[1].pAddr = NULL;
mgmt_bp_ss[1].instr = 0;
// We have two possible management breaks, if previous instruction was branch or jump
if (is_branch_shadow)
{
int type = instr_info(*pAddr_prev, &info);
tdisasm(g_buf, (unsigned int)pAddr_prev, (unsigned int)*pAddr_prev, 0, &junk, (unsigned int*)&branch_addr, (unsigned int*)&reg);
// Is jump target stored in register
if (type == INSTR_TYPE_JUMP || type == INSTR_TYPE_BRANCH)
{
if (info.flags & (INSTR_FLAGS_JUMP_REGISTER|INSTR_FLAGS_BRANCH_REGISTER))
{
branch_addr = xcp->regs[reg&0x1F];
}
}
// Don't overwrite user breaks
if (IsBreak(branch_addr) && (BreakGetType(branch_addr) == BP_USER_BASE))
{
dbg_puts_d("Instruction at branch address ");dbg_print_word_d((long)branch_addr);dbg_puts_d(" is user break\n");
}
else
{
set_break_at_jump_target = 1;
}
}
set_mgmt_break(pAddr_next, 0);
if (set_break_at_jump_target)
{
set_mgmt_break((uint32_t*)branch_addr, 1);
}
}
int dbg_handler(struct xcptcontext * xcp)
{
uint32_t bp_addr, bp_index = 0, branch_addr, reg, result, bp_type;
int junk, i, leave_isr, is_branch_shadow, is_user_bp;
uint32_t *pInstr, *pAddr_curr, *pAddr_prev, *pAddr_next;
instr_info_t info;
is_user_bp = 0;
pAddr_curr = (uint32_t*)xcp->epc;
is_branch_shadow = ((xcp->cr & 0x80000000) == 0x80000000);
if (is_branch_shadow)
pAddr_curr++;
pAddr_prev = pAddr_curr - 1;
pAddr_next = pAddr_curr + 1;
if (g_state = STATE_INIT)
{
dbg_memset(&xcp_last, 0, sizeof(EXCEPTION_CONTEXT));
}
dbg_puts_d("\n");dbg_puts_d(g_state_names[g_state]);dbg_puts_d("\n");
if (IsBreak(*pAddr_curr))
{
bp_type = BreakGetType(*pAddr_curr);
switch (bp_type)
{
case BP_MGMT_BASE_SS:
// Restore original instructions after single-step
dbg_puts_d("1. Restore after single-step at ");dbg_print_word_d((long)mgmt_bp_ss[0].pAddr);dbg_puts_d("\n");
*(mgmt_bp_ss[0].pAddr) = mgmt_bp_ss[0].instr;
ICACHE_invalidate_at(mgmt_bp_ss[0].pAddr);
if (mgmt_bp_ss[1].pAddr)
{
dbg_puts_d("2. Restore after single-step at ");dbg_print_word_d((long)mgmt_bp_ss[1].pAddr);dbg_puts_d("\n");
*(mgmt_bp_ss[1].pAddr) = mgmt_bp_ss[1].instr;
ICACHE_invalidate_at(mgmt_bp_ss[1].pAddr);
}
break;
case BP_MGMT_BASE_RU:
bp_index = BP_GET_ID(*pAddr_curr);
dbg_puts_d("Restore user break at ");dbg_print_word_d((long)user_bp[bp_index].pAddr);dbg_puts_d("\n");
*(user_bp[bp_index].pAddr) = BP_USER(bp_index);
ICACHE_invalidate_at(user_bp[bp_index].pAddr);
*(mgmt_bp_ru[0].pAddr) = mgmt_bp_ru[0].instr;
ICACHE_invalidate_at(mgmt_bp_ru[0].pAddr);
dbg_puts_d("1. Restore after RU at ");dbg_print_word_d((long)mgmt_bp_ru[0].pAddr);dbg_puts_d("\n");
if (mgmt_bp_ru[1].pAddr)
{
*(mgmt_bp_ru[1].pAddr) = mgmt_bp_ru[1].instr;
ICACHE_invalidate_at(mgmt_bp_ru[1].pAddr);
dbg_puts_d("2. Restore after RU at ");dbg_print_word_d((long)mgmt_bp_ru[1].pAddr);dbg_puts_d("\n");
}
if (!g_is_ss)
{
return 0;
}
break;
case BP_USER_BASE:
is_user_bp = 1;
bp_index = BP_GET_ID(*pAddr_curr);
dbg_puts_d("Restore instruction at ");dbg_print_word_d((long)user_bp[bp_index].pAddr);dbg_puts_d("\n");
*(user_bp[bp_index].pAddr) = user_bp[bp_index].instr;
ICACHE_invalidate_at(user_bp[bp_index].pAddr);
break;
default:
dbg_puts_d("Found ordinary break at ");dbg_print_word_d((long)pAddr_curr);dbg_puts_d("\n");
break;
}
}
dbg_puts("\n");
print_regs(xcp, &xcp_last);
pInstr = pAddr_prev;
// Disassemble instructions
for (i=0; i < SHOW_NUM_INSTR; i++)
{
dbg_print_word((long)pInstr);
if (pInstr != pAddr_curr)
{
if (IsBreak(*pInstr) && (BreakGetType(*pInstr) == BP_USER_BASE))
{
tdisasm(g_buf, (long)user_bp[BP_GET_ID(*pInstr)].pAddr, user_bp[BP_GET_ID(*pInstr)].instr, 0, &junk, &junk, &junk);
dbg_puts(": b("); dbg_print_byte((char)BP_GET_ID(*pInstr)); dbg_puts(") ");
}
else
{
tdisasm(g_buf, (long)pInstr, *pInstr, 0, &junk, &junk, &junk);
dbg_puts(": ");
}
}
else
{
tdisasm(g_buf, (long)pInstr, *pInstr, 0, &junk, &junk, &junk);
if (is_user_bp)
{
dbg_puts(": b("); dbg_print_byte((char)bp_index); dbg_puts(")-> ");
}
else
{
dbg_puts(": -> ");
}
}
dbg_puts(g_buf);
dbg_puts("\n");
pInstr++;
}
if (is_user_bp)
{
// Save original instruction
mgmt_bp_ru[0].pAddr = pAddr_next;
mgmt_bp_ru[0].instr = *(mgmt_bp_ru[0].pAddr);
// Replace instruction with managment breakpoint
*(mgmt_bp_ru[0].pAddr) = BP_MGMT_RU(bp_index);
ICACHE_invalidate_at(mgmt_bp_ru[0].pAddr);
mgmt_bp_ru[1].pAddr = NULL;
mgmt_bp_ru[1].instr = 0;
dbg_puts_d("1. Insert RU-break at ");dbg_print_word_d((long)mgmt_bp_ru[0].pAddr);dbg_puts_d("\n");
// We have two possible management breaks, if previous instruction was branch or jump
if (is_branch_shadow)
{
int type = instr_info(*pAddr_prev, &info);
tdisasm(g_buf, (long)pAddr_prev, *pAddr_prev, 0, &junk, (unsigned int*)&branch_addr, (unsigned int*)&reg);
// Is jump target stored in register
if (type == INSTR_TYPE_JUMP || type == INSTR_TYPE_BRANCH)
{
if (info.flags & (INSTR_FLAGS_JUMP_REGISTER|INSTR_FLAGS_BRANCH_REGISTER))
{
branch_addr = xcp->regs[reg&0x1F];
}
}
// Save original instruction
mgmt_bp_ru[1].pAddr = (uint32_t*)branch_addr;
mgmt_bp_ru[1].instr = *(mgmt_bp_ru[1].pAddr);
// Replace instruction with managment breakpoint
*(mgmt_bp_ru[1].pAddr) = BP_MGMT_RU(bp_index);
ICACHE_invalidate_at(mgmt_bp_ru[1].pAddr);
dbg_puts_d("2. Insert RU-break at ");dbg_print_word_d((long)mgmt_bp_ru[1].pAddr);dbg_puts_d("\n");
}
}
do
{
char buffer[33];
leave_isr = 0;
switch(dbg_getchar())
{
case 'c':
g_state = STATE_RUN;
leave_isr = 1;
g_is_ss = 0;
if (IsBreak(*pAddr_curr))
{
if (BreakGetType(*pAddr_curr) != BP_USER_BASE)
{
xcp->epc += 4; // Skip ordinary program breaks
}
}
break;
case 'g':
g_state = STATE_RUN;
leave_isr = 1;
g_is_ss = 0;
dbg_puts("Enter address: ");
dbg_gets(buffer, sizeof(buffer));
xcp->epc = strtol(buffer, NULL, 16);
break;
case 'b':
dbg_puts("Enter breakpoint: ");
dbg_gets(buffer, sizeof(buffer));
bp_addr = strtol(buffer, NULL, 16);
dbg_puts("Insert breakpoint at "); dbg_print_word(bp_addr); dbg_puts("\n");
user_bp[g_bp_count].pAddr = (uint32_t*)bp_addr;
user_bp[g_bp_count].instr = *(user_bp[g_bp_count].pAddr);
*(user_bp[g_bp_count].pAddr) = BP_USER(g_bp_count);
tdisasm(g_buf, (long)user_bp[g_bp_count].pAddr, user_bp[g_bp_count].instr, 0, &junk, &junk, &junk);
dbg_print_word((long)user_bp[g_bp_count].pAddr);dbg_puts(": b ");dbg_puts(g_buf);dbg_puts("\n");
ICACHE_invalidate_at(user_bp[g_bp_count].pAddr);
g_bp_count++;
break;
case 's':
g_state = STATE_STEP_SINGLE;
g_is_ss = 1;
leave_isr = 1;
if (is_user_bp)
break;
if (IsBreak(*pAddr_curr))
{
if (BreakGetType(*pAddr_curr) == BP_USER_BASE)
{
break;
}
else
{
xcp->epc += 4; // Skip ordinary program breaks
}
}
singlestep(xcp, pAddr_curr, is_branch_shadow);
break;
case 'e':
g_state = STATE_STEP_SINGLE;
g_is_ss = 1;
leave_isr = 1;
if (is_user_bp)
break;
if (IsBreak(*pAddr_curr))
{
if (BreakGetType(*pAddr_curr) == BP_USER_BASE)
{
break;
}
else
{
xcp->epc += 4; // Skip ordinary program breaks
}
}
pInstr = pAddr_curr;
do
{
result = instr_info(*pInstr, &info);
if (result == INSTR_TYPE_JUMP)
{
if (info.rs == 0x1F)
break;
}
else if (result == INSTR_TYPE_LOAD)
{
if (info.rs == 0x1F)
break;
}
pInstr++;
} while(1);
dbg_puts_d("Return found at "); dbg_print_word_d((long)pInstr);dbg_puts_d("\n");
set_mgmt_break(pInstr, 0);
break;
case 'p':
g_state = STATE_STEP_PROC;
g_is_ss = 1;
leave_isr = 1;
if (is_user_bp)
break;
if (IsBreak(*pAddr_curr))
{
if (BreakGetType(*pAddr_curr) == BP_USER_BASE)
{
break;
}
else
{
xcp->epc += 4; // Skip ordinary program breaks
}
}
result = instr_info(*pAddr_curr, &info);
if ((result == INSTR_TYPE_JUMP) && (info.flags & INSTR_FLAGS_JUMP_LINK))
{
singlestep(xcp, pAddr_next, 0);
dbg_puts_d("Skip sub-routine\n");
}
else
{
singlestep(xcp, pAddr_curr, is_branch_shadow);
}
break;
default:
break;
}
} while (!leave_isr);
dbg_memcpy(&xcp_last, xcp, sizeof(EXCEPTION_CONTEXT));
return 0;
}
+825
View File
@@ -0,0 +1,825 @@
/* +----------------------------------------------------------------+ */
/* | Copyright (c) 1994 Stanford University. | */
/* | All Rights Reserved. | */
/* | | */
/* | This software is distributed with *ABSOLUTELY NO SUPPORT* | */
/* | and *NO WARRANTY*. Use or reproduction of this code for | */
/* | commerical gains is strictly prohibited. Otherwise, you | */
/* | are given permission to use or modify this code as long | */
/* | as you do not remove this notice. | */
/* +----------------------------------------------------------------+ */
/* --------------------------------------------------- */
/* | Copyright (c) 1986 MIPS Computer Systems, Inc. | */
/* | All Rights Reserved. | */
/* --------------------------------------------------- */
/*
* Copyright 1985 by MIPS Computer Systems, Inc.
*/
/* TORCH disassembler */
/* derived from MIPS instruction dissassembler by PGL October 91 */
#include <stdio.h>
#include <string.h>
#include "mips_dis.h"
#define false 0
#define true 1
typedef int boolean;
char *strcat();
#define ZERO 0
#define COMPILER_NAMES tdis_reg_names[0]
#define HARDWARE_NAMES tdis_reg_names[1]
#define ASSEMBLER_NAMES tdis_reg_names[2]
#define DIS_REG_NAMES(x) tdis_reg_names[x]
union extension_byte {
unsigned char byte;
struct { /* extension byte bits in little-endian order */
#if (defined __MIPSEB || defined _MIPSEB || defined MIPSEB)
unsigned reserved:1;
unsigned dyn_nop:1;
unsigned rs_boost:2;
unsigned rt_boost:2;
unsigned rd_boost:2;
#elif (defined __MIPSEL || defined _MIPSEL || defined MIPSEL)
unsigned rd_boost:2;
unsigned rt_boost:2;
unsigned rs_boost:2;
unsigned dyn_nop:1;
unsigned reserved:1;
#endif /*MIPSEB*/
} e;
};
#define blez_op_T blez_op
#define blez_op_N (blez_op | 0x10)
#define bgtz_op_T bgtz_op
#define bgtz_op_N (bgtz_op | 0x10)
#define beq_op_T beq_op
#define beq_op_N (beq_op | 0x10)
#define bne_op_T bne_op
#define bne_op_N (bne_op | 0x10)
#define bc_op_T bc_op
#define bc_op_N (bc_op | 0x02)
static char *op_name[64] = {
/* 0 */ "special", "regimm","j", "jal", "beq", "bne", "blez", "bgtz",
/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui",
/*16 */ "cop0", "cop1", "cop2", "cop3", "beql","bnel","blezl","bgtzl",
/*24 */ "op60", "op64", "op68", "op6c", "op70", "op74", "op78", "op7c",
/*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "ld",
/*40 */ "sb", "sh", "swl", "sw", "opb0", "opb4", "swr", "sd",
/*48 */ "lwc0", "lwc1", "lwc2", "lwc3", "ldc0", "ldc1", "ldc2", "ldc3",
/*56 */ "swc0", "swc1", "swc2", "swc3", "sdc0", "sdc1", "sdc2", "sdc3"
};
static char *spec_name[64] = {
/* 0*/ "sll", "spec01","srl", "sra", "sllv", "spec05","srlv","srav",
/* 8*/ "jr", "jalr", "spec12","spec13","syscall","break","vcall","spec17",
/*16*/ "mfhi", "mthi", "mflo", "mtlo", "spec24","spec25","spec26","spec27",
/*24*/ "mult", "multu","div", "divu", "spec34","spec35","spec36","spec37",
/*32*/ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
/*40*/ "spec50","spec51","slt","sltu", "spec54","spec55","spec56","spec57",
/*48*/ "spec60","spec61","spec62","spec63","spec64","spec65","spec66","spec67",
/*56*/ "spec70","spec71","spec72","spec73","spec74","spec75","spec76","spec77"
};
static char *bcond_name[32] = {
"bltz",
"bgez",
"bltzl",
"bgezl",
"bcond04",
"bcond05",
"bcond06",
"bcond07",
"tgei",
"tgeiu",
"tlti",
"tltiu",
"teqi",
"bcond0d",
"tnei",
"bcond0f",
"bltzal",
"bgezal",
"bltzall",
"bgezall",
"bcond14",
"bcond15",
"bcond16",
"bcond17",
"bcond18",
"bcond19",
"bcond1a",
"bcond1b",
"bcond1c",
"bcond1d",
"bcond1e",
"bcond1f"
};
static char *cop1_name[64] = {
/* 0 */ "add", "sub", "mul", "div", "sqrt", "abs", "mov", "neg",
/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
/*32 */ "cvt.s","cvt.d","cvt.e","fop23","cvt.w","fop25","fop26","fop27",
/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
/*48 */ "c.f", "c.un","c.eq","c.ueq","c.olt","c.ult","c.ole","c.ule",
/*56 */ "c.sf","c.ngle","c.seq","c.ngl","c.lt","c.nge","c.le","c.ngt"
};
static char *fmt_name[16] = {
"s", "d", "e", "q",
"w", "fmt5", "fmt6", "fmt7",
"fmt8", "fmt9", "fmta", "fmtb",
"fmtc", "fmtd", "fmte", "fmtf"
};
/* public */
/* Three sets of commonly used register names */
const char *tdis_reg_names[3][64] = {
{ /* compiler names */
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
"zero.B","at.B","v0.B", "v1.B", "a0.B", "a1.B", "a2.B", "a3.B",
"t0.B", "t1.B", "t2.B", "t3.B", "t4.B", "t5.B", "t6.B", "t7.B",
"s0.B", "s1.B", "s2.B", "s3.B", "s4.B", "s5.B", "s6.B", "s7.B",
"t8.B", "t9.B", "k0.B", "k1.B", "gp.B", "sp.B", "s8.B", "ra.B"
},
{ /* hardware names */
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
"r24", "r25", "r26", "r27", "gp", "sp", "r30", "r31",
"r0.B", "r1.B", "r2.B", "r3.B", "r4.B", "r5.B", "r6.B", "r7.B",
"r8.B", "r9.B", "r10.B","r11.B","r12.B","r13.B","r14.B","r15.B",
"r16.B","r17.B","r18.B","r19.B","r20.B","r21.B","r22.B","r23.B",
"r24.B","r25.B","r26.B","r27.B","gp.B", "sp.B", "r30.B","r31.B"
},
{ /* assembler names */
"$0", "$at", "$2", "$3", "$4", "$5", "$6", "$7",
"$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
"$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
"$24", "$25", "$26", "$27", "$gp", "$sp", "$30", "$31",
"$0.B", "$at.B","$2.B", "$3.B", "$4.B", "$5.B", "$6.B", "$7.B",
"$8.B", "$9.B", "$10.B","$11.B","$12.B","$13.B","$14.B","$15.B",
"$16.B","$17.B","$18.B","$19.B","$20.B","$21.B","$22.B","$23.B",
"$24.B","$25.B","$26.B","$27.B","$gp.B","$sp.B","$30.B","$31.B"
}
};
static char *c0_opname[64] = {
"c0op0","tlbr","tlbwi","c0op3","c0op4","c0op5","tlbwr","c0op7",
"tlbp","c0op9","c0op10","c0op11","c0op12","c0op13","c0op14","c0op15",
"rfe","c0op17","c0op18","c0op19","c0op20","c0op21","c0op22","c0op23",
"c0op24","c0op25","c0op26","c0op27","c0op28","c0op29","c0op30","c0op31",
"c0op32","c0op33","c0op34","c0op35","c0op36","c0op37","c0op38","c0op39",
"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
"c0op48","c0op49","c0op50","c0op51","c0op52","c0op53","c0op54","c0op55",
"c0op56","c0op57","c0op58","c0op59","c0op60","c0op61","c0op62","c0op63"
};
static char *c0_reg[32] = {
"index","random","tlblo","c0r3","context","c0r5","c0r6","c0r7",
"badvaddr","c0r9","tlbhi","epcn","sr", "cause","epc", "c0r15",
"c0r16","c0r17","c0r18","c0r19","c0r20","c0r21","c0r22","c0r23",
"c0r24","c0r25","c0r26","c0r27","c0r28","c0r29","c0r30","c0r31"
};
/* Remember the options set by dis_init */
//#define ADDR_DEFAULT "%#010x:\t"
#define ADDR_DEFAULT 0
//#define VALUE_DEFAULT "%#010x\t"
#define VALUE_DEFAULT 0
#define NAME_DEFAULT COMPILER_NAMES
static struct {
char *addr_format;
char *value_format;
const char **reg_names;
int print_jal_targets;
} save = {
ADDR_DEFAULT,
VALUE_DEFAULT,
NAME_DEFAULT,
true
};
/* Update regmask to reflect the use of this general-purpose (not fp)
register, and return its name */
static const char *
register_name(ireg, boosted, regmask)
unsigned ireg, *regmask;
int boosted;
{
if (!boosted)
*regmask |= (1 << ireg);
return save.reg_names[boosted ? ireg + 32 : ireg];
}
int instr_info(unsigned iword, instr_info_t *pInfo)
{
unsigned address, *regmask, *symbol_value, *ls_register;
int return_value = 0;
boolean do_b_displacement = false;
boolean do_loadstore = false;
union mips_instruction i;
union extension_byte e;
i.word = iword;
*regmask = *symbol_value = *ls_register = 0;
/* decode the instruction */
switch (i.j_format.opcode)
{
case spec_op:
if (i.word == 0x20)
{
pInfo->type = INSTR_TYPE_NOP;
break;
}
else if (i.r_format.func == addu_op && i.r_format.rt == ZERO)
{
pInfo->type = INSTR_TYPE_MOVE;
pInfo->rd = i.r_format.rd;
pInfo->rs = i.r_format.rs;
break;
}
switch (i.r_format.func)
{
case sll_op:
case srl_op:
case sra_op:
pInfo->type = INSTR_TYPE_ARITH;
pInfo->rd = i.r_format.rd;
pInfo->rt = i.r_format.rt;
pInfo->re = i.r_format.re;
break;
case sllv_op:
case srlv_op:
case srav_op:
pInfo->type = INSTR_TYPE_ARITH;
pInfo->rd = i.r_format.rd;
pInfo->rt = i.r_format.rt;
pInfo->rs = i.r_format.rs;
break;
case mfhi_op:
case mflo_op:
pInfo->type = INSTR_TYPE_ARITH;
pInfo->rd = i.r_format.rd;
break;
case jalr_op:
pInfo->type = INSTR_TYPE_JUMP;
pInfo->flags = INSTR_FLAGS_JUMP_LINK | INSTR_FLAGS_JUMP_REGISTER;
pInfo->rd = i.r_format.rd;
pInfo->rs = i.r_format.rs;
break;
case jr_op:
pInfo->type = INSTR_TYPE_JUMP;
pInfo->flags = INSTR_FLAGS_JUMP_REGISTER;
pInfo->rs = i.r_format.rs;
break;
case mtlo_op:
case mthi_op:
pInfo->rs = i.r_format.rs;
case mult_op:
case multu_op:
case div_op:
case divu_op:
pInfo->type = INSTR_TYPE_ARITH;
pInfo->rt = i.r_format.rt;
break;
case syscall_op:
pInfo->type = INSTR_TYPE_SYSCALL;
break;
case break_op:
case vcall_op:
pInfo->type = INSTR_TYPE_BREAK;
break;
default:
break;
}
break;
case bcond_op:
pInfo->type = INSTR_TYPE_BRANCH;
pInfo->rs = i.i_format.rs;
do_b_displacement = true;
break;
case blez_op_T:
case bgtz_op_T:
case blez_op_N:
case bgtz_op_N:
pInfo->type = INSTR_TYPE_BRANCH;
pInfo->rs = i.i_format.rs;
do_b_displacement = true;
break;
case beq_op_T:
case beq_op_N:
case bne_op_T:
case bne_op_N:
pInfo->type = INSTR_TYPE_BRANCH;
pInfo->rs = i.i_format.rs;
pInfo->rt = i.i_format.rt;
do_b_displacement = true;
break;
case cop0_op:
case cop1_op:
case cop2_op:
case cop3_op:
pInfo->type = INSTR_TYPE_COP;
break; /* End of cop0, cop1, cop2, cop3 */
case jal_op:
pInfo->type = INSTR_TYPE_JUMP;
pInfo->flags = INSTR_FLAGS_JUMP_LINK | INSTR_FLAGS_JUMP_IMMEDIATE;
break;
case j_op:
pInfo->type = INSTR_TYPE_JUMP;
pInfo->flags = INSTR_FLAGS_JUMP_IMMEDIATE;
break;
case swc1_op:
case sdc1_op:
pInfo->type = INSTR_TYPE_STORE;
pInfo->flags = INSTR_FLAGS_STORE_COP;
do_loadstore = true;
break;
case lwc1_op:
case ldc1_op:
pInfo->type = INSTR_TYPE_LOAD;
pInfo->flags = INSTR_FLAGS_LOAD_COP;
do_loadstore = true;
break;
break;
case lb_op:
case lh_op:
case lw_op:
case ld_op:
case lbu_op:
case lhu_op:
case lwl_op:
case lwr_op:
pInfo->type = INSTR_TYPE_LOAD;
pInfo->flags = INSTR_FLAGS_LOAD_MEMORY;
pInfo->rt = i.i_format.rt;
do_loadstore = true;
break;
case sb_op:
case sh_op:
case sw_op:
case sd_op:
pInfo->type = INSTR_TYPE_STORE;
pInfo->flags = INSTR_FLAGS_STORE_MEMORY;
pInfo->rt = i.i_format.rt;
do_loadstore = true;
break;
case ori_op:
case xori_op:
pInfo->type = INSTR_TYPE_ARITH;
pInfo->flags = INSTR_FLAGS_ARITH_IMMEDIATE;
pInfo->rt = i.i_format.rt;
break;
/* fall through */
case andi_op:
pInfo->type = INSTR_TYPE_ARITH;
pInfo->flags = INSTR_FLAGS_ARITH_IMMEDIATE;
pInfo->rt = i.u_format.rt;
pInfo->rs = i.u_format.rs;
break;
case lui_op:
pInfo->type = INSTR_TYPE_LOAD;
pInfo->flags = INSTR_FLAGS_LOAD_IMMEDIATE;
pInfo->rt = i.u_format.rt;
break;
case addi_op:
case addiu_op:
pInfo->type = INSTR_TYPE_ARITH;
pInfo->flags = INSTR_FLAGS_ARITH_IMMEDIATE;
pInfo->rt = i.i_format.rt;
/* fall through */
default:
break;
}
return pInfo->type;
}
/* public -- see dissassembler.h */
int
tdisasm(buffer, address, iword, ext, regmask, symbol_value, ls_register)
char *buffer;
unsigned char ext; /* extension byte */
unsigned address, iword, *regmask, *symbol_value, *ls_register;
{
int return_value = 0;
char *bufptr = buffer;
boolean do_b_displacement = false;
boolean do_loadstore = false;
union mips_instruction i;
union extension_byte e;
*bufptr = 0;
i.word = iword;
e.byte = ext;
*regmask = *symbol_value = *ls_register = 0;
/* Put out the address and hex value of the instruction,
leaving bufptr set at the end */
if (save.addr_format) {
sprintf(bufptr, save.addr_format, address);
bufptr += strlen(bufptr);
}
if (save.value_format) {
sprintf(bufptr, save.value_format, iword);
bufptr += strlen(bufptr);
}
/* check for dynamic NOP */
if (e.e.dyn_nop) {
strcat(bufptr, "D.");
bufptr += 2;
}
/* decode the instruction */
switch (i.j_format.opcode) {
case spec_op:
if (i.word == 0x20) {
strcat(bufptr, "nop");
if (e.e.rd_boost)
strcat(bufptr, ".B");
bufptr += strlen(bufptr);
break;
} else if (i.r_format.func == addu_op && i.r_format.rt == ZERO) {
sprintf(bufptr, "move%s\t%s,%s",
e.e.rd_boost ? ".B" : "",
register_name(i.r_format.rd, e.e.rd_boost, regmask),
register_name(i.r_format.rs, e.e.rs_boost, regmask));
bufptr += strlen(bufptr);
break;
}
strcat(bufptr, spec_name[i.r_format.func]);
if (e.e.rd_boost)
strcat(bufptr, ".B");
bufptr += strlen(bufptr);
switch (i.r_format.func) {
case sll_op:
case srl_op:
case sra_op:
sprintf(bufptr, "\t%s,%s,%d",
register_name(i.r_format.rd, e.e.rd_boost, regmask),
register_name(i.r_format.rt, e.e.rt_boost, regmask),
i.r_format.re);
break;
case sllv_op:
case srlv_op:
case srav_op:
sprintf(bufptr, "\t%s,%s,%s",
register_name(i.r_format.rd, e.e.rd_boost, regmask),
register_name(i.r_format.rt, e.e.rt_boost, regmask),
register_name(i.r_format.rs, e.e.rs_boost, regmask));
break;
case mfhi_op:
case mflo_op:
sprintf(bufptr, "\t%s",
register_name(i.r_format.rd, e.e.rd_boost, regmask));
break;
case jalr_op:
return_value = 3;
sprintf(bufptr, "\t%s,%s",
register_name(i.r_format.rd, e.e.rd_boost, regmask),
register_name(i.r_format.rs, e.e.rs_boost, regmask));
*ls_register = i.r_format.rs;
break;
case jr_op:
return_value = 3;
*ls_register = i.r_format.rs;
/* fall through */
case mtlo_op:
case mthi_op:
sprintf(bufptr, "\t%s",
register_name(i.r_format.rs, e.e.rs_boost, regmask));
break;
case mult_op:
case multu_op:
case div_op:
case divu_op:
sprintf(bufptr, "\t%s,%s",
register_name(i.r_format.rs, e.e.rs_boost, regmask),
register_name(i.r_format.rt, e.e.rt_boost, regmask));
break;
case syscall_op:
break;
case break_op:
case vcall_op:
{
char *format = "\t%d";
unsigned op2 = i.r_format.rd * 32 + i.r_format.re;
if (op2)
format = "\t%d,%d";
sprintf(bufptr, format, i.r_format.rs*32+i.r_format.rt,
op2);
}
break;
default:
sprintf(bufptr, "\t%s,%s,%s",
register_name(i.r_format.rd, e.e.rd_boost, regmask),
register_name(i.r_format.rs, e.e.rs_boost, regmask),
register_name(i.r_format.rt, e.e.rt_boost, regmask));
break;
};
break;
case bcond_op:
sprintf(bufptr, "%s%s\t%s,",
bcond_name[i.i_format.rt],
e.e.rd_boost ? ".B" : "",
register_name(i.i_format.rs, e.e.rs_boost, regmask));
do_b_displacement = true;
break;
case blez_op_T:
case bgtz_op_T:
case blez_op_N:
case bgtz_op_N:
sprintf(bufptr, "%s%s\t%s,", op_name[i.i_format.opcode],
e.e.rd_boost ? ".B" : "",
register_name(i.i_format.rs, e.e.rs_boost, regmask));
do_b_displacement = true;
break;
case beq_op_T:
case beq_op_N:
if (i.i_format.rs == ZERO && i.i_format.rt == ZERO) {
strcat(bufptr, "b");
if (i.j_format.opcode == beq_op_T)
strcat(bufptr, ".T");
else
strcat(bufptr, ".N");
if (e.e.rd_boost)
strcat(bufptr, ".B\t");
else
strcat(bufptr, "\t");
do_b_displacement = true;
break;
}
/* fall through */
case bne_op_T:
case bne_op_N:
sprintf(bufptr, "%s%s\t%s,%s,", op_name[i.i_format.opcode],
e.e.rd_boost ? ".B" : "",
register_name(i.i_format.rs, e.e.rs_boost, regmask),
register_name(i.i_format.rt, e.e.rt_boost, regmask));
do_b_displacement = true;
break;
case cop0_op:
case cop1_op:
case cop2_op:
case cop3_op:
{
unsigned which_cop = i.j_format.opcode - cop0_op;
char *f_or_r = "rf";
switch (i.r_format.rs) {
case bc_op_T:
sprintf(bufptr, "bc%d%c.T%s\t", which_cop,
"ft"[i.r_format.rt],
e.e.rd_boost ? ".B" : "");
do_b_displacement = true;
break;
case bc_op_N:
sprintf(bufptr, "bc%d%c.N%s\t", which_cop,
"ft"[i.r_format.rt],
e.e.rd_boost ? ".B" : "");
do_b_displacement = true;
break;
case mtc_op:
if (which_cop == 0)
sprintf(bufptr, "mtc%d%s\t%s,%s", which_cop,
e.e.rd_boost ? ".B" : "",
register_name(i.r_format.rt, e.e.rt_boost,regmask),
c0_reg[i.f_format.rd]);
else
sprintf(bufptr, "mtc%d%s\t%s,%c%d", which_cop,
e.e.rd_boost ? ".B" : "",
register_name(i.r_format.rt, e.e.rt_boost,regmask),
f_or_r[(which_cop == 1)],
i.f_format.rd);
break;
case mfc_op:
if (which_cop == 0)
sprintf(bufptr, "mfc%d%s\t%s,%s", which_cop,
e.e.rd_boost ? ".B" : "",
register_name(i.r_format.rt, e.e.rt_boost,regmask),
c0_reg[i.f_format.rd]);
else
sprintf(bufptr, "mfc%d%s\t%s,%c%d", which_cop,
e.e.rd_boost ? ".B" : "",
register_name(i.r_format.rt, e.e.rt_boost,regmask),
f_or_r[(which_cop == 1)],
i.f_format.rd);
break;
case cfc_op:
sprintf(bufptr, "cfc%d%s\t%s,%c%d", which_cop,
e.e.rd_boost ? ".B" : "",
register_name(i.r_format.rt, e.e.rt_boost, regmask),
f_or_r[(which_cop == 1)],
i.f_format.rd);
break;
case ctc_op:
sprintf(bufptr, "ctc%d%s\t%s,%c%d", which_cop,
e.e.rd_boost ? ".B" : "",
register_name(i.r_format.rt, e.e.rt_boost, regmask),
f_or_r[(which_cop == 1)],
i.f_format.rd);
break;
default:
if (which_cop != 1)
sprintf(bufptr, "c0%s\t%s", e.e.rd_boost ? ".B" : "",
c0_opname[i.f_format.func]);
else
{
sprintf(bufptr, "%s.%s%s\t",
cop1_name[i.f_format.func],
fmt_name[i.f_format.fmt],
e.e.rd_boost ? ".B" : "");
bufptr += strlen(bufptr);
switch (i.f_format.func) {
case fsqrt_op:
case fabs_op:
case fmov_op:
case fcvts_op:
case fcvtd_op:
case fcvte_op:
case fcvtw_op:
sprintf(bufptr, "f%d,f%d",
i.f_format.re,
i.f_format.rd);
break;
case fcmp_op+0x0:
case fcmp_op+0x1:
case fcmp_op+0x2:
case fcmp_op+0x3:
case fcmp_op+0x4:
case fcmp_op+0x5:
case fcmp_op+0x6:
case fcmp_op+0x7:
case fcmp_op+0x8:
case fcmp_op+0x9:
case fcmp_op+0xa:
case fcmp_op+0xb:
case fcmp_op+0xc:
case fcmp_op+0xd:
case fcmp_op+0xe:
case fcmp_op+0xf:
sprintf(bufptr, "f%d,f%d",
i.f_format.rd,
i.f_format.rt);
break;
default:
sprintf(bufptr, "f%d,f%d,f%d",
i.f_format.re,
i.f_format.rd,
i.f_format.rt);
break;
} /* switch on func */
}
break; /* End of default */
} /* switch on rs */
}
break; /* End of cop0, cop1, cop2, cop3 */
case jal_op:
case j_op:
sprintf(bufptr, "%s%s\t", op_name[i.j_format.opcode],
e.e.rd_boost ? ".B" : "");
*symbol_value = (address & 0xF0000000) | i.j_format.target << 2;
if (save.print_jal_targets)
{
bufptr += strlen(bufptr);
sprintf(bufptr, "%#x", *symbol_value);
}
return_value = 1;
break;
case swc1_op:
case sdc1_op:
case lwc1_op:
case ldc1_op:
sprintf(bufptr, "%s%s\tf%d,", op_name[i.i_format.opcode],
e.e.rd_boost ? ".B" : "",
i.i_format.rt);
do_loadstore = true;
break;
case lb_op:
case lh_op:
case lw_op:
case ld_op:
case lbu_op:
case lhu_op:
case sb_op:
case sh_op:
case sw_op:
case sd_op:
case lwl_op:
case lwr_op:
sprintf(bufptr, "%s%s\t%s,", op_name[i.i_format.opcode],
e.e.rd_boost ? ".B" : "",
register_name(i.i_format.rt, e.e.rt_boost, regmask));
do_loadstore = true;
break;
case ori_op:
case xori_op:
if (i.u_format.rs == ZERO) {
sprintf(bufptr, "li%s\t%s,%d",
e.e.rd_boost ? ".B" : "",
register_name(i.u_format.rt, e.e.rt_boost, regmask),
i.u_format.uimmediate);
break;
}
/* fall through */
case andi_op:
sprintf(bufptr, "%s%s\t%s,%s,%#x", op_name[i.u_format.opcode],
e.e.rd_boost ? ".B" : "",
register_name(i.u_format.rt, e.e.rt_boost, regmask),
register_name(i.u_format.rs, e.e.rs_boost, regmask),
i.u_format.uimmediate);
break;
case lui_op:
sprintf(bufptr, "%s%s\t%s,%#x", op_name[i.u_format.opcode],
e.e.rd_boost ? ".B" : "",
register_name(i.u_format.rt, e.e.rt_boost, regmask),
i.u_format.uimmediate);
break;
case addi_op:
case addiu_op:
if (i.i_format.rs == ZERO) {
short sign_extender = i.i_format.simmediate;
sprintf(bufptr, "li%s\t%s,%d",
e.e.rd_boost ? ".B" : "",
register_name(i.i_format.rt, e.e.rt_boost, regmask),
sign_extender);
break;
}
/* fall through */
default:
{
short sign_extender = i.i_format.simmediate;
sprintf(bufptr, "%s%s\t%s,%s,%d", op_name[i.i_format.opcode],
e.e.rd_boost ? ".B" : "",
register_name(i.i_format.rt, e.e.rt_boost, regmask),
register_name(i.i_format.rs, e.e.rs_boost, regmask),
sign_extender);
}
break;
}
/* Some instructions require more than just registers */
if (do_loadstore)
{
short sign_extender = i.i_format.simmediate;
*symbol_value = sign_extender;
*ls_register = i.i_format.rs;
bufptr += strlen(bufptr);
sprintf(bufptr, "%d(%s)", sign_extender,
register_name(i.i_format.rs, e.e.rs_boost, regmask));
return_value = -1;
}
else if (do_b_displacement)
{
short sign_extender = i.i_format.simmediate;
bufptr += strlen(bufptr);
*symbol_value = 4 + address + ((((long)sign_extender & 0xFFFD0000) | (0x3FFFF & (sign_extender << 2))));
sprintf(bufptr, "%#x", *symbol_value);
return_value = 2;
}
return return_value;
}
+489
View File
@@ -0,0 +1,489 @@
/* ------------------------------------------------------------------ */
/* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | */
/* | Reserved. This software contains proprietary and confidential | */
/* | information of MIPS and its suppliers. Use, disclosure or | */
/* | reproduction is prohibited without the prior express written | */
/* | consent of MIPS. | */
/* ------------------------------------------------------------------ */
/* inst.h 4.2 */
/*
* inst.h -- instruction format defines
*/
/**
** UPDATE - 19 Sept 89 by Michael Smith
**
** Removed signed type to remove obnoxious C++ warning message.
**/
#ifdef LANGUAGE_C
#ifdef MIPSEB
union mips_instruction {
unsigned word;
unsigned char byte[4];
struct {
unsigned opcode : 6;
unsigned target : 26;
} j_format;
struct {
unsigned opcode : 6;
unsigned rs : 5;
unsigned rt : 5;
unsigned simmediate : 16;
} i_format;
struct {
unsigned opcode : 6;
unsigned rs : 5;
unsigned rt : 5;
unsigned uimmediate : 16;
} u_format;
struct {
unsigned opcode : 6;
unsigned rs : 5;
unsigned rt : 5;
unsigned rd : 5;
unsigned re : 5;
unsigned func : 6;
} r_format;
struct {
unsigned opcode : 6;
unsigned : 1;
unsigned fmt : 4;
unsigned rt : 5;
unsigned rd : 5;
unsigned re : 5;
unsigned func : 6;
} f_format;
};
#endif
#ifdef MIPSEL
union mips_instruction {
unsigned word;
unsigned char byte[4];
struct {
unsigned target : 26;
unsigned opcode : 6;
} j_format;
struct {
unsigned simmediate : 16;
unsigned rt : 5;
unsigned rs : 5;
unsigned opcode : 6;
} i_format;
struct {
unsigned uimmediate : 16;
unsigned rt : 5;
unsigned rs : 5;
unsigned opcode : 6;
} u_format;
struct {
unsigned func : 6;
unsigned re : 5;
unsigned rd : 5;
unsigned rt : 5;
unsigned rs : 5;
unsigned opcode : 6;
} r_format;
struct {
unsigned func : 6;
unsigned re : 5;
unsigned rd : 5;
unsigned rt : 5;
unsigned fmt : 4;
unsigned : 1;
unsigned opcode : 6;
} f_format;
};
#endif
#define INSTR_FLAGS_ARITH_IMMEDIATE 0x0000001
#define INSTR_FLAGS_ARITH_REGISTER 0x0000002
#define INSTR_FLAGS_JUMP_LINK 0x8000000
#define INSTR_FLAGS_JUMP_IMMEDIATE 0x0000001
#define INSTR_FLAGS_JUMP_REGISTER 0x0000002
#define INSTR_FLAGS_BRANCH_LINK 0x8000000
#define INSTR_FLAGS_BRANCH_IMMEDIATE 0x0000001
#define INSTR_FLAGS_BRANCH_REGISTER 0x0000002
#define INSTR_FLAGS_LOAD_IMMEDIATE 0x0000001
#define INSTR_FLAGS_LOAD_MEMORY 0x0000002
#define INSTR_FLAGS_LOAD_COP 0x0000004
#define INSTR_FLAGS_STORE_MEMORY 0x0000002
#define INSTR_FLAGS_STORE_COP 0x0000004
enum
{
INSTR_TYPE_NOP = 0,
INSTR_TYPE_MOVE,
INSTR_TYPE_ARITH,
INSTR_TYPE_JUMP,
INSTR_TYPE_BRANCH,
INSTR_TYPE_LOAD,
INSTR_TYPE_STORE,
INSTR_TYPE_COP,
INSTR_TYPE_MUL,
INSTR_TYPE_DIV,
INSTR_TYPE_BREAK,
INSTR_TYPE_SYSCALL
};
typedef struct _sinstr_info_t
{
unsigned type;
unsigned flags;
unsigned rd, rt, rs, re;
} instr_info_t;
#define spec_op 0x00
#define bcond_op 0x01
#define j_op 0x02
#define jal_op 0x03
#define beq_op 0x04
#define bne_op 0x05
#define blez_op 0x06
#define bgtz_op 0x07
#define addi_op 0x08
#define addiu_op 0x09
#define slti_op 0x0A
#define sltiu_op 0x0B
#define andi_op 0x0C
#define ori_op 0x0D
#define xori_op 0x0E
#define lui_op 0x0F
#define lb_op 0x20
#define lh_op 0x21
#define lw_op 0x23
#define lbu_op 0x24
#define lhu_op 0x25
#define ld_op 0x27
#define sb_op 0x28
#define sh_op 0x29
#define sw_op 0x2B
#define sd_op 0x2F
#define lwl_op 0x22
#define lwr_op 0x26
#define swl_op 0x2a
#define swr_op 0x2e
/* Co-processor sub-opcodes */
#define bc_op 0x08
#define mfc_op 0x00
#define cfc_op 0x02
#define mtc_op 0x04
#define ctc_op 0x06
/* Co-processor 0 opcodes */
#define cop0_op 0x10
#define lwc0_op 0x30
#define ldc0_op 0x34
#define swc0_op 0x38
#define sdc0_op 0x3c
/* Co-processor 0 sub-opcodes */
#define tlbr_op 0x1
#define tlbwi_op 0x2
#define tlbwr_op 0x6
#define tlbp_op 0x8
#define rfe_op 0x10
/* Co-processor 1 opcodes */
#define cop1_op 0x11
#define lwc1_op 0x31
#define ldc1_op 0x35
#define swc1_op 0x39
#define sdc1_op 0x3D
/* Co-processor 1 sub-opcodes */
#define fadd_op 0x00
#define fsub_op 0x01
#define fmpy_op 0x02
#define fdiv_op 0x03
#define fsqrt_op 0x04
#define fabs_op 0x05
#define fmov_op 0x06
#define fneg_op 0x07
#define fcvts_op 0x20
#define fcvtd_op 0x21
#define fcvte_op 0x22
#define fcvtw_op 0x24
#define fcmp_op 0x30
#define s_fmt 0
#define d_fmt 1
#define e_fmt 2
#define w_fmt 4
/* Other coprocessor opcodes */
#define cop2_op 0x12
#define lwc2_op 0x32
#define ldc2_op 0x36
#define swc2_op 0x3a
#define sdc2_op 0x3e
#define cop3_op 0x13
#define lwc3_op 0x33
#define ldc3_op 0x37
#define swc3_op 0x3b
#define sdc3_op 0x3f
/* bcond subopcodes */
#define bltz_op 0x00
#define bgez_op 0x01
#define bltzal_op 0x10
#define bgezal_op 0x11
/* special subopcodes */
#define sll_op 0x00
#define srl_op 0x02
#define sra_op 0x03
#define sllv_op 0x04
#define srlv_op 0x06
#define srav_op 0x07
#define jr_op 0x08
#define jalr_op 0x09
#define syscall_op 0x0C
#define break_op 0x0D
#define vcall_op 0x0E
#define mfhi_op 0x10
#define mthi_op 0x11
#define mflo_op 0x12
#define mtlo_op 0x13
#define mult_op 0x18
#define multu_op 0x19
#define div_op 0x1A
#define divu_op 0x1B
#define add_op 0x20
#define addu_op 0x21
#define and_op 0x24
#define or_op 0x25
#define xor_op 0x26
#define nor_op 0x27
#define sub_op 0x22
#define subu_op 0x23
#define slt_op 0x2A
#define sltu_op 0x2B
#endif /* LANGUAGE_C */
#ifdef LANGUAGE_PASCAL
#ifdef MIPSEB
type
mips_instruction =
packed record
case cardinal of
0: (
word: cardinal;
);
1: (
byte: packed array[0..3] of 0..255;
);
2: (
opcode: 0..63;
target: 0..67108863;
);
3: (
opcode3: 0..63;
rs: 0..31;
rt: 0..31;
simmediate: -32768..32767;
);
4: (
opcode4: 0..63;
rs4: 0..63;
rt4: 0..63;
uimmediate: 0..65535;
);
5: (
opcode5: 0..63;
rs5: 0..63;
rt5: 0..63;
rd5: 0..63;
re5: 0..63;
func: 0..63;
);
end {record};
#endif
#ifdef MIPSEL
type
mips_instruction =
packed record
case cardinal of
0: (
word: cardinal;
);
1: (
byte: packed array[0..3] of 0..255;
);
2: (
target: 0..67108863;
opcode: 0..63;
);
3: (
simmediate: -32768..32767;
rt: 0..31;
rs: 0..31;
opcode3: 0..63;
);
4: (
uimmediate: 0..65535;
rt4: 0..63;
rs4: 0..63;
opcode4: 0..63;
);
5: (
func: 0..63;
re5: 0..63;
rd5: 0..63;
rt5: 0..63;
rs5: 0..63;
opcode5: 0..63;
);
end {record};
#endif
#define spec_op 16#00
#define bcond_op 16#01
#define j_op 16#02
#define jal_op 16#03
#define beq_op 16#04
#define bne_op 16#05
#define blez_op 16#06
#define bgtz_op 16#07
#define addi_op 16#08
#define addiu_op 16#09
#define slti_op 16#0A
#define sltiu_op 16#0B
#define andi_op 16#0C
#define ori_op 16#0D
#define xori_op 16#0E
#define lui_op 16#0F
#define lb_op 16#20
#define lh_op 16#21
#define lw_op 16#23
#define lbu_op 16#24
#define lhu_op 16#25
#define ld_op 16#27
#define sb_op 16#28
#define sh_op 16#29
#define sw_op 16#2B
#define sd_op 16#2F
#define lwl_op 16#22
#define lwr_op 16#26
#define swl_op 16#2a
#define swr_op 16#2e
/* Co-processor sub-opcodes */
#define bc_op 16#08
#define mfc_op 16#00
#define cfc_op 16#02
#define mtc_op 16#04
#define ctc_op 16#06
/* Co-processor 0 opcodes */
#define cop0_op 16#10
#define lwc0_op 16#30
#define ldc0_op 16#34
#define swc0_op 16#38
#define sdc0_op 16#3c
/* Co-processor 0 sub-opcodes */
#define tlbr_op 16#1
#define tlbwi_op 16#2
#define tlbwr_op 16#6
#define tlbp_op 16#8
#define rfe_op 16#10
/* Co-processor 1 opcodes */
#define cop1_op 16#11
#define lwc1_op 16#31
#define ldc1_op 16#35
#define swc1_op 16#39
#define sdc1_op 16#3D
/* Co-processor 1 sub-opcodes */
#define fadd_op 16#00
#define fsub_op 16#01
#define fmpy_op 16#02
#define fdiv_op 16#03
#define fsqrt_op 16#04
#define fabs_op 16#05
#define fmov_op 16#06
#define fneg_op 16#07
#define fcvts_op 16#20
#define fcvtd_op 16#21
#define fcvte_op 16#22
#define fcvtw_op 16#24
#define fcmp_op 16#30
#define s_fmt 0
#define d_fmt 1
#define e_fmt 2
#define w_fmt 4
/* Other coprocessor opcodes */
#define cop2_op 16#12
#define lwc2_op 16#32
#define ldc2_op 16#36
#define swc2_op 16#3a
#define sdc2_op 16#3e
#define cop3_op 16#13
#define lwc3_op 16#33
#define ldc3_op 16#37
#define swc3_op 16#3b
#define sdc3_op 16#3f
/* bcond subopcodes */
#define bltz_op 16#00
#define bgez_op 16#01
#define bltzal_op 16#10
#define bgezal_op 16#11
/* special subopcodes */
#define sll_op 16#00
#define srl_op 16#02
#define sra_op 16#03
#define sllv_op 16#04
#define srlv_op 16#06
#define srav_op 16#07
#define jr_op 16#08
#define jalr_op 16#09
#define syscall_op 16#0C
#define break_op 16#0D
#define vcall_op 16#0E
#define mfhi_op 16#10
#define mthi_op 16#11
#define mflo_op 16#12
#define mtlo_op 16#13
#define mult_op 16#18
#define multu_op 16#19
#define div_op 16#1A
#define divu_op 16#1B
#define add_op 16#20
#define addu_op 16#21
#define and_op 16#24
#define or_op 16#25
#define xor_op 16#26
#define nor_op 16#27
#define sub_op 16#22
#define subu_op 16#23
#define slt_op 16#2A
#define sltu_op 16#2B
#endif /* LANGUAGE_PASCAL */
+831
View File
@@ -0,0 +1,831 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libsys.h"
#include "mips_gfx.h"
#define USE_HW_BLITTER
static vga_hw_t *g_pRegs;
// -------------------------------------------------------------
// Functions
// -------------------------------------------------------------
void __gfx_block_set_8(uint32_t* pDst, uint32_t value)
{
__asm__ volatile
(
"sw %[value], 0(%[pDst])\n"
"sw %[value], 4(%[pDst])\n"
"sw %[value], 8(%[pDst])\n"
"sw %[value], 12(%[pDst])\n"
"sw %[value], 16(%[pDst])\n"
"sw %[value], 20(%[pDst])\n"
"sw %[value], 24(%[pDst])\n"
"sw %[value], 28(%[pDst])\n"
:
: [pDst] "r" (pDst), [value] "r" (value)
);
}
void __gfx_block_copy_8(uint32_t* pDst, uint32_t* pSrc)
{
__asm__ volatile
(
".set noreorder\n"
".set nomacro\n"
"lw $s0, 0(%[pSrc])\n"
"lw $s1, 4(%[pSrc])\n"
"sw $s0, 0(%[pDst])\n"
"lw $s0, 8(%[pSrc])\n"
"sw $s1, 4(%[pDst])\n"
"lw $s1, 12(%[pSrc])\n"
"sw $s0, 8(%[pDst])\n"
"lw $s0, 16(%[pSrc])\n"
"sw $s1, 12(%[pDst])\n"
"lw $s1, 20(%[pSrc])\n"
"sw $s0, 16(%[pDst])\n"
"lw $s0, 24(%[pSrc])\n"
"sw $s1, 20(%[pDst])\n"
"lw $s1, 28(%[pSrc])\n"
"sw $s0, 24(%[pDst])\n"
"sw $s1, 28(%[pDst])\n"
".set macro\n"
".set reorder\n"
:
: [pDst] "r" (pDst), [pSrc] "r" (pSrc)
: "s0", "s1"
);
}
void _GFX_copy32(uint32_t* pDst, uint32_t* pSrc, uint32_t ndwords)
{
while (ndwords > 3)
{
__gfx_block_copy_8(pDst, pSrc);
pDst += 8;
pSrc += 8;
ndwords -= 8;
}
while (ndwords)
{
*(pDst++) = *(pSrc++);
ndwords -= 1;
}
}
void _GFX_memset32(uint32_t* pDst, uint32_t value, uint32_t ndwords)
{
while (ndwords > 3)
{
__gfx_block_set_8(pDst, value);
pDst += 8;
ndwords -= 8;
}
while (ndwords)
{
*(pDst++) = value;
ndwords -= 1;
}
}
void _GFX_copy32_hw(uint32_t* pDst, uint32_t* pSrc, uint32_t ndwords, uint32_t wait_finish)
{
g_pRegs->pVGA_src0 = (uint32_t)pSrc;
g_pRegs->pVGA_dst = (uint32_t)pDst;
g_pRegs->pVGA_src0_dimx = 0;
g_pRegs->pVGA_dst_dimx = 0;
g_pRegs->pVGA_nx = ndwords;
g_pRegs->pVGA_ny = 1;
g_pRegs->pVGA_ctrl &= ~SYS_VGA_BIT_BLIT_OP_CONSTCOL;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_BSY);
g_pRegs->pVGA_ctrl |= SYS_VGA_BIT_BLIT_REQ;
if (!wait_finish)
return;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_ACTIVE);
}
void _GFX_memset32_hw(uint32_t* pDst, uint32_t value, uint32_t ndwords, uint32_t wait_finish)
{
g_pRegs->pVGA_dst = (uint32_t)pDst;
g_pRegs->pVGA_src0_dimx = 0;
g_pRegs->pVGA_dst_dimx = 0;
g_pRegs->pVGA_nx = ndwords;
g_pRegs->pVGA_ny = 1;
g_pRegs->pVGA_color = value;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_BSY);
g_pRegs->pVGA_ctrl |= (SYS_VGA_BIT_BLIT_REQ | SYS_VGA_BIT_BLIT_OP_CONSTCOL);
if (!wait_finish)
return;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_ACTIVE);
}
void _GFX_BLIT_const(uint32_t* pDst, uint32_t xdim_dst, uint32_t xmin, uint32_t ymin, uint32_t xmax, uint32_t ymax, uint32_t value)
{
uint32_t xmax8, x, y;
uint32_t *pStart, *pEnd;
xmax8 = xmax - ((xmax-xmin)%8);
for (y=ymin; y < ymax; y += xdim_dst)
{
pStart = &pDst[xmin + y];
pEnd = &pDst[xmax8 + y];
while(pStart < pEnd)
{
__gfx_block_set_8(pStart, value);
pStart += 8;
}
// Do remainder
for (x=xmax8; x < xmax; x++)
{
pDst[x + y] = value;
}
}
}
void _GFX_BLIT_const_hw(uint32_t* pDst, uint32_t xdim_dst, uint32_t xmin, uint32_t ymin, uint32_t xmax, uint32_t ymax, uint32_t value, uint32_t wait_finish)
{
uint32_t *pStart, *pEnd;
pStart = (uint32_t*)&pDst[xmin + ymin*xdim_dst];
g_pRegs->pVGA_dst = (uint32_t)pStart;
g_pRegs->pVGA_dst_dimx = xdim_dst;
g_pRegs->pVGA_nx = xmax - xmin + 1;
g_pRegs->pVGA_ny = ymax - ymin + 1;
g_pRegs->pVGA_color = value;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_BSY);
g_pRegs->pVGA_ctrl |= (SYS_VGA_BIT_BLIT_REQ | SYS_VGA_BIT_BLIT_OP_CONSTCOL);
if (!wait_finish)
return;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_ACTIVE);
}
void GFX_DirtyRectSetClean(gfx_t *pObj, buf_t *pBuf)
{
pBuf->dirty.xmin = pBuf->w;
pBuf->dirty.xmax = 0;
pBuf->dirty.ymin = pBuf->h;
pBuf->dirty.ymax = 0;
pBuf->is_dirty = 0;
}
void GFX_DirtyRectInit(gfx_t *pObj, buf_t *pBuf, uint32_t w, uint32_t h)
{
pBuf->w = w;
pBuf->h = h;
GFX_DirtyRectSetClean(pObj, pBuf);
}
void GFX_DirtyRectUpdate(gfx_t *pObj, buf_t *pBuf, uint32_t xmin, uint32_t xmax, uint32_t ymin, uint32_t ymax)
{
if (xmin < pBuf->dirty.xmin)
{
pBuf->is_dirty = 1;
pBuf->dirty.xmin = xmin;
}
if (xmax > pBuf->dirty.xmax)
{
pBuf->is_dirty = 1;
pBuf->dirty.xmax = xmax;
}
if (ymin < pBuf->dirty.ymin)
{
pBuf->is_dirty = 1;
pBuf->dirty.ymin = ymin;
}
if (ymax > pBuf->dirty.ymax)
{
pBuf->is_dirty = 1;
pBuf->dirty.ymax = ymax;
}
if (pBuf->is_dirty && ((pBuf->dirty.xmax-pBuf->dirty.xmin+1)%8))
pBuf->dirty.xmax = pBuf->dirty.xmin + ((pBuf->dirty.xmax-pBuf->dirty.xmin)/8 + 1) * 8; // Make len_x multiple of 8
pObj->restore.xmin = pBuf->dirty.xmin;
pObj->restore.xmax = pBuf->dirty.xmax;
pObj->restore.ymin = pBuf->dirty.ymin;
pObj->restore.ymax = pBuf->dirty.ymax;
}
void GFX_DirtyRectCopy(gfx_t *pObj, buf_t *pBuf)
{
uint32_t xmin, xmax, xmax8, ymin, ymax, x, y;
uint32_t *pDst, *pDst_end;
uint32_t *pSrc, *pSrc_end;
xmin = pBuf->dirty.xmin;
xmax = pBuf->dirty.xmax;
ymin = pBuf->dirty.ymin;
ymax = pBuf->dirty.ymax;
ymin *= pBuf->w;
ymax *= pBuf->w;
#ifdef USE_HW_BLITTER
pSrc = (uint32_t*)&pBuf->pLast->pFB[xmin + ymin];
pDst = (uint32_t*)&pBuf->pFB[xmin + ymin];
g_pRegs->pVGA_src0 = (uint32_t)pSrc;
g_pRegs->pVGA_dst = (uint32_t)pDst;
g_pRegs->pVGA_src0_dimx = (uint32_t)pBuf->w;
g_pRegs->pVGA_dst_dimx = (uint32_t)pBuf->w;
g_pRegs->pVGA_nx = (uint32_t)(pBuf->dirty.xmax-pBuf->dirty.xmin);
g_pRegs->pVGA_ny = (uint32_t)(pBuf->dirty.ymax-pBuf->dirty.ymin);
g_pRegs->pVGA_ctrl &= ~SYS_VGA_BIT_BLIT_OP_CONSTCOL;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_BSY);
g_pRegs->pVGA_ctrl |= SYS_VGA_BIT_BLIT_REQ;
#else
xmax8 = xmax - ((xmax-xmin)%8);
for (y=ymin; y < ymax; y += pBuf->w)
{
pSrc = &pBuf->pLast->pFB[xmin + y];
pSrc_end = &pBuf->pLast->pFB[xmax8 + y];
pDst = &pBuf->pFB[xmin + y];
pDst_end = &pBuf->pFB[xmax8 + y];
while(pDst < pDst_end)
{
__gfx_block_copy_8(pDst, pSrc);
pDst += 8;
pSrc += 8;
}
// Do remainder
for (x=xmax8; x < xmax; x++)
{
pBuf->pFB[x + y] = pBuf->pLast->pFB[x + y];
}
}
#endif
}
void GFX_init(gfx_t *pObj)
{
int i;
buf_t *pBuf;
uint32_t w, h, fps;
g_pRegs = (vga_hw_t*)SYS_VGA_CTRL;
g_pRegs->pVGA_ctrl &= ~SYS_VGA_BIT_MSTEN;
w = Screen_get_resx();
h = Screen_get_resy();
fps = Screen_get_fps();
// printf("VGA screen = %d x %d @ %d fps\n", w, h, fps);
pObj->w = w;
pObj->h = h;
// Init background buffer
pObj->pBG = (uint32_t*)calloc(w * h, sizeof(buf_t));
// Init framebuffers
pObj->pBuf = (buf_t*)calloc(1, sizeof(buf_t));
pBuf = pObj->pBuf;
pBuf->pFB = (uint32_t*)calloc((w+8) * h, sizeof(uint32_t)); // w+8 because of dirty rectangle 8 byte min. x-size
for (i=1; i < GFX_NUM_FRAME_BUFFERS; i++)
{
pBuf->pNext = (buf_t*)calloc(1, sizeof(buf_t));
pBuf->pNext->pLast = pBuf;
pBuf = pBuf->pNext;
pBuf->pFB = (uint32_t*)calloc((w+8) * h, sizeof(uint32_t)); // w+8 because of dirty rectangle 8 byte min. x-size
}
pObj->pBuf->pLast = pBuf;
pBuf->pNext = pObj->pBuf;
pBuf = pObj->pBuf;
for (i=0; i < GFX_NUM_FRAME_BUFFERS; i++)
{
GFX_DirtyRectInit(pObj, pBuf, w, h);
// fprintf(stderr, "pBuf = %08X, pLast = %08X, pNext = %08X\n", pBuf, pBuf->pLast, pBuf->pNext);
pBuf = pBuf->pNext;
}
g_pRegs->pVGA_front = (uint32_t)pObj->pBuf->pLast->pFB;
g_pRegs->pVGA_back = (uint32_t)pObj->pBuf->pLast->pFB;
g_pRegs->pVGA_ctrl |= SYS_VGA_BIT_MSTEN;
}
void GFX_set_background(gfx_t *pObj, uint32_t *pImage, uint32_t image_nx, uint32_t image_ny, uint32_t image_scale_x, uint32_t image_scale_y)
{
uint32_t off_x, off_y;
uint32_t i, j;
uint32_t *pDst, *pSrc;
buf_t *pBuf;
if (!pImage)
return;
off_x = (pObj->w-(image_scale_x*image_nx))/2;
off_y = (pObj->h-(image_scale_y*image_ny))/2;
#ifdef USE_HW_BLITTER
pDst = ((uint32_t*)pObj->pBG) + pObj->w*off_y + off_x;
pSrc = pImage;
g_pRegs->pVGA_src0 = (uint32_t)pSrc;
g_pRegs->pVGA_dst = (uint32_t)pDst;
g_pRegs->pVGA_src0_dimx = (uint32_t)0;
g_pRegs->pVGA_dst_dimx = (uint32_t)0;
g_pRegs->pVGA_nx = (uint32_t)image_ny*image_nx;
g_pRegs->pVGA_ny = (uint32_t)1;
g_pRegs->pVGA_ctrl &= ~SYS_VGA_BIT_BLIT_OP_CONSTCOL;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_BSY);
g_pRegs->pVGA_ctrl |= SYS_VGA_BIT_BLIT_REQ;
pBuf = pObj->pBuf;
pDst = pBuf->pFB;
pSrc = pObj->pBG;
g_pRegs->pVGA_src0 = (uint32_t)pSrc;
g_pRegs->pVGA_dst = (uint32_t)pDst;
g_pRegs->pVGA_src0_dimx = (uint32_t)0;
g_pRegs->pVGA_dst_dimx = (uint32_t)0;
g_pRegs->pVGA_nx = (uint32_t)image_ny*image_nx;
g_pRegs->pVGA_ny = (uint32_t)1;
g_pRegs->pVGA_ctrl &= ~SYS_VGA_BIT_BLIT_OP_CONSTCOL;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_BSY);
g_pRegs->pVGA_ctrl |= SYS_VGA_BIT_BLIT_REQ;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_ACTIVE);
#else
pDst = ((uint32_t*)pObj->pBG) + pObj->w*off_y + off_x;
pSrc = pImage;
for (i=0; i < image_ny*image_nx; i += 8)
{
__gfx_block_copy_8(pDst, pSrc);
pDst += 8;
pSrc += 8;
}
pBuf = pObj->pBuf;
pDst = pBuf->pFB;
pSrc = pObj->pBG;
for (i=0; i < image_ny*image_nx; i += 8)
{
__gfx_block_copy_8(pDst, pSrc);
pDst += 8;
pSrc += 8;
}
#endif
do
{
GFX_DirtyRectUpdate(pObj, pBuf, 0, pObj->w-1, 0, pObj->h-1);
pBuf = pBuf->pNext;
} while(pBuf != pObj->pBuf);
}
void GFX_frame(gfx_t *pObj, uint32_t sync_mode)
{
// Wait until back buffer becomes front
if (sync_mode == GFX_FRAME_SYNC)
{
while(g_pRegs->pVGA_front == (uint32_t)pObj->pBuf->pFB);
}
GFX_copy_front2back(pObj);
// Invalidate D-Cache after blitting has finished
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_BSY);
#ifdef USE_HW_BLITTER
DCACHE_invalidate_all();
#endif
}
void GFX_show(gfx_t *pObj)
{
g_pRegs->pVGA_back = (uint32_t)pObj->pBuf->pFB;
pObj->pBuf = pObj->pBuf->pNext;
}
void GFX_copy_front2back(gfx_t *pObj)
{
buf_t *pBuf;
pBuf = pObj->pBuf;
// Lopp over all frame buffers, except front buffer
while(pBuf != pObj->pBuf->pLast)
{
if (pBuf->is_dirty)
{
// fprintf(stderr, "Dirty rect [%08X]: w=%d, h=%d\n", (int)pBuf, pBuf->dirty.xmax - pBuf->dirty.xmin, pBuf->dirty.ymax - pBuf->dirty.ymin);
GFX_DirtyRectCopy(pObj, pBuf);
GFX_DirtyRectSetClean(pObj, pBuf);
}
pBuf = pBuf->pNext;
}
}
void GFX_get_FB_front(gfx_t *pObj, uint32_t **ppFB)
{
*ppFB = pObj->pBuf->pLast->pFB;
}
void box_create(box_t *pObj, uint32_t w, uint32_t h)
{
pObj->w = w;
pObj->h = h;
}
void GFX_restore(gfx_t *pObj, box_t *pBox, uint32_t posx, uint32_t posy)
{
uint32_t xmin, xmax, xmax8, ymin, ymax, x, y, nx, ny;
uint32_t *pDst, *pDst_end;
uint32_t *pSrc, *pSrc_end;
buf_t *pBuf;
if (pBox)
{
xmin = posx;
xmax = pBox->w + posx - 0;
if (xmax >= pObj->w)
xmax = pObj->w - 0;
ymin = posy;
ymax = pBox->h + posy - 0;
if (ymax >= pObj->h)
ymax = pObj->h - 0;
}
else
{
xmin = pObj->restore.xmin;
xmax = pObj->restore.xmax;
ymin = pObj->restore.ymin;
ymax = pObj->restore.ymax;
}
pObj->restore.xmin = 0;
pObj->restore.xmax = 0;
pObj->restore.ymin = 0;
pObj->restore.ymax = 0;
pBuf = pObj->pBuf->pNext;
// Lopp over all frame buffers, except current back buffer
while(pBuf != pObj->pBuf)
{
GFX_DirtyRectUpdate(pObj, pBuf, xmin, xmax, ymin, ymax);
pBuf = pBuf->pNext;
}
nx = xmax - xmin;
ny = ymax - ymin;
pBuf = pObj->pBuf;
ymin *= pObj->w;
ymax *= pObj->w;
#ifdef USE_HW_BLITTER
pSrc = (uint32_t*)&pObj->pBG[xmin + ymin];
pDst = (uint32_t*)&pBuf->pFB[xmin + ymin];
g_pRegs->pVGA_src0 = (uint32_t)pSrc;
g_pRegs->pVGA_dst = (uint32_t)pDst;
g_pRegs->pVGA_src0_dimx = (uint32_t)pObj->w;
g_pRegs->pVGA_dst_dimx = (uint32_t)pObj->w;
g_pRegs->pVGA_nx = (uint32_t)nx;
g_pRegs->pVGA_ny = (uint32_t)ny;
g_pRegs->pVGA_ctrl &= ~SYS_VGA_BIT_BLIT_OP_CONSTCOL;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_BSY);
g_pRegs->pVGA_ctrl |= SYS_VGA_BIT_BLIT_REQ;
#else
xmax8 = xmax - ((xmax-xmin)%8);
for (y=ymin; y < ymax; y += pBuf->w)
{
pSrc = &pObj->pBG[xmin + y];
pSrc_end = &pObj->pBG[xmax8 + y];
pDst = &pBuf->pFB[xmin + y];
pDst_end = &pBuf->pFB[xmax8 + y];
while(pDst < pDst_end)
{
__gfx_block_copy_8(pDst, pSrc);
pDst += 8;
pSrc += 8;
}
// Do remainder
for (x=xmax8; x < xmax; x++)
{
pBuf->pFB[x + y] = pObj->pBG[x + y];
}
}
#endif
}
void GFX_box_draw_direct(gfx_t *pObj, box_t *pBox, uint32_t posx, uint32_t posy, uint32_t color)
{
uint32_t xmin, xmax, xmax8, ymin, ymax, x, y;
uint32_t *pFB, *pFB_end;
buf_t *pBuf;
pBuf = pObj->pBuf->pLast;
xmin = posx;
xmax = pBox->w + posx - 0;
if (xmax >= pObj->w)
xmax = pObj->w - 0;
ymin = posy;
ymax = pBox->h + posy - 0;
if (ymax >= pObj->h)
ymax = pObj->h - 0;
ymin *= pObj->w;
ymax *= pObj->w;
xmax8 = xmax - ((xmax-xmin)%8);
for (y=ymin; y < ymax; y += pObj->w)
{
pFB = &pBuf->pFB[xmin + y];
pFB_end = &pBuf->pFB[xmax8 + y];
while(pFB < pFB_end)
{
__gfx_block_set_8(pFB, color);
pFB += 8;
}
// Do remainder
for (x=xmax8; x < xmax; x++)
{
pBuf->pFB[x + y] = color;
}
}
}
void GFX_box_draw(gfx_t *pObj, box_t *pBox, uint32_t posx, uint32_t posy, uint32_t color)
{
uint32_t xmin, xmax, xmax8, ymin, ymax, x, y, nx, ny;
uint32_t *pFB, *pFB_end;
buf_t *pBuf;
xmin = posx;
xmax = pBox->w + posx - 0;
if (xmax >= pObj->w)
xmax = pObj->w - 0;
ymin = posy;
ymax = pBox->h + posy - 0;
if (ymax >= pObj->h)
ymax = pObj->h - 0;
nx = xmax - xmin;
ny = ymax - ymin;
// fprintf(stderr, "GFX_box_draw(): x=%d, y=%d, nx=%d, ny=%d\n", posx, posy, nx, ny);
pBuf = pObj->pBuf->pNext;
// Lopp over all frame buffers, except current back buffer
while(pBuf != pObj->pBuf)
{
GFX_DirtyRectUpdate(pObj, pBuf, xmin, xmax-1, ymin, ymax-1);
pBuf = pBuf->pNext;
}
pBuf = pObj->pBuf;
ymin *= pObj->w;
ymax *= pObj->w;
#ifdef USE_HW_BLITTER
pFB = (uint32_t*)&pBuf->pFB[xmin + ymin];
g_pRegs->pVGA_dst = (uint32_t)pFB;
g_pRegs->pVGA_dst_dimx = (uint32_t)pObj->w;
g_pRegs->pVGA_nx = (uint32_t)nx;
g_pRegs->pVGA_ny = (uint32_t)ny;
g_pRegs->pVGA_color = color;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_BSY);
g_pRegs->pVGA_ctrl |= (SYS_VGA_BIT_BLIT_REQ | SYS_VGA_BIT_BLIT_OP_CONSTCOL);
#else
xmax8 = xmax - ((xmax-xmin)%8);
for (y=ymin; y < ymax; y += pObj->w)
{
pFB = &pBuf->pFB[xmin + y];
pFB_end = &pBuf->pFB[xmax8 + y];
while(pFB < pFB_end)
{
__gfx_block_set_8(pFB, color);
pFB += 8;
}
// Do remainder
for (x=xmax8; x < xmax; x++)
{
pBuf->pFB[x + y] = color;
}
}
#endif
}
void GFX_box_draw_bg(gfx_t *pObj, box_t *pBox, uint32_t posx, uint32_t posy, uint32_t color)
{
uint32_t xmin, xmax, xmax8, ymin, ymax, x, y, nx, ny;
uint32_t *pFB, *pFB_end;
xmin = posx;
xmax = pBox->w + posx - 0;
if (xmax >= pObj->w)
xmax = pObj->w - 0;
ymin = posy;
ymax = pBox->h + posy - 0;
if (ymax >= pObj->h)
ymax = pObj->h - 0;
nx = xmax - xmin;
ny = ymax - ymin;
ymin *= pObj->w;
ymax *= pObj->w;
#ifdef USE_HW_BLITTER
pFB = (uint32_t*)&pObj->pBG[xmin + ymin];
g_pRegs->pVGA_dst = (uint32_t)pFB;
g_pRegs->pVGA_dst_dimx = (uint32_t)pObj->w;
g_pRegs->pVGA_nx = (uint32_t)nx;
g_pRegs->pVGA_ny = (uint32_t)ny;
g_pRegs->pVGA_color = color;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_BSY);
g_pRegs->pVGA_ctrl |= (SYS_VGA_BIT_BLIT_REQ | SYS_VGA_BIT_BLIT_OP_CONSTCOL);
#else
xmax8 = xmax - ((xmax-xmin)%8);
for (y=ymin; y < ymax; y += pObj->w)
{
pFB = &pObj->pBG[xmin + y];
pFB_end = &pObj->pBG[xmax8 + y];
while(pFB < pFB_end)
{
__gfx_block_set_8(pFB, color);
pFB += 8;
}
// Do remainder
for (x=xmax8; x < xmax; x++)
{
pObj->pBG[x + y] = color;
}
}
#endif
}
void GFX_box_blit_bg(gfx_t *pObj, box_t *pBox, uint32_t pos_x_src, uint32_t pos_y_src, uint32_t pos_x_dst, uint32_t pos_y_dst)
{
uint32_t x_src, y_src, xmax8_src;
uint32_t x_dst, y_dst, xmax8_dst;
uint32_t xmin_src, xmax_src, ymin_src, ymax_src;
uint32_t xmin_dst, xmax_dst, ymin_dst, ymax_dst;
uint32_t *pDst, *pDst_end;
uint32_t *pSrc, *pSrc_end;
buf_t *pBuf;
pBuf = pObj->pBuf->pNext;
xmin_src = pos_x_src;
xmax_src = pBox->w + pos_x_src - 0;
if (xmax_src >= pObj->w)
xmax_src = pObj->w - 0;
ymin_src = pos_y_src;
ymax_src = pBox->h + pos_y_src - 0;
if (ymax_src >= pObj->h)
ymax_src = pObj->h - 0;
xmin_dst = pos_x_dst;
xmax_dst = pBox->w + pos_x_dst - 0;
if (xmax_dst >= pObj->w)
xmax_dst = pObj->w - 0;
ymin_dst = pos_y_dst;
ymax_dst = pBox->h + pos_y_dst - 0;
if (ymax_dst >= pObj->h)
ymax_dst = pObj->h - 0;
// Lopp over all frame buffers, except current back buffer
while(pBuf != pObj->pBuf)
{
GFX_DirtyRectUpdate(pObj, pBuf, xmin_dst, xmax_dst, ymin_dst, ymax_dst);
pBuf = pBuf->pNext;
}
pBuf = pObj->pBuf;
#ifdef USE_HW_BLITTER
pSrc = (uint32_t*)&pObj->pBG[xmin_src + ymin_src*pObj->w];
pDst = (uint32_t*)&pBuf->pFB[xmin_dst + ymin_dst*pObj->w];
g_pRegs->pVGA_src0 = (uint32_t)pSrc;
g_pRegs->pVGA_src0_dimx = pObj->w;
g_pRegs->pVGA_dst = (uint32_t)pDst;
g_pRegs->pVGA_dst_dimx = pObj->w;
g_pRegs->pVGA_nx = pBox->w;
g_pRegs->pVGA_ny = pBox->h;
while (g_pRegs->pVGA_ctrl & SYS_VGA_BIT_BLIT_BSY);
g_pRegs->pVGA_ctrl &= ~SYS_VGA_BIT_BLIT_OP_CONSTCOL;
g_pRegs->pVGA_ctrl |= SYS_VGA_BIT_BLIT_REQ;
#else
ymin_src *= pObj->w;
ymax_src *= pObj->w;
ymin_dst *= pObj->w;
ymax_dst *= pObj->w;
y_dst = ymin_dst;
xmax8_src = xmax_src - ((xmax_src-xmin_src)%8);
xmax8_dst = xmax_dst - ((xmax_dst-xmin_dst)%8);
for (y_src=ymin_src; y_src < ymax_src; y_src += pBuf->w)
{
pSrc = &pObj->pBG[xmin_src + y_src];
pSrc_end = &pObj->pBG[xmax8_src + y_src];
pDst = &pBuf->pFB[xmin_dst + y_dst];
pDst_end = &pBuf->pFB[xmax8_dst + y_dst];
while(pDst < pDst_end)
{
__gfx_block_copy_8(pDst, pSrc);
pDst += 8;
pSrc += 8;
}
// Do remainder
for (x_src=xmax8_src; x_src < xmax_src; x_src++)
{
*(pDst++) = *(pSrc++);
}
y_dst += pBuf->w;
}
#endif
}
+95
View File
@@ -0,0 +1,95 @@
#ifndef GFX_H
#define GFX_H
#include "libsys.h"
#define GFX_NUM_FRAME_BUFFERS 2
#define GFX_FRAME_NOSYNC 0
#define GFX_FRAME_SYNC 1
// -------------------------------------------------------------
// Types
// -------------------------------------------------------------
typedef struct _sbox_t
{
uint32_t w, h;
} box_t;
typedef struct _srect_t
{
uint32_t xmin, xmax;
uint32_t ymin, ymax;
} rect_t;
typedef struct _svga_hw_t
{
uint32_t volatile pVGA_ctrl; // 0xA0030000 // R/W
uint32_t volatile pVGA_ascii; // 0xA0030004 // R/W
uint32_t volatile pVGA_posx; // 0xA0030008 // R/W
uint32_t volatile pVGA_posy; // 0xA003000C // R/W
uint32_t volatile pVGA_cgcol; // 0xA0030010 // R/W
uint32_t volatile pVGA_res; // 0xA0030014 // RO
uint32_t volatile pVGA_front; // 0xA0030018 // R/W
uint32_t volatile pVGA_back; // 0xA003001C // R/W
uint32_t volatile pVGA_src0; // 0xA0030020 // R/W
uint32_t volatile pVGA_src0_dimx; // 0xA0030024 // R/W
uint32_t volatile pVGA_gap0; // 0xA0030028 // R/W
uint32_t volatile pVGA_gap1; // 0xA003002C // R/W
uint32_t volatile pVGA_src1; // 0xA0030030 // R/W
uint32_t volatile pVGA_src1_dimx; // 0xA0030034 // R/W
uint32_t volatile pVGA_gap2; // 0xA0030038 // R/W
uint32_t volatile pVGA_gap3; // 0xA003003C // R/W
uint32_t volatile pVGA_dst; // 0xA0030040 // R/W
uint32_t volatile pVGA_dst_dimx; // 0xA0030044 // R/W
uint32_t volatile pVGA_gap4; // 0xA0030048 // R/W
uint32_t volatile pVGA_gap5; // 0xA003004C // R/W
uint32_t volatile pVGA_nx; // 0xA0030050 // R/W
uint32_t volatile pVGA_ny; // 0xA0030054 // R/W
uint32_t volatile pVGA_color; // 0xA0030058 // R/W
} vga_hw_t;
typedef struct _sbuf_t
{
uint32_t *pFB;
struct _sbuf_t *pNext;
struct _sbuf_t *pLast;
uint32_t is_dirty;
rect_t dirty;
uint32_t w, h;
} buf_t;
typedef struct _sgfx_t
{
uint32_t w, h;
buf_t *pBuf;
uint32_t *pBG;
rect_t restore;
} gfx_t;
// -------------------------------------------------------------
// Functions
// -------------------------------------------------------------
void __gfx_block_set_8(uint32_t* pDst, uint32_t value);
void __gfx_block_copy_8(uint32_t* pDst, uint32_t* pSrc);
void _GFX_copy32(uint32_t* pDst, uint32_t* pSrc, uint32_t ndwords);
void _GFX_copy32_hw(uint32_t* pDst, uint32_t* pSrc, uint32_t ndwords, uint32_t wait_finish);
void _GFX_memset32(uint32_t* pDst, uint32_t value, uint32_t ndwords);
void _GFX_memset32_hw(uint32_t* pDst, uint32_t value, uint32_t ndwords, uint32_t wait_finish);
void _GFX_BLIT_const(uint32_t* pDst, uint32_t xdim_dst, uint32_t xmin, uint32_t ymin, uint32_t xmax, uint32_t ymax, uint32_t value);
void _GFX_BLIT_const_hw(uint32_t* pDst, uint32_t xdim_dst, uint32_t xmin, uint32_t ymin, uint32_t xmax, uint32_t ymax, uint32_t value, uint32_t wait_finish);
void GFX_init(gfx_t *pObj);
void GFX_set_background(gfx_t *pObj, uint32_t *pImage, uint32_t image_nx, uint32_t image_ny, uint32_t image_scale_x, uint32_t image_scale_y);
void GFX_frame(gfx_t *pObj, uint32_t sync_mode);
void GFX_show(gfx_t *pObj);
void GFX_copy_front2back(gfx_t *pObj);
void GFX_get_FB_front(gfx_t *pObj, uint32_t **ppFB);
void box_create(box_t *pObj, uint32_t w, uint32_t h);
void GFX_restore(gfx_t *pObj, box_t *pBox, uint32_t posx, uint32_t posy);
void GFX_box_draw_direct(gfx_t *pObj, box_t *pBox, uint32_t posx, uint32_t posy, uint32_t color);
void GFX_box_draw(gfx_t *pObj, box_t *pBox, uint32_t posx, uint32_t posy, uint32_t color);
void GFX_box_draw_bg(gfx_t *pObj, box_t *pBox, uint32_t posx, uint32_t posy, uint32_t color);
void GFX_box_blit_bg(gfx_t *pObj, box_t *pBox, uint32_t pos_x_src, uint32_t pos_y_src, uint32_t pos_x_dst, uint32_t pos_y_dst);
#endif // GFX_H
+472
View File
@@ -0,0 +1,472 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "libsys.h"
#include "mips_ps2.h"
uint32_t ps2_readchar(ps2_if_t *pIF);
const ps2_if_t ps2_if[2] =
{
{ps2_type_unknown, (uint32_t*)SYS_PS2_0_STAT, (uint32_t*)SYS_PS2_0_DATA},
{ps2_type_unknown, (uint32_t*)SYS_PS2_1_STAT, (uint32_t*)SYS_PS2_1_DATA}
};
uint32_t PS2_get_num_if(void)
{
return (sizeof(ps2_if)/sizeof(ps2_if_t));
}
int PS2_readchar(void const *pInst)
{
assert(pInst);
ps2_if_t *pIF = (ps2_if_t*)pInst;
return (int)ps2_readchar(pIF);
}
void PS2_open(void const *pInst)
{
assert(pInst);
ps2_if_t *pIF = (ps2_if_t*)pInst;
PS2_init(pIF);
}
void PS2_close(void const *pInst)
{
}
void PS2_byte_write(ps2_if_t *pIF, uint8_t byte)
{
assert(pIF);
while(!(*pIF->pCTRL & SYS_PS2_BIT_TX_EMPTY));
*pIF->pDATA = (uint32_t)byte;
}
uint32_t PS2_byte_read(ps2_if_t *pIF, uint32_t timeout_ms)
{
assert(pIF);
while(!(*pIF->pCTRL & SYS_PS2_BIT_RX_AVAIL))
{
timeout_ms--;
if (!timeout_ms)
return PS2_ERR_TIMEOUT;
sleep(1);
}
return (uint32_t)*pIF->pDATA;
}
uint32_t PS2_cmd(ps2_if_t *pIF, uint8_t cmd, uint32_t ack_timeout_ms)
{
uint32_t result;
PS2_byte_write(pIF, cmd);
result = PS2_byte_read(pIF, ack_timeout_ms);
if (0xFA != result)
{
printf ("PS2_cmd(%p): no ACK received. Result = %08X\n", pIF->pCTRL, result);
return PS2_ERR_PS2_PREFIX | result;
}
return 0;
}
void PS2_flush(ps2_if_t *pIF)
{
while (!IS_ERROR(PS2_byte_read(pIF, 10)));
}
uint32_t PS2_init(ps2_if_t *pIF)
{
int i;
uint8_t id[2];
pIF->type = ps2_type_unknown;
uint32_t result;
// Disable RX-interrupt
*pIF->pCTRL &= ~SYS_PS2_BIT_RX_INTEN;
printf ("PS2_init(%p) - Initialize... ", pIF->pCTRL);
// Flush buffer
PS2_flush(pIF);
// send RESET
result = PS2_cmd(pIF, 0xFF, 1000);
if (IS_ERROR(result))
{
printf ("Reset error %08X\n", result);
return result;
}
// Read BAT
result = PS2_byte_read(pIF, 1000);
if (0xAA != result)
{
printf ("BAT error %08X\n", result);
return result;
}
printf ("Success\n");
while(1)
{
// Read ID
result = PS2_byte_read(pIF, 10);
if (IS_ERROR(result))
{
// No ID => keyboard
printf ("PS2_init(%p) - Keyboard detected\n", pIF->pCTRL);
// send Get Device-ID
result = PS2_cmd(pIF, 0xF2, 1000);
if (IS_ERROR(result))
{
printf ("Get Device-ID error %08X\n", result);
break;
}
id[0] = PS2_byte_read(pIF, 1000);
id[1] = PS2_byte_read(pIF, 1000);
printf ("PS2_init(%p) - Device-ID: %02X%02X\n", pIF->pCTRL, id[0], id[1]);
// Get Scan code set (phase 1)
result = PS2_cmd(pIF, 0xF0, 1000);
if (IS_ERROR(result))
{
printf ("1. Get Scan code error %08X\n", result);
break;
}
// Get Scan code set (phase 2)
result = PS2_cmd(pIF, 0x00, 1000);
if (IS_ERROR(result))
{
printf ("2. Get Scan code error %08X\n", result);
break;
}
result = PS2_byte_read(pIF, 1000);
printf ("PS2_init(%p) - Current scan code set = %d\n", pIF->pCTRL, result);
// if Scan code SET != 2
if (result != 2)
{
printf ("PS2_init(%p) - Set scan code set = 2\n", pIF->pCTRL);
// Set Scan code set (phase 1)
result = PS2_cmd(pIF, 0xF0, 1000);
if (IS_ERROR(result))
{
printf ("1. Set Scan code error %08X\n", result);
break;
}
// Set Scan code set (phase 2)
result = PS2_cmd(pIF, 0x02, 1000);
if (IS_ERROR(result))
{
printf ("2. Set Scan code error %08X\n", result);
break;
}
}
// Test LEDs
for (i=0; i < 4; i++)
{
result = PS2_cmd(pIF, 0xED, 1000);
if (IS_ERROR(result))
{
printf ("1. LED error %08X\n", result);
break;
}
result = PS2_cmd(pIF, 0x02, 1000);
if (IS_ERROR(result))
{
printf ("2. LED error %08X\n", result);
break;
}
sleep(100);
result = PS2_cmd(pIF, 0xED, 1000);
if (IS_ERROR(result))
{
printf ("1. LED error %08X\n", result);
break;
}
result = PS2_cmd(pIF, 0x04, 1000);
if (IS_ERROR(result))
{
printf ("2. LED error %08X\n", result);
break;
}
sleep(100);
result = PS2_cmd(pIF, 0xED, 1000);
if (IS_ERROR(result))
{
printf ("1. LED error %08X\n", result);
break;
}
result = PS2_cmd(pIF, 0x01, 1000);
if (IS_ERROR(result))
{
printf ("2. LED error %08X\n", result);
break;
}
sleep(100);
}
result = PS2_cmd(pIF, 0xED, 1000);
if (IS_ERROR(result))
{
printf ("1. LED error %08X\n", result);
break;
}
result = PS2_cmd(pIF, 0x00, 1000);
if (IS_ERROR(result))
{
printf ("2. LED error %08X\n", result);
break;
}
pIF->type = ps2_type_keyb;
result = pIF->type;
break;
}
// We got a byte => maybe mouse
if (result == 0)
{
// We got zero => yes, it's a mouse
printf ("PS2_init(%p) - Mouse device detected\n", pIF->pCTRL);
// send Get Device-ID
result = PS2_cmd(pIF, 0xF2, 1000);
if (IS_ERROR(result))
{
printf ("Get Device-ID error %08X\n", result);
break;
}
id[0] = PS2_byte_read(pIF, 1000);
printf ("PS2_init(%p) - Device-ID: %02X\n", pIF->pCTRL, id[0]);
printf ("PS2_init(%p) - Enable stream mode...", pIF->pCTRL);
result = PS2_cmd(pIF, 0xF4, 1000);
if (IS_ERROR(result))
{
printf ("error %08X\n", result);
break;
}
printf ("Success\n");
pIF->type = ps2_type_mouse;
result = pIF->type;
break;
}
}
// Flush buffer
PS2_flush(pIF);
if (IS_ERROR(result))
return result;
// Enable RX-interrupt
*pIF->pCTRL |= SYS_PS2_BIT_RX_INTEN;
return result;
}
// -------------------------------------------------------------
// BEGIN QUICK AND DIRTY
// -------------------------------------------------------------
//keymap for the AT keyboard SG layout
typedef struct
{
uint8_t scancode;
uint8_t unshifted;
uint8_t shifted;
uint8_t altered;
} libsys_key_entry_t;
#define SHIFTED (1<<0)
#define ALTERED (1<<1)
#define CONTROLLED (1<<2)
static const libsys_key_entry_t __keymap_german[] =
{
{0x1c, 'a', 'A', 'a'},
{0x32, 'b', 'B', 'b'},
{0x21, 'c', 'C', 'c'},
{0x23, 'd', 'D', 'd'},
{0x24, 'e', 'E', ''},
{0x2b, 'f', 'F', 'f'},
{0x34, 'g', 'G', 'g'},
{0x33, 'h', 'H', 'h'},
{0x43, 'i', 'I', 'i'},
{0x3b, 'j', 'J', 'j'},
{0x42, 'k', 'K', 'k'},
{0x4b, 'l', 'L', 'l'},
{0x3a, 'm', 'M', 'µ'},
{0x31, 'n', 'N', 'n'},
{0x44, 'o', 'O', 'o'},
{0x4d, 'p', 'P', 'p'},
{0x15, 'q', 'Q', '@'},
{0x2d, 'r', 'R', 'r'},
{0x1b, 's', 'S', 's'},
{0x2c, 't', 'T', 't'},
{0x3c, 'u', 'U', 'u'},
{0x2a, 'v', 'V', 'v'},
{0x1d, 'w', 'W', 'w'},
{0x22, 'x', 'X', 'x'},
{0x1a, 'y', 'Y', 'y'},
{0x35, 'z', 'Z', 'z'},
{0x16, '1', '!', '1'},
{0x1e, '2', '"', '2'},
{0x26, '3', '§', '3'},
{0x25, '4', '$', '4'},
{0x2e, '5', '%', '5'},
{0x36, '6', '&', '6'},
{0x3d, '7', '/', '{'},
{0x3e, '8', '(', '['},
{0x46, '9', ')', ']'},
{0x45, '0', '=', '}'},
{0x4e, 'ß', '?', '\\'},
{0x29, ' ', ' ', ' '},
{0x41, ',', ';', ','},
{0x49, '.', ':', '.'},
{0x4a, '-', '_', '-'},
{0x52, 'ä', 'Ä', 'ä'},
{0x4c, 'ö', 'Ö', 'ö'},
{0x54, 'ü', 'Ü', 'ü'},
{0x5a, '\n', '\n', '\n'}, //RETURN
{0x5b, '+', '*', '~'},
{0x5d, '#', '\'', '#'},
{0x0e, '^', '°', '^'},
{0x61, '<', '>', '|'},
{0x66, '\b', '\b', '\b'},
{0} //sentinel
};
static char __findkey(char scancode, int mode)
{
const libsys_key_entry_t *p = __keymap_german;
while (p->scancode)
{
if (p->scancode == scancode)
{
switch (mode)
{
case SHIFTED:
return p->shifted;
case ALTERED:
return p->altered;
case ALTERED|SHIFTED:
default:
return p->unshifted;
}
}
p++;
}
return 0;
}
#define RELEASE 0x8000
#define SPECIALKEY 0x4000
#define EXTENDED 0x2000
#define X_CONTROLLED 0x0400
#define X_ALTERED 0x0200
#define X_SHIFTED 0x0100
#define CAPS (SPECIALKEY|0x58)
#define F1 (SPECIALKEY|0x05)
#define F2 (SPECIALKEY|0x06)
#define F3 (SPECIALKEY|0x04)
#define F4 (SPECIALKEY|0x0c)
#define F5 (SPECIALKEY|0x03)
#define F6 (SPECIALKEY|0x0b)
#define F7 (SPECIALKEY|0x83)
#define F8 (SPECIALKEY|0x0a)
#define F9 (SPECIALKEY|0x01)
#define F10 (SPECIALKEY|0x09)
#define F11 (SPECIALKEY|0x78)
#define F12 (SPECIALKEY|0x07)
#define ARROW_UP (SPECIALKEY|EXTENDED|0x75)
#define ARROW_DOWN (SPECIALKEY|EXTENDED|0x72)
#define ARROW_LEFT (SPECIALKEY|EXTENDED|0x6b)
#define ARROW_RIGHT (SPECIALKEY|EXTENDED|0x74)
uint32_t ps2_readchar(ps2_if_t *pIF)
{
uint8_t c;
static char mode = 0;
static char nextrelease = 0;
static char extended = 0;
int flags = 0;
int char_valid = 0;
uint8_t key;
while (!(SYS_PS2_BIT_RX_AVAIL & *pIF->pCTRL));
key = *pIF->pDATA & 0xFF;
switch (key)
{
case 0xf0: //release key
nextrelease = 1;
break;
case 0x14: //control key
if (nextrelease)
{
mode &= ~CONTROLLED;
} else
{
mode |= CONTROLLED;
}
nextrelease = 0;
break;
case 0x12: //left SHIFT
case 0x59: //right SHIFT
if (nextrelease)
{
mode &= ~SHIFTED;
} else
{
mode |= SHIFTED;
}
nextrelease = 0;
break;
case 0x11: //left and right ALT (right one also with E0)
if (nextrelease)
{
mode &= ~ALTERED;
} else
{
mode |= ALTERED;
}
nextrelease = 0;
break;
case 0xe0: //extended key following
extended = 1;
break;
default:
if (nextrelease) flags |= RELEASE;
if (extended) flags |= EXTENDED;
flags |= mode << 8;
c = __findkey(key, mode);
char_valid = (c && ((flags & RELEASE) != RELEASE));
nextrelease = 0;
extended = 0;
break;
}
if (char_valid)
{
// fprintf(stderr, "c = %c (%d), flags = 0x%08X, mode = 0x%08X\n", c, c, flags, mode);
return c;
}
return -1;
}
// -------------------------------------------------------------
// END QUICK AND DIRTY
// -------------------------------------------------------------
+47
View File
@@ -0,0 +1,47 @@
#ifndef PS2_H
#define PS2_H
#include "libsys.h"
// --------------------------------------------------
// Types
// --------------------------------------------------
enum
{
ps2_type_unknown = 0,
ps2_type_keyb,
ps2_type_mouse
};
typedef struct _sps2_if_t
{
uint32_t type;
volatile uint32_t *pCTRL;
volatile uint32_t *pDATA;
} ps2_if_t;
// --------------------------------------------------
// Constants
// --------------------------------------------------
#define PS2_MODULE_PREFIX 0x1000000
#define PS2_SUCCESS LSYS_SUCCESS
#define PS2_ERROR (LSYS_ERR_BASE | PS2_MODULE_PREFIX)
#define PS2_ERR_TIMEOUT (PS2_ERROR | 0x0000001)
#define PS2_ERR_PS2_PREFIX (PS2_ERROR | 0x0010000)
// --------------------------------------------------
// Functions
// --------------------------------------------------
uint32_t PS2_get_num_if(void);
uint32_t PS2_init(ps2_if_t *pIF);
void PS2_byte_write(ps2_if_t *pIF, uint8_t byte);
uint32_t PS2_byte_read(ps2_if_t *pIF, uint32_t timeout_ms);
int PS2_readchar(void const *pInst);
void PS2_open(void const *pInst);
void PS2_close(void const *pInst);
uint32_t PS2_cmd(ps2_if_t *pIF, uint8_t cmd, uint32_t ack_timeout_ms);
void PS2_flush(ps2_if_t *pIF);
#endif // PS2_H
+164
View File
@@ -0,0 +1,164 @@
/*
* 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 <assert.h>
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <board.h>
#include "screen.h"
const vga_if_t vga_if =
{
(uint32_t*)SYS_VGA_CTRL, (uint32_t*)SYS_VGA_ASCII, (uint32_t*)SYS_VGA_POSX, (uint32_t*)SYS_VGA_POSY
};
void cg_open(void const *pInst)
{
assert (pInst);
vga_if_t *pIF = (vga_if_t*)pInst;
cg_clr_screen(&vga_if);
}
void cg_close(void const *pInst)
{
}
void cg_writechar(void const *pInst, char c)
{
assert (pInst);
vga_if_t *pIF = (vga_if_t*)pInst;
uint32_t code;
// Output translation
switch(c)
{
case 'Ä':
code = 196;
break;
case 'ä':
code = 228;
break;
case 'Ö':
code = 214;
break;
case 'ö':
code = 246;
break;
case 'Ü':
code = 220;
break;
case 'ü':
code = 252;
break;
case '&':
code = 230;
break;
case '§':
code = 167;
break;
case 'ß':
code = 223;
break;
case '°':
code = 176;
break;
case 'µ':
code = 181;
break;
default:
code = (uint32_t)c;
break;
}
while (!(*pIF->pCTRL & SYS_VGA_BIT_CGRDY));
*pIF->pDATA = code;
if (c == 0x0A)
{
cg_clr_line(pIF);
while (!(*pIF->pCTRL & SYS_VGA_BIT_CGRDY));
*pIF->pDATA = 0x0D;
}
}
void cg_set_csr_x(vga_if_t const *pIF, uint32_t coord)
{
assert (pIF);
// Set cursor
while (!(*pIF->pCTRL & SYS_VGA_BIT_CGRDY));
*pIF->pCSRX = coord;
}
void cg_set_csr_y(vga_if_t const *pIF, uint32_t coord)
{
assert (pIF);
// Set cursor
while (!(*pIF->pCTRL & SYS_VGA_BIT_CGRDY));
*pIF->pCSRY = coord;
}
void cg_clr_line(vga_if_t const *pIF)
{
assert (pIF);
while (!(*pIF->pCTRL & SYS_VGA_BIT_CGRDY));
*pIF->pCTRL |= SYS_VGA_BIT_CLRLINE;
}
void cg_clr_screen(vga_if_t const *pIF)
{
assert (pIF);
while (!(*pIF->pCTRL & SYS_VGA_BIT_CGRDY));
*pIF->pCTRL |= SYS_VGA_BIT_CLRSCR;
// Cursor home
while (!(*pIF->pCTRL & SYS_VGA_BIT_CGRDY));
*pIF->pCSRX = 0;
while (!(*pIF->pCTRL & SYS_VGA_BIT_CGRDY));
*pIF->pCSRY = 0;
}
uint32_t Screen_get_resx(void)
{
uint32_t volatile *pVGA_res = (uint32_t*)SYS_VGA_RES;
return (0xFFF & (*pVGA_res >> 0));
}
uint32_t Screen_get_resy(void)
{
uint32_t volatile *pVGA_res = (uint32_t*)SYS_VGA_RES;
return (0xFFF & (*pVGA_res >> 12));
}
uint32_t Screen_get_fps(void)
{
uint32_t volatile *pVGA_res = (uint32_t*)SYS_VGA_RES;
return (0xFF & (*pVGA_res >> 24));
}
+47
View File
@@ -0,0 +1,47 @@
/*
* 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: screen.h
* Author: jens
*
* Created on 8. Januar 2017, 14:22
*/
#ifndef SCREEN_H
#define SCREEN_H
typedef struct _svga_if_t
{
volatile uint32_t *pCTRL;
volatile uint32_t *pDATA;
volatile uint32_t *pCSRX;
volatile uint32_t *pCSRY;
} vga_if_t;
#ifdef __cplusplus
extern "C" {
#endif
void cg_set_csr_x(vga_if_t const *pIF, uint32_t coord);
void cg_set_csr_y(vga_if_t const *pIF, uint32_t coord);
void cg_clr_line(vga_if_t const *pIF);
void cg_clr_screen(vga_if_t const *pIF);
uint32_t Screen_get_resx(void);
uint32_t Screen_get_resy(void);
uint32_t Screen_get_fps(void);
void cg_writechar(void const *pInst, char c);
void cg_open(void const *pInst);
void cg_close(void const *pInst);
#ifdef __cplusplus
}
#endif
#endif /* SCREEN_H */
+86
View File
@@ -0,0 +1,86 @@
#include <stdio.h>
#include "libsys.h"
#include "xcpt.h"
/* 10 digits + 1 sign + 1 trailing nul */
static char itoa_buf[12];
char *itoa(int i)
{
char *pos = itoa_buf + sizeof(itoa_buf) - 1;
unsigned int u;
int negative = 0;
if (i < 0)
{
negative = 1;
u = ((unsigned int)(-(1+i))) + 1;
}
else
{
u = i;
}
*pos = 0;
do
{
*--pos = '0' + (u % 10);
u /= 10;
} while (u);
if (negative)
{
*--pos = '-';
}
return pos;
}
int syscalls_handler(struct xcptcontext * xcp)
{
int syscall_code;
char *pStr, buf[33];
syscall_code = xcp->regs[2];
switch(syscall_code)
{
case 1: // print integer
sputs(itoa(xcp->regs[4]));
break;
case 4: // print string
pStr = (char*)xcp->regs[4];
sputs(pStr);
break;
case 5: // read integer
pStr = fgets(buf, sizeof(buf), stdin);
xcp->regs[2] = atoi(pStr);
break;
case 8: // read string
pStr = (char*)xcp->regs[4];
fgets(pStr, xcp->regs[5], stdin);
break;
case 10: // exit
_exit(0);
break;
default:
sputs("\nUnknown syscall (");print_word(syscall_code);sputs(") at ");print_word(xcp->epc);sputs("\n");
break;
}
xcp->epc += 4; // set return address to instruction after syscall
return 0;
}
void syscalls_init(void)
{
xcpt_register(EXC_SYSCALL, syscalls_handler);
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef SYSCALLS_H
#define SYSCALLS_H
#include <stdint.h>
void syscalls_init(void);
#endif // SYSCALLS_H
+43
View File
@@ -0,0 +1,43 @@
/*
* 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>
#include "uart.h"
// ------------------------------------
// Low-level I/O
// ------------------------------------
void UART_setbaud(void const *pInst, uint32_t baudrate)
{
if (pInst)
{
uart_if_t *pReg = (uart_if_t*)pInst;
*pReg->pBAUD = UART_CALC_BAUD(baudrate);
}
}
int UART_readchar(void const *pInst)
{
if (pInst)
{
uart_if_t *pReg = (uart_if_t*)pInst;
if (SYS_UART_BIT_RX_AVAIL & *pReg->pCTRL)
{
return (*pReg->pDATA & 0xFF);
}
}
return -1;
}
void UART_writechar(void const *pInst, char c)
{
if (pInst)
{
uart_if_t *pReg = (uart_if_t*)pInst;
while((SYS_UART_BIT_TX_HALFFULL & *pReg->pCTRL) != 0);
*pReg->pDATA = (uint32_t)c;
}
}
+42
View File
@@ -0,0 +1,42 @@
/*
* 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: uart.h
* Author: jens
*
* Created on 9. Januar 2017, 08:05
*/
#include <stdint.h>
#ifndef UART_H
#define UART_H
#define UART_CALC_BAUD(b) \
(((10*CPU_FREQ_HZ)/((16*b) + 5))/10 - 1)
typedef struct _suart_if_t
{
volatile uint32_t *pCTRL;
volatile uint32_t *pDATA;
volatile uint32_t *pBAUD;
} uart_if_t;
#ifdef __cplusplus
extern "C" {
#endif
int UART_readchar(void const *pInst);
void UART_writechar(void const *pInst, char c);
#ifdef __cplusplus
}
#endif
#endif /* UART_H */
+150
View File
@@ -0,0 +1,150 @@
#include <sys/times.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include "libsys.h"
#include "xcpt.h"
#include "irq.h"
static fp_xcpt_t g_xcpt_handler[MAX_NUM_XCPT] = {NULL};
char const * const _xcpt_code_str[MAX_NUM_XCPT] =
{
"Interrupt", "Mod", "TLBL", "TLBS", "AdEL", "AdES", "IBE", "DBE",
"Syscall", "Break", "RI", "CpU", "Ov", "Tr", "NCD/VCEI", "MC/FPE",
"Res(16)", "Res(17)", "Res(18)", "Res(19)", "Res(20)", "Res(21)", "Res(22)", "WATCH",
"Res(24)", "Res(25)", "Res(26)", "Res(27)", "Res(28)", "Res(29)", "Res(30)", "VCED"
};
void xcpt_register(int xcpt_num, fp_xcpt_t fp)
{
if ((xcpt_num >= EXC_INT) && (xcpt_num <= EXC_VCED))
g_xcpt_handler[xcpt_num] = fp;
}
void xcpt_registers_print(struct xcptcontext * xcp)
{
xcpt_registers_print_with_change(xcp, xcp);
}
void xcpt_registers_print_with_change(struct xcptcontext * xcp, struct xcptcontext * xcp_last)
{
PRINT_REG_CHG(" Status : ", xcp->sr, xcp_last->sr);
PRINT_REG_CHG(" Cause : ", xcp->cr, xcp_last->cr);
PRINT_REG_CHG(" EPC : ", xcp->epc, xcp_last->epc);
PRINT_REG_CHG("BadAddr : ", xcp->baddr, xcp_last->baddr);
sputs("\n");
PRINT_REG_CHG(" MDLO : ", xcp->mdlo, xcp_last->mdlo);
PRINT_REG_CHG(" MDHI : ", xcp->mdhi, xcp_last->mdhi);
sputs("\n");
sputs("Registers:\n");
PRINT_REG_CHG(" 0 (ze) : ", xcp->regs[0], xcp_last->regs[0]);
PRINT_REG_CHG(" 1 (at) : ", xcp->regs[1], xcp_last->regs[1]);
PRINT_REG_CHG(" 2 (v0) : ", xcp->regs[2], xcp_last->regs[2]);
PRINT_REG_CHG(" 3 (v1) : ", xcp->regs[3], xcp_last->regs[3]);
sputs("\n");
PRINT_REG_CHG(" 4 (a0) : ", xcp->regs[4], xcp_last->regs[4]);
PRINT_REG_CHG(" 5 (a1) : ", xcp->regs[5], xcp_last->regs[5]);
PRINT_REG_CHG(" 6 (a2) : ", xcp->regs[6], xcp_last->regs[6]);
PRINT_REG_CHG(" 7 (a3) : ", xcp->regs[7], xcp_last->regs[7]);
sputs("\n");
PRINT_REG_CHG(" 8 (t0) : ", xcp->regs[8], xcp_last->regs[8]);
PRINT_REG_CHG(" 9 (t1) : ", xcp->regs[9], xcp_last->regs[9]);
PRINT_REG_CHG("10 (t2) : ", xcp->regs[10], xcp_last->regs[10]);
PRINT_REG_CHG("11 (t3) : ", xcp->regs[11], xcp_last->regs[11]);
sputs("\n");
PRINT_REG_CHG("12 (t4) : ", xcp->regs[12], xcp_last->regs[12]);
PRINT_REG_CHG("13 (t5) : ", xcp->regs[13], xcp_last->regs[13]);
PRINT_REG_CHG("14 (t6) : ", xcp->regs[14], xcp_last->regs[14]);
PRINT_REG_CHG("15 (t7) : ", xcp->regs[15], xcp_last->regs[15]);
sputs("\n");
PRINT_REG_CHG("16 (s0) : ", xcp->regs[16], xcp_last->regs[16]);
PRINT_REG_CHG("17 (s1) : ", xcp->regs[17], xcp_last->regs[17]);
PRINT_REG_CHG("18 (s2) : ", xcp->regs[18], xcp_last->regs[18]);
PRINT_REG_CHG("19 (s3) : ", xcp->regs[19], xcp_last->regs[19]);
sputs("\n");
PRINT_REG_CHG("20 (s4) : ", xcp->regs[20], xcp_last->regs[20]);
PRINT_REG_CHG("21 (s5) : ", xcp->regs[21], xcp_last->regs[21]);
PRINT_REG_CHG("22 (s6) : ", xcp->regs[22], xcp_last->regs[22]);
PRINT_REG_CHG("23 (s7) : ", xcp->regs[23], xcp_last->regs[23]);
sputs("\n");
PRINT_REG_CHG("24 (t8) : ", xcp->regs[24], xcp_last->regs[24]);
PRINT_REG_CHG("25 (t9) : ", xcp->regs[25], xcp_last->regs[25]);
PRINT_REG_CHG("26 (k0) : ", xcp->regs[26], xcp_last->regs[26]);
PRINT_REG_CHG("27 (k1) : ", xcp->regs[27], xcp_last->regs[27]);
sputs("\n");
PRINT_REG_CHG("28 (gp) : ", xcp->regs[28], xcp_last->regs[28]);
PRINT_REG_CHG("29 (sp) : ", xcp->regs[29], xcp_last->regs[29]);
PRINT_REG_CHG("30 (fp) : ", xcp->regs[30], xcp_last->regs[30]);
PRINT_REG_CHG("31 (ra) : ", xcp->regs[31], xcp_last->regs[31]);
sputs("\n");
}
int xcpt_get_type(struct xcptcontext * xcp)
{
return (xcp->cr >> 2) & 0x1F;
}
void xcpt_exctype_print(struct xcptcontext * xcp)
{
int exc_code;
exc_code = xcpt_get_type(xcp);
sputs(_xcpt_code_str[exc_code]);
}
int _xcpt_dispatch(struct xcptcontext * xcp)
{
int result;
int xcpt_code;
xcpt_code = (xcp->cr >> 2) & 0x1F;
result = XCPT_ERR_NOTHANDLED;
if (g_xcpt_handler[xcpt_code])
{
result = (g_xcpt_handler[xcpt_code])(xcp);
}
return result;
}
int _xcpt_deliver(struct xcptcontext * _xcp)
{
int exc_code;
volatile int *pInstr;
/* This function gets called by the low-level exception handler. */
if (_xcpt_dispatch(_xcp) == XCPT_ERR_NOTHANDLED)
{
sputs("\n");
xcpt_registers_print(_xcp);
sputs("\n");
exc_code = (_xcp->cr >> 2) & 0x1F;
if (_xcp->cr & 0x80000000)
{
pInstr = (int*)(_xcp->epc + 4);
}
else
{
pInstr = (int*)(_xcp->epc);
}
sputs("Unhandled exception <");xcpt_exctype_print(_xcp); sputs("> at PC : ");print_word((int)pInstr);sputs("\n");
sputs("Instruction at exception address : ");
print_word(*pInstr);
sputs("\n");
sputs("Terminate.\n");
_exit(exc_code);
}
return 0;
}
+59
View File
@@ -0,0 +1,59 @@
#ifndef XCPT_H
#define XCPT_H
#define MAX_NUM_XCPT 32
#define XCPT_ERR_NOTHANDLED 0x80000000
typedef enum
{
EXC_INT = 0, EXC_MOD = 1, EXC_TLBL = 2, EXC_TLBS = 3, EXC_ADEL = 4, EXC_ADES = 5,
EXC_IBE = 6, EXC_DBE = 7, EXC_SYSCALL = 8, EXC_BP = 9, EXC_RI = 10, EXC_CPU = 11,
EXC_OV = 12, EXC_TRAP = 13, EXC_VCEI = 14, EXC_FPE = 15, EXC_C2E = 16, EXC_WATCH = 23, EXC_VCED = 31
} EXCEPTION_CODE;
typedef unsigned int reg_t;
typedef struct xcptcontext
{
/* This is the exception context frame that is passed to the exception
handlers. It gets filled in by the low-level exception handler in
"machine.S". An assembler version of this structure can be found at the
bottom of "machine.H".*/
reg_t sr; /* Status Register */
reg_t cr; /* Cause Register */
reg_t epc; /* PC at time of exception. */
reg_t baddr;
reg_t regs[32]; /* Copy of all general purpose registers */
reg_t mdlo; /* HI/LO registers (used for memory management) */
reg_t mdhi;
reg_t count; /* Timer registers */
reg_t compare;
struct xcptcontext * prev; /* To link exceptions. (unused for now) */
unsigned xclass; /* Priority class of this exception. (unused for now). */
} EXCEPTION_CONTEXT;
typedef int (*fp_xcpt_t)(struct xcptcontext * xcp);
#define PRINT_REG(tag_str, reg) \
sputs(tag_str); \
print_word(reg); \
sputs(" ");
#define PRINT_REG_CHG(tag_str, reg, reg_last) \
sputs(tag_str); \
print_word(reg); \
sputs(reg != reg_last ? "*" : " "); \
sputs(" ");
// Public functions
void xcpt_register(int xcpt_num, fp_xcpt_t fp);
int xcpt_get_type(struct xcptcontext * xcp);
void xcpt_registers_print(struct xcptcontext * xcp);
void xcpt_registers_print_with_change(struct xcptcontext * xcp, struct xcptcontext * xcp_last);
void xcpt_exctype_print(struct xcptcontext * xcp);
#endif // XCPT_H