Skip to content
This repository was archived by the owner on Aug 19, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.vscode
.idea
*.o
*.swp
*.objdump
*~
tags
hello
45 changes: 45 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
ENDIAN := EL

QEMU := qemu-system-mipsel
CROSS_COMPILE := mips-linux-gnu-
CC := $(CROSS_COMPILE)gcc
CFLAGS += --std=gnu99 -$(ENDIAN) -G 0 -mno-abicalls -fno-pic \
-ffreestanding -fno-stack-protector -fno-builtin \
-Wa,-xgot -Wall -mxgot -mno-fix-r4000 -march=4kc -g -ggdb
LD := $(CROSS_COMPILE)ld
LDFLAGS += -EL -G 0 -static -n -nostdlib --fatal-warnings
INCLUDES := -I./include/
target := hello
objects := hello.o output.o start.o
qemu_files += hello
qemu_flags += -cpu 4Kc -m 64 -nographic -M malta -no-reboot

%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<

%.o: %.S
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<

.PHONY: all clean dbg

all: hello

hello: linker.lds $(objects)
$(LD) $(LDFLAGS) -o hello -N -T linker.lds $(objects)

clean:
rm -rf *~ *.o hello *.objdump

dbg_run: qemu_flags += -s -S
dbg_run: run

dbg:
make dbg_run >/dev/null 2>&1 &
gdb-multiarch $(target) -ex "target remote localhost:1234"
killall $(QEMU)

run:
$(QEMU) $(qemu_flags) -kernel $(qemu_files)

objdump:
$(CROSS_COMPILE)objdump $(target) -aldS > hello.objdump
18 changes: 18 additions & 0 deletions hello.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "output.h"
#include <stddef.h>

void hello(int a, int b, int c, int d, int e, int f) {
print_num(a);
print_str("\n");
print_num(b);
print_str("\n");
print_num(c);
print_str("\n");
print_num(d);
print_str("\n");
print_num(e);
print_str("\n");
print_num(f);
print_str("\n");
halt();
}
40 changes: 40 additions & 0 deletions include/asm/asm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <asm/cp0regdef.h>
#include <asm/regdef.h>

/*
* LEAF - declare leaf routine
*/
#define LEAF(symbol) \
.globl symbol; \
.align 2; \
.type symbol, @function; \
.ent symbol; \
symbol: \
.frame sp, 0, ra

/*
* NESTED - declare nested routine entry point
*/
#define NESTED(symbol, framesize, rpc) \
.globl symbol; \
.align 2; \
.type symbol, @function; \
.ent symbol; \
symbol: \
.frame sp, framesize, rpc

/*
* END - mark end of function
*/
#define END(function) \
.end function; \
.size function, .- function

#define EXPORT(symbol) \
.globl symbol; \
symbol:

#define FEXPORT(symbol) \
.globl symbol; \
.type symbol, @function; \
symbol:
39 changes: 39 additions & 0 deletions include/asm/cp0regdef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef _cp0regdef_h_
#define _cp0regdef_h_

#define CP0_INDEX $0
#define CP0_RANDOM $1
#define CP0_ENTRYLO0 $2
#define CP0_ENTRYLO1 $3
#define CP0_CONTEXT $4
#define CP0_PAGEMASK $5
#define CP0_WIRED $6
#define CP0_BADVADDR $8
#define CP0_COUNT $9
#define CP0_ENTRYHI $10
#define CP0_COMPARE $11
#define CP0_STATUS $12
#define CP0_CAUSE $13
#define CP0_EPC $14
#define CP0_PRID $15
#define CP0_CONFIG $16
#define CP0_LLADDR $17
#define CP0_WATCHLO $18
#define CP0_WATCHHI $19
#define CP0_XCONTEXT $20
#define CP0_FRAMEMASK $21
#define CP0_DIAGNOSTIC $22
#define CP0_PERFORMANCE $25
#define CP0_ECC $26
#define CP0_CACHEERR $27
#define CP0_TAGLO $28
#define CP0_TAGHI $29
#define CP0_ERROREPC $30

#define STATUS_CU0 0x10000000
#define STATUS_IM4 0x1000
#define STATUS_KUp 0x8
#define STATUS_IEp 0x4
#define STATUS_KUc 0x2
#define STATUS_IEc 0x1
#endif
1 change: 1 addition & 0 deletions include/asm/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

42 changes: 42 additions & 0 deletions include/asm/regdef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef __ASM_MIPS_REGDEF_H
#define __ASM_MIPS_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_MIPS_REGDEF_H */
56 changes: 56 additions & 0 deletions include/machine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#ifndef _MACHINE_H
#define _MACHINE_H

// Memory segments (32-bit kernel mode addresses)
#define KUSEG 0x00000000U
#define KSEG0 0x80000000U
#define KSEG1 0xA0000000U
#define KSEG2 0xC0000000U

/*
* QEMU MMIO address definitions.
*/
#define MALTA_PCIIO_BASE 0x18000000
#define MALTA_FPGA_BASE 0x1f000000

/*
* 16550 Serial UART device definitions.
*/
#define MALTA_SERIAL_BASE (MALTA_PCIIO_BASE + 0x3f8)
#define MALTA_SERIAL_DATA (MALTA_SERIAL_BASE + 0x0)
#define MALTA_SERIAL_LSR (MALTA_SERIAL_BASE + 0x5)
#define MALTA_SERIAL_DATA_READY 0x1
#define MALTA_SERIAL_THR_EMPTY 0x20

