ping-pong

This commit is contained in:
cxy004 2021-08-15 16:50:28 +08:00
parent f8f732bb70
commit bb76bfece2
13 changed files with 2591 additions and 0 deletions

View File

@ -0,0 +1,78 @@
RM := rm -f
ifeq ($(OS),Windows_NT)
# Windows Host
GCCPREFIX ?= mips-mti-elf-
else
#GCCPREFIX := mipsel-linux-gnu-
GCCPREFIX ?= mips-mti-elf-
endif
QEMU := qemu-system-mipsel
LD := $(GCCPREFIX)ld
CC := $(GCCPREFIX)gcc
MODULE := init
OBJDIR := obj
INCLUDE := include
SRCDIR := kern
LDSCRIPT := kern/kernel.ld
SRC := $(foreach sdir, $(SRCDIR), $(wildcard $(sdir)/*.S))
OBJ := $(patsubst $(SRCDIR)/%.S, $(OBJDIR)/%.o, $(SRC))
TARGET := kernel.elf
ASFLAG := -D__ASSEMBLY__ -EL -g -mips32r2 -mno-abicalls -mno-shared
override ON_FPGA ?= y
ifeq ($(ON_FPGA), y)
MACH_DEF = -DMACH_FPGA
else
MACH_DEF = -DMACH_QEMU
endif
ASFLAG += $(MACH_DEF)
override EN_INT ?= y
ifeq ($(EN_INT), y)
ASFLAG += -DENABLE_INT
EN_TLB = n
endif
override EN_TLB ?= n
ifeq ($(EN_TLB), y)
ASFLAG += -DENABLE_TLB
endif
CONFIG_FILE := .config_$(ON_FPGA)_$(EN_INT)_$(EN_TLB)
.PHONY: all clean checkdirs show-utest commits-num sim
all: $(TARGET) kernel.bin show-utest
$(CONFIG_FILE):
@rm -f .config_*
touch $@
$(TARGET): checkdirs $(OBJ) $(LDSCRIPT)
$(LD) $(OBJ) -T$(LDSCRIPT)
$(OBJ): $(OBJDIR)/%.o : $(SRCDIR)/%.S $(CONFIG_FILE)
$(CC) -o $@ $< -c -I$(INCLUDE) $(ASFLAG)
checkdirs: $(OBJDIR)
$(OBJDIR):
test -d $@ || mkdir $@
kernel.bin: $(TARGET)
@$(GCCPREFIX)objcopy -j .text -j .rodata -j .data -O binary -v $< kernel.bin
@$(GCCPREFIX)objdump -lD $< > kernel.s
show-utest: $(TARGET)
@$(GCCPREFIX)objdump -D $< | grep "^[0-9a-f]\{8\} <UTEST_" | grep -n --color=auto 'UTEST_'
sim: $(TARGET)
$(QEMU) -M mipssim -m 8M -kernel $< -nographic -monitor none -serial tcp::6666,server -s
commits-num:
@git log --pretty=format:"commit %H" | grep -c 'commit'
clean:
-$(RM) -r $(OBJDIR)

View File

@ -0,0 +1,55 @@
#include <regdef.h>
.set noreorder
.set noat
.section .text.init
.p2align 2
la t0, _text_ebase_begin | 0xa0000000
la t1, _text_ebase_end | 0xa0000000
la t2, _text_ebase_begin | 0xbfc00000
la t3, _text_code_begin | 0xa0000000
la t4, _text_code_end | 0xa0000000
la t5, _text_code_begin | 0xbfc00000
la t6, _data_begin | 0xa0000000
la t7, _data_end | 0xa0000000
la t8, _data_begin | 0xbfc00000
la t9, START
/* copy .text.ebase */
1:
lw k0, 0(t2)
addiu t2, t2, 4
sw k0, 0(t0)
addiu t0, t0, 4
bne t0, t1, 1b
nop
/* copy .text.code */
2:
lw k1, 0(t5)
addiu t5, t5, 4
sw k1, 0(t3)
addiu t3, t3, 4
bne t3, t4, 2b
nop
/* copy .data */
beq t6, t7, 4f
nop
3:
lw k0, 0(t8)
addiu t8, t8, 4
sw k0, 0(t6)
addiu t6, t6, 4
bne t6, t7, 3b
nop
4:
jr t9
.set reorder
.set at

View File

@ -0,0 +1,26 @@
#include <regdef.h>
#include <mipsregs.h>
#include <game.h>
.set noreorder
.set noat
.text
.p2align 2
.global GAME_START
GAME_START:
nop
nop
nop
nop
nop
nop
nop
nop
j GAME_START
.set reorder
.set at

View File

@ -0,0 +1,44 @@
ENTRY(INITLOCATE)
OUTPUT("kernel.elf")
OUTPUT_ARCH("mips:isa32r2")
OUTPUT_FORMAT("elf32-tradlittlemips")
PROVIDE(SPVR_STACK_INIT = 0x807E0000);
PROVIDE(GAME_STACK_INIT = 0x807F0000);
PROVIDE(UART0 = 0xBFE40000);
PROVIDE(UART1 = 0xBFE40010);
SECTIONS
{
. = 0x807F0000;
.bss : {
_sbss = .;
*(.bss)
. = ALIGN(4);
_ebss = .;
}
. = 0x80000000;
.text : {
*(.text.init)
. = 0x1000;
_text_ebase_begin = .;
*(.text.ebase)
. = 0x1180;
*(.text.ebase180)
_text_ebase_end = .;
. = ALIGN(0x1000);
_text_code_begin = .;
*(.text)
. = ALIGN(0x1000);
_text_code_end = .;
}
_data_begin = .;
.rodata : {
*(.rodata)
. = ALIGN(4);
}
.data : {
*(.data)
. = ALIGN(4);
}
_data_end = .;
}

View File

@ -0,0 +1,209 @@
#include <regdef.h>
#include <mipsregs.h>
#include <exception.h>
.set noreorder
.set noat
.section .rodata
.p2align 2
pingpong_hello:
.asciz "Ping Pong."
.section .data
.p2align 2
.global TCBT
TCBT:
.global SUPV_TCB
SUPV_TCB:
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
// gp
.word 0
// sp
.word SPVR_STACK_INIT
// fp
.word SPVR_STACK_INIT
// ra
.word 0
// Count
.word 0
// Compare
.word 0
// STATUS
.word STATUSF_IP5 | STATUSF_IP4 | ST0_IE
// EPC
.word SUPV_START
.global GAME_TCB
GAME_TCB:
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word DEFAULT_INT_HANDLER
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
// gp
.word 0
// sp
.word SPVR_STACK_INIT
// fp
.word SPVR_STACK_INIT
// ra
.word 0
// Count
.word 0
// Compare
.word 33000000 / 2
// STATUS
.word STATUSF_IP7 | STATUSF_IP5 | STATUSF_IP4 | ST0_IE
// EPC
.word GAME_START
.global current_thread
current_thread:
.word 0
.global next_thread
next_thread:
.word GAME_TCB
.section .text
.p2align 2
.global START
START:
la t0, _sbss
la t1, _ebss
beq t0, t1, bss_init_done
nop
bss_init:
sw zero, 0(t0)
addiu t0, t0, 4
bne t0, t1, bss_init
nop
bss_init_done:
la t2, _text_ebase_begin
mtc0 t2, CP0_EBASE
/* init serial */
la t0, UART0
// FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1
li t1, 0x1 | 0x2 | 0x4 | 0x0
sb t1, 2(t0) // FIFO
li t1, 0x80 // CFCR_DLAB, divisor latch
sb t1, 3(t0) // CFCR
li t1, 0x23 // modify Baud 57600
sb t1, 0(t0) // DATA
srl t1, 8
sb t1, 1(t0) // IER
li t1, 0x3 // CFCR_8BITS
sb t1, 3(t0) // CFCR
// MCR_DTR | MCR_RTS
li t1, 0x1 | 0x2
sb t1, 4(t0) // MCR
li t1, 0x1 // IRxE
sb t1, 1(t0) // IER
la t0, UART1
// FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1
li t1, 0x1 | 0x2 | 0x4 | 0x0
sb t1, 2(t0) // FIFO
li t1, 0x80 // CFCR_DLAB, divisor latch
sb t1, 3(t0) // CFCR
li t1, 0x23 // modify Baud 57600
sb t1, 0(t0) // DATA
srl t1, 8
sb t1, 1(t0) // IER
li t1, 0x3 // CFCR_8BITS
sb t1, 3(t0) // CFCR
// MCR_DTR | MCR_RTS
li t1, 0x1 | 0x2
sb t1, 4(t0) // MCR
li t1, 0x1 // IRxE
sb t1, 1(t0) // IER
la s0, pingpong_hello
la a0, UART0
lb a1, 0(s0)
0:
jal WRITESERIAL
addiu s0, s0, 0x1
lb a0, 0(s0)
bne a0, zero, 0b
nop
j RESTART_LOAD
nop
.set reorder
.set at

View File

@ -0,0 +1,26 @@
#include <regdef.h>
#include <mipsregs.h>
#include <game.h>
.set noreorder
.set noat
.text
.p2align 2
.global SUPV_START
SUPV_START:
nop
nop
nop
nop
nop
nop
nop
nop
j SUPV_START
.set reorder
.set at

View File

@ -0,0 +1,195 @@
#include <regdef.h>
#include <mipsregs.h>
#include <exception.h>
.set noreorder
.set noat
.p2align 2
.section .text.ebase180
mfc0 k1, CP0_STATUS
la k0, 0
mtc0 k0, CP0_STATUS
lui k0, %hi(current_thread)
lw k0, %lo(current_thread)(k0)
sw k1, TF_STATUS(k0)
mfc0 k0, CP0_CAUSE
andi k1, k0, 0x00FC
bnez k1, SYSCALL
nop
mfc0, k1, CP0_STATUS
and k0, k0, k1
7:
andi k1, k0, CAUSEF_IP7
beqz k1, 6f
nop
lui k0, %hi(current_thread)
lw k0, %lo(current_thread)(k0)
lw k1, TF_INTHDL7(k0)
jr k1
6:
andi k1, k0, CAUSEF_IP6
beqz k1, 5f
nop
lui k0, %hi(current_thread)
lw k0, %lo(current_thread)(k0)
lw k1, TF_INTHDL6(k0)
jr k1
5:
andi k1, k0, CAUSEF_IP5
beqz k1, 4f
nop
lui k0, %hi(current_thread)
lw k0, %lo(current_thread)(k0)
lw k1, TF_INTHDL5(k0)
jr k1
4:
andi k1, k0, CAUSEF_IP4
beqz k1, 3f
nop
lui k0, %hi(current_thread)
lw k0, %lo(current_thread)(k0)
lw k1, TF_INTHDL4(k0)
jr k1
3:
andi k1, k0, CAUSEF_IP3
beqz k1, 2f
nop
lui k0, %hi(current_thread)
lw k0, %lo(current_thread)(k0)
lw k1, TF_INTHDL3(k0)
jr k1
2:
andi k1, k0, CAUSEF_IP2
beqz k1, 1f
nop
lui k0, %hi(current_thread)
lw k0, %lo(current_thread)(k0)
lw k1, TF_INTHDL2(k0)
jr k1
1:
andi k1, k0, CAUSEF_IP1
beqz k1, 0f
nop
lui k0, %hi(current_thread)
lw k0, %lo(current_thread)(k0)
lw k1, TF_INTHDL1(k0)
jr k1
0:
lui k0, %hi(current_thread)
lw k0, %lo(current_thread)(k0)
lw k1, TF_INTHDL0(k0)
jr k1
SYSCALL:
li k1, EX_SYS
bne k0, k1, DEFAULT_INT_HANDLER
nop
mfc0 k1, C0_EPC
addiu k1, k1, 0x4
mtc0 k1, C0_EPC
.global DEFAULT_INT_HANDLER
DEFAULT_INT_HANDLER:
j RESTART
nop
.global RESTART_SAVE
RESTART_SAVE:
lui k0, %hi(current_thread)
lw k0, %lo(current_thread)(k0)
sw AT, TF_AT(k0)
sw v0, TF_v0(k0)
sw v1, TF_v1(k0)
sw a0, TF_a0(k0)
sw a1, TF_a1(k0)
sw a2, TF_a2(k0)
sw a3, TF_a3(k0)
sw t0, TF_t0(k0)
sw t1, TF_t1(k0)
sw t2, TF_t2(k0)
sw t3, TF_t3(k0)
sw t4, TF_t4(k0)
sw t5, TF_t5(k0)
sw t6, TF_t6(k0)
sw t7, TF_t7(k0)
sw s0, TF_s0(k0)
sw s1, TF_s1(k0)
sw s2, TF_s2(k0)
sw s3, TF_s3(k0)
sw s4, TF_s4(k0)
sw s5, TF_s5(k0)
sw s6, TF_s6(k0)
sw s7, TF_s7(k0)
sw t8, TF_t8(k0)
sw t9, TF_t9(k0)
sw gp, TF_gp(k0)
sw sp, TF_sp(k0)
mfc0 k1, CP0_COUNT
sw fp, TF_fp(k0)
sw k1, TF_COUNT(k0)
mfc0 k1, CP0_COMPARE
sw ra, TF_ra(k0)
sw k1, TF_COMPARE(k0)
sw k1, TF_EPC(k0)
.global RESTART_LOAD
RESTART_LOAD:
lui k0, %hi(next_thread)
lui k1, %hi(current_thread)
lw k0, %lo(next_thread)(k0)
sw k0, %lo(current_thread)(k1)
lw AT, TF_AT(k0)
lw v0, TF_v0(k0)
lw v1, TF_v1(k0)
lw a0, TF_a0(k0)
lw a1, TF_a1(k0)
lw a2, TF_a2(k0)
lw a3, TF_a3(k0)
lw t0, TF_t0(k0)
lw t1, TF_t1(k0)
lw t2, TF_t2(k0)
lw t3, TF_t3(k0)
lw t4, TF_t4(k0)
lw t5, TF_t5(k0)
lw t6, TF_t6(k0)
lw t7, TF_t7(k0)
lw s0, TF_s0(k0)
lw s1, TF_s1(k0)
lw s2, TF_s2(k0)
lw s3, TF_s3(k0)
lw s4, TF_s4(k0)
lw s5, TF_s5(k0)
lw s6, TF_s6(k0)
lw s7, TF_s7(k0)
lw t8, TF_t8(k0)
lw t9, TF_t9(k0)
lw gp, TF_gp(k0)
lw sp, TF_sp(k0)
lw fp, TF_fp(k0)
lw ra, TF_ra(k0)
lw k1, TF_COUNT(k0)
mtc0 k1, CP0_COUNT
lw k1, TF_COMPARE(k0)
mtc0 k1, CP0_COMPARE
lw k1, TF_EPC(k0)
mtc0 k1, CP0_EPC
.global RESTART
RESTART:
lui k0, %hi(current_thread)
lw k0, %lo(current_thread)(k0)
lw k1, TF_STATUS(k0)
mtc0 k1, CP0_STATUS
eret
j RESTART
nop
.set reorder
.set at

View File

@ -0,0 +1,38 @@
#include <regdef.h>
.set noreorder
.set noat
.text
.p2align 2
.global WRITESERIAL
WRITESERIAL:
.TESTW:
lb t0, 5(a0)
andi t0, t0, 0x20
beqz t0, .TESTW
nop
.WSERIAL:
sb a1, 0(a0)
jr ra
nop
.global READSERIAL
READSERIAL:
.TESTR:
lb t0, 5(a0)
andi t0, t0, 0x01
bnez t0, .RSERIAL
nop
j .TESTR
nop
.RSERIAL:
lb v0, 0(a0)
jr ra
nop
.set reorder
.set at

View File

@ -0,0 +1,59 @@
#ifndef EXCEPTION_H
#define EXCEPTION_H
#define EX_MASK 0xFC
#define EX_INT (0x00 << 2)
#define EX_MOD (0x01 << 2)
#define EX_TLBL (0x02 << 2)
#define EX_TLBS (0x03 << 2)
#define EX_ADEL (0x04 << 2)
#define EX_ADES (0x05 << 2)
#define EX_SYS (0x08 << 2)
#define EX_BP (0x09 << 2)
#define EX_RI (0x0A << 2)
#define EX_OV (0x0C << 2)
#define TF_SIZE 0xA4
#define TF_INTHDL0 0x00
#define TF_INTHDL1 0x04
#define TF_INTHDL2 0x08
#define TF_INTHDL3 0x0C
#define TF_INTHDL4 0x10
#define TF_INTHDL5 0x14
#define TF_INTHDL6 0x18
#define TF_INTHDL7 0x1C
#define TF_AT 0x20
#define TF_v0 0x24
#define TF_v1 0x28
#define TF_a0 0x2C
#define TF_a1 0x30
#define TF_a2 0x34
#define TF_a3 0x38
#define TF_t0 0x3C
#define TF_t1 0x40
#define TF_t2 0x44
#define TF_t3 0x48
#define TF_t4 0x4C
#define TF_t5 0x50
#define TF_t6 0x54
#define TF_t7 0x58
#define TF_s0 0x5C
#define TF_s1 0x60
#define TF_s2 0x64
#define TF_s3 0x68
#define TF_s4 0x6C
#define TF_s5 0x70
#define TF_s6 0x74
#define TF_s7 0x78
#define TF_t8 0x7C
#define TF_t9 0x80
#define TF_gp 0x84
#define TF_sp 0x88
#define TF_fp 0x8C
#define TF_ra 0x90
#define TF_COUNT 0x94
#define TF_COMPARE 0x98
#define TF_STATUS 0x9C
#define TF_EPC 0xA0
#endif

View File

@ -0,0 +1,11 @@
#ifndef GAME_H
#define GAME_H
#define KB_UP 0xCB
#define KB_DOWN 0xCF
#define KB_PAUSE 0xD3
#define KB_RESUME 0xD7
#define KB_SCORE 0xEB
#define KB_RESET 0xF3
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/*
* 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 */
#endif /* _ASM_REGDEF_H */

View File

@ -0,0 +1,428 @@
#!/usr/bin/env python3
# -*- encoding=utf-8 -*-
import argparse
import math
import os
import platform
import re
import select
import socket
import string
import struct
import subprocess
import sys
import tempfile
from timeit import default_timer as timer
try:
import serial
except:
print("Please install pyserial")
exit(1)
try:
import readline
except:
pass
try: type(raw_input)
except NameError: raw_input = input
CCPREFIX = "mips-mti-elf-"
if 'GCCPREFIX' in os.environ:
CCPREFIX=os.environ['GCCPREFIX']
CMD_ASSEMBLER = CCPREFIX + 'as'
CMD_DISASSEMBLER = CCPREFIX + 'objdump'
CMD_BINARY_COPY = CCPREFIX + 'objcopy'
Reg_alias = ['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/jp', 'k0', 'k1', 'gp', 'sp', 'fp/s8', 'ra']
def test_programs():
tmp = tempfile.NamedTemporaryFile()
for prog in [CMD_ASSEMBLER, CMD_DISASSEMBLER, CMD_BINARY_COPY]:
try:
subprocess.check_call([prog, '--version'], stdout=tmp)
except:
print("Couldn't run", prog)
print("Please check your PATH env", os.environ["PATH"].split(os.pathsep))
tmp.close()
return False
tmp.close()
return True
def output_binary(binary):
if hasattr(sys.stdout,'buffer'): # Python 3
sys.stdout.buffer.write(binary)
else:
sys.stdout.write(binary)
# convert 32-bit int to byte string of length 4, from LSB to MSB
def int_to_byte_string(val):
return struct.pack('<I', val)
def byte_string_to_int(val):
return struct.unpack('<I', val)[0]
# invoke assembler to compile instructions (in little endian MIPS32)
# returns a byte string of encoded instructions, from lowest byte to highest byte
# returns empty string on failure (in which case assembler messages are printed to stdout)
def multi_line_asm(instr):
tmp_asm = tempfile.NamedTemporaryFile(delete=False)
tmp_obj = tempfile.NamedTemporaryFile(delete=False)
tmp_binary = tempfile.NamedTemporaryFile(delete=False)
try:
tmp_asm.write((instr + "\n").encode('utf-8'))
tmp_asm.close()
tmp_obj.close()
tmp_binary.close()
subprocess.check_output([
CMD_ASSEMBLER, '-EL', '-mips32r2', tmp_asm.name, '-o', tmp_obj.name])
subprocess.check_call([
CMD_BINARY_COPY, '-j', '.text', '-O', 'binary', tmp_obj.name, tmp_binary.name])
with open(tmp_binary.name, 'rb') as f:
binary = f.read()
return binary
except subprocess.CalledProcessError as e:
print(e.output)
except:
print("Unexpected error:", sys.exc_info()[0])
finally:
os.remove(tmp_asm.name)
# object file won't exist if assembler fails
if os.path.exists(tmp_obj.name):
os.remove(tmp_obj.name)
os.remove(tmp_binary.name)
return ''
# invoke objdump to disassemble single instruction
# accepts encoded instruction (exactly 4 bytes), from least significant byte
# objdump does not seem to report errors so this function does not guarantee
# to produce meaningful result
def single_line_disassmble(binary_instr, addr):
assert(len(binary_instr) == 4)
tmp_binary = tempfile.NamedTemporaryFile(delete=False)
tmp_binary.write(binary_instr)
tmp_binary.close()
raw_output = subprocess.check_output([
CMD_DISASSEMBLER, '-D', '-b', 'binary',
'--adjust-vma=' + str(addr),
'-m', 'mips:isa32r2', tmp_binary.name])
# the last line should be something like:
# 0: 21107f00 addu v0,v1,ra
result = raw_output.strip().split(b'\n')[-1].split(None, 2)[-1]
os.remove(tmp_binary.name)
return result.decode('utf-8')
def run_T(num):
if num < 0: #Print all entries
start = 0
entries = 16
else:
start = num
entries = 1
print("Index | ASID | VAddr | PAddr | C | D | V | G")
for i in range(start, start+entries):
outp.write(b'T')
outp.write(int_to_byte_string(i))
entry_hi = byte_string_to_int(inp.read(4))
entry_lo0 = byte_string_to_int(inp.read(4))
entry_lo1 = byte_string_to_int(inp.read(4))
if (entry_hi & entry_lo1 & entry_lo0) == 0xffffffff:
print("Error: TLB support not enabled")
break
print(" %x %02x %05x_000 %05x_000 %x %x %x %x" %
(i, entry_hi&0xff, entry_hi>>12, entry_lo0>>6, entry_lo0>>3&7, entry_lo0>>2&1, entry_lo0>>1&1, entry_lo0&1))
print(" %05x_000 %05x_000 %x %x %x %x" %
( entry_hi>>12|1, entry_lo1>>6, entry_lo1>>3&7, entry_lo1>>2&1, entry_lo1>>1&1, entry_lo1&1))
def run_A(addr):
print("one instruction per line, empty line to end.")
offset = addr & 0xfffffff
prompt_addr = addr
asm = ".set noreorder\n.set noat\n.org {:#x}\n".format(offset)
while True:
try:
line = raw_input('[0x%04x] ' % prompt_addr).strip()
except EOFError:
print('')
break
if line == '':
break
elif re.match("\\w+:$", line) is not None:
# ASM label only
asm += line + "\n"
continue
try:
asm += ".word {:#x}\n".format(int(line, 16))
except ValueError:
instr = multi_line_asm(".set noat\n" + line)
if instr == '':
continue
asm += line + "\n"
prompt_addr = prompt_addr + 4
# print(asm)
binary = multi_line_asm(asm)
for i in range(offset, len(binary), 4):
outp.write(b'A')
outp.write(int_to_byte_string(addr))
outp.write(int_to_byte_string(4))
outp.write(binary[i:i+4])
addr = addr + 4
def run_F(addr, file_name):
if not os.path.isfile(file_name):
print("file %s does not exist" % file_name)
return
print("reading from file %s" % file_name)
offset = addr & 0xfffffff
prompt_addr = addr
asm = ".set noreorder\n.set noat\n.org {:#x}\n".format(offset)
with open(file_name, "r") as f:
for line in f:
print('[0x%04x] %s' % (prompt_addr, line.strip()))
if line == '':
break
elif re.match("\\w+:$", line) is not None:
# ASM label only
asm += line + "\n"
continue
try:
asm += ".word {:#x}\n".format(int(line, 16))
except ValueError:
instr = multi_line_asm(".set noat\n" + line)
if instr == '':
continue
asm += line + "\n"
prompt_addr = prompt_addr + 4
binary = multi_line_asm(asm)
for i in range(offset, len(binary), 4):
outp.write(b'A')
outp.write(int_to_byte_string(addr))
outp.write(int_to_byte_string(4))
outp.write(binary[i:i+4])
addr = addr + 4
def run_R():
outp.write(b'R')
for i in range(1, 31):
val_raw = inp.read(4)
val = byte_string_to_int(val_raw)
print('R{0}{1:7} = 0x{2:0>8x}'.format(
str(i).ljust(2),
'(' + Reg_alias[i] + ')',
val,
))
def run_D(addr, num):
if num % 4 != 0:
print("num % 4 should be zero")
return
outp.write(b'D')
outp.write(int_to_byte_string(addr))
outp.write(int_to_byte_string(num))
counter = 0
while counter < num:
val_raw = inp.read(4)
counter = counter + 4
val = byte_string_to_int(val_raw)
print('0x%08x: 0x%08x' % (addr,val))
addr = addr + 4
def run_U(addr, num):
if num % 4 != 0:
print("num % 4 should be zero")
return
outp.write(b'D')
outp.write(int_to_byte_string(addr))
outp.write(int_to_byte_string(num))
counter = 0
while counter < num:
val_raw = inp.read(4)
print('0x%08x: %s' % (addr,single_line_disassmble(val_raw, addr)))
counter = counter + 4
addr = addr + 4
def run_G(addr):
outp.write(b'G')
outp.write(int_to_byte_string(addr))
class TrapError(Exception):
pass
try:
ret = inp.read(1)
if ret == b'\x80':
raise TrapError()
if ret != b'\x06':
print("start mark should be 0x06")
time_start = timer()
while True:
ret = inp.read(1)
if ret == b'\x07':
break
elif ret == b'\x80':
raise TrapError()
output_binary(ret)
print('') #just a new line
elapse = timer() - time_start
print('elapsed time: %.3fs' % (elapse))
except TrapError:
print('supervisor reported an exception during execution')
def MainLoop():
while True:
try:
cmd = raw_input('>> ').strip().upper()
except EOFError:
print('')
break
EmptyBuf()
try:
if cmd == 'Q':
break
elif cmd == 'A':
addr = raw_input('>>addr: 0x')
run_A(int(addr, 16))
elif cmd == 'F':
file_name = raw_input('>>file name: ')
addr = raw_input('>>addr: 0x')
run_F(int(addr, 16), file_name)
elif cmd == 'R':
run_R()
elif cmd == 'D':
addr = raw_input('>>addr: 0x')
num = raw_input('>>num: ')
run_D(int(addr, 16), int(num))
elif cmd == 'U':
addr = raw_input('>>addr: 0x')
num = raw_input('>>num: ')
run_U(int(addr, 16), int(num))
elif cmd == 'G':
addr = raw_input('>>addr: 0x')
run_G(int(addr, 16))
elif cmd == 'T':
num = raw_input('>>num: ')
run_T(int(num))
else:
print("Invalid command")
except ValueError as e:
print(e)
def InitializeSerial(pipe_path, baudrate):
global outp, inp
tty = serial.Serial(port=pipe_path, baudrate=baudrate)
tty.reset_input_buffer()
inp = tty
outp = tty
return True
def Main(welcome_message=True):
#debug
# welcome_message = False
if welcome_message:
output_binary(inp.read(33))
print('')
MainLoop()
class tcp_wrapper:
def __init__(self, sock=None):
if sock is None:
self.sock = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
else:
self.sock = sock
def connect(self, host, port):
self.sock.connect((host, port))
def write(self, msg):
totalsent = 0
MSGLEN = len(msg)
while totalsent < MSGLEN:
sent = self.sock.send(msg[totalsent:])
if sent == 0:
raise RuntimeError("socket connection broken")
totalsent = totalsent + sent
def flush(self): # dummy
pass
def read(self, MSGLEN):
chunks = []
bytes_recd = 0
while bytes_recd < MSGLEN:
chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
# print 'read:...', list(map(lambda c: hex(ord(c)), chunk))
if chunk == b'':
raise RuntimeError("socket connection broken")
chunks.append(chunk)
bytes_recd = bytes_recd + len(chunk)
return b''.join(chunks)
def reset_input_buffer(self):
local_input = [self.sock]
while True:
inputReady, o, e = select.select(local_input, [], [], 0.0)
if len(inputReady) == 0:
break
for s in inputReady:
s.recv(1)
def EmptyBuf():
inp.reset_input_buffer()
def InitializeTCP(host_port):
ValidIpAddressRegex = re.compile("^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])):(\d+)$");
ValidHostnameRegex = re.compile("^((([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])):(\d+)$");
if ValidIpAddressRegex.search(host_port) is None and \
ValidHostnameRegex.search(host_port) is None:
return False
match = ValidIpAddressRegex.search(host_port) or ValidHostnameRegex.search(host_port)
groups = match.groups()
ser = tcp_wrapper()
host, port = groups[0], groups[4]
sys.stdout.write("connecting to %s:%s..." % (host, port))
sys.stdout.flush()
ser.connect(host, int(port))
print("connected")
global outp, inp
outp = ser
inp = ser
return True
if __name__ == "__main__":
# para = '127.0.0.1:6666' if len(sys.argv) != 2 else sys.argv[1]
parser = argparse.ArgumentParser(description = 'Term for mips32 expirence.')
parser.add_argument('-c', '--continued', action='store_true', help='Term will not wait for welcome if this flag is set')
parser.add_argument('-t', '--tcp', default=None, help='TCP server address:port for communication')
parser.add_argument('-s', '--serial', default=None, help='Serial port name (e.g. /dev/ttyACM0, COM3)')
parser.add_argument('-b', '--baud', default=9600, help='Serial port baudrate (9600 by default)')
args = parser.parse_args()
if args.tcp:
if not InitializeTCP(args.tcp):
print('Failed to establish TCP connection')
exit(1)
elif args.serial:
if not InitializeSerial(args.serial, args.baud):
print('Failed to open serial port')
exit(1)
else:
parser.print_help()
exit(1)
if not test_programs():
exit(1)
Main(not args.continued)