/*
* Intel PIIX4 IDE Controller device definitions.
* Hardware documentation available at
* https://www.intel.com/Assets/PDF/datasheet/290562.pdf
*/
#define MALTA_IDE_BASE (MALTA_PCIIO_BASE + 0x01f0)
#define MALTA_IDE_DATA (MALTA_IDE_BASE + 0x00)
#define MALTA_IDE_ERR (MALTA_IDE_BASE + 0x01)
#define MALTA_IDE_NSECT (MALTA_IDE_BASE + 0x02)
#define MALTA_IDE_LBAL (MALTA_IDE_BASE + 0x03)
#define MALTA_IDE_LBAM (MALTA_IDE_BASE + 0x04)
#define MALTA_IDE_LBAH (MALTA_IDE_BASE + 0x05)
#define MALTA_IDE_DEVICE (MALTA_IDE_BASE + 0x06)
#define MALTA_IDE_STATUS (MALTA_IDE_BASE + 0x07)
#define MALTA_IDE_LBA 0xE0
#define MALTA_IDE_BUSY 0x80
#define MALTA_IDE_CMD_PIO_READ 0x20 /* Read sectors with retry */
#define MALTA_IDE_CMD_PIO_WRITE 0x30 /* write sectors with retry */

/*
* MALTA Power Management device definitions.
*/
#define MALTA_FPGA_HALT (MALTA_FPGA_BASE + 0x500)


/* IO function */
void m_putch(char ch);
char m_getch(void);
/* when call this func, gxemul will quit */
void m_halt(void);

#endif
9 changes: 9 additions & 0 deletions include/output.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef _OUTPUT_H_
#define _OUTPUT_H_

void print_str(const char *buf);
void printcharc(char ch);
void print_num(unsigned long u);
void halt(void);

#endif
29 changes: 29 additions & 0 deletions linker.lds
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Set the architecture to mips.
*/
OUTPUT_ARCH(mips)

/*
* Set the ENTRY point of the program to _start_mips.
*/
ENTRY(_start_mips)

SECTIONS {

. = 0x80020000;

.text : {
*(.text)
}

.data : {
*(.data)
}

.bss : {
*(.bss)
}

. = 0x80400000;
end = . ;
}
32 changes: 32 additions & 0 deletions output.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <machine.h>
#include <stddef.h>
#include <output.h>

void printcharc(char ch) {
while (!(*((volatile char *)(KSEG1 + MALTA_SERIAL_LSR)) & MALTA_SERIAL_THR_EMPTY)) {
}
*((volatile char *)(KSEG1 + MALTA_SERIAL_DATA)) = ch;
}

void halt(void) {
*(volatile char *)(KSEG1 + MALTA_FPGA_HALT) = 0x42;
}

void print_str(const char *buf) {
for (int i = 0; buf[i]; i++) {
printcharc(buf[i]);
}
}

void print_num(unsigned long u) {
if (u < 0) {
printcharc('-');
u = -u;
}
char digit = '0' + u % 10;
u /= 10;
if (u != 0) {
print_num(u);
}
printcharc(digit);
}
50 changes: 50 additions & 0 deletions start.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <asm/asm.h>
.data
str:
.asciiz "Hello World\n" # Null-terminated string "Hello World" stored at label 'str'
.align 2 # align to 4-byte boundary (2^2)
var:
.byte 3 # correctly aligned byte: 3
/* '<x>' in the comments is the part to be replaced. */
/* use '.align <x>' to align the following words to 1-byte boundary (disabling word-alignment) */
/* so that the byte 3 and word 7 is "connected" */
/* Your code here. (1/6) */
.align 0
.word 7, 8, 9

.text
/* We define '_start_mips' here as the entry of our program. */
EXPORT(_start_mips)
.set at
.set reorder
mtc0 zero, CP0_STATUS
li sp, 0x84000000
/* Load the address of the string 'str' into the first parameter register. */
la a0, str
/* use 'addiu sp, sp, <x>' to push a proper-sized frame onto the stack for Nonleaf function 'print_str'. */
/* Your code here. (2/6) */
addiu sp, sp,-4
jal print_str
/* use 'addiu sp, sp, <x>' to restore stack pointer. */
/* Your code here. (3/6) */
addiu sp, sp,4
/* Set the first four parameters. */
li a0, 0
li a1, 1
li a2, 2
li a3, 3
/* use 'addiu sp, sp, <x>' to push a proper-sized frame onto the stack for Nonleaf function 'hello'. */
/* Your code here. (4/6) */
addiu sp, sp, -24
lw t1, var
li t2, 5
/* use 'sw t1, <x>(sp)' to store t1 at the proper place of the stack */
/* so that t1 is 5th argument of function hello. */
/* Your code here. (5/6) */
sw t1, 16(sp)
/* use 'sw t2, <x>(sp)' to store t2 at the proper place of the stack */
/* so that t2 is 6th argument of function hello. */
/* Your code here. (6/6) */
sw t2, 20(sp)
/* use 'j' to call the function 'hello', we use 'j' instead of 'jal' because 'hello' is 'noreturn' */
j hello