From 44eab364aee1a7cb6198cb148d68a065715a434a Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Tue, 7 Nov 2023 00:43:34 -0800 Subject: [PATCH] add sc_test --- sc_test/Makefile | 35 ++++++++++++ sc_test/head.S | 127 ++++++++++++++++++++++++++++++++++++++++++ sc_test/hello_world.c | 107 +++++++++++++++++++++++++++++++++++ sc_test/powerpc.lds | 27 +++++++++ 4 files changed, 296 insertions(+) create mode 100644 sc_test/Makefile create mode 100644 sc_test/head.S create mode 100644 sc_test/hello_world.c create mode 100644 sc_test/powerpc.lds diff --git a/sc_test/Makefile b/sc_test/Makefile new file mode 100644 index 0000000..159cb86 --- /dev/null +++ b/sc_test/Makefile @@ -0,0 +1,35 @@ +ARCH = $(shell uname -m) +ifneq ("$(ARCH)", "ppc64") +ifneq ("$(ARCH)", "ppc64le") + CROSS_COMPILE ?= powerpc64le-linux-gnu- +endif +endif + +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld +OBJCOPY = $(CROSS_COMPILE)objcopy + +CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -I../include +ASFLAGS = $(CFLAGS) +LDFLAGS = -T powerpc.lds + +all: hello_world.hex + +console.o: ../lib/console.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + +hello_world.elf: hello_world.o head.o console.o + $(LD) $(LDFLAGS) -o $@ $^ + +hello_world.bin: hello_world.elf + $(OBJCOPY) -O binary $^ $@ + +hello_world.hex: hello_world.bin + ../scripts/bin2hex.py $^ > hello_world.hex.tmp + mv -f hello_world.hex.tmp hello_world.hex + +clean: + @rm -f *.o hello_world.elf hello_world.bin hello_world.hex +distclean: clean + rm -f *~ + diff --git a/sc_test/head.S b/sc_test/head.S new file mode 100644 index 0000000..c032a1d --- /dev/null +++ b/sc_test/head.S @@ -0,0 +1,127 @@ +/* Copyright 2013-2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define STACK_TOP 0x2000 + +#define FIXUP_ENDIAN \ + tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \ + b 191f; /* Skip trampoline if endian is good */ \ + .long 0xa600607d; /* mfmsr r11 */ \ + .long 0x01006b69; /* xori r11,r11,1 */ \ + .long 0x05009f42; /* bcl 20,31,$+4 */ \ + .long 0xa602487d; /* mflr r10 */ \ + .long 0x14004a39; /* addi r10,r10,20 */ \ + .long 0xa64b5a7d; /* mthsrr0 r10 */ \ + .long 0xa64b7b7d; /* mthsrr1 r11 */ \ + .long 0x2402004c; /* hrfid */ \ +191: + + +/* Load an immediate 64-bit value into a register */ +#define LOAD_IMM64(r, e) \ + lis r,(e)@highest; \ + ori r,r,(e)@higher; \ + rldicr r,r, 32, 31; \ + oris r,r, (e)@h; \ + ori r,r, (e)@l; + + .section ".head","ax" + + /* + * Microwatt currently enters in LE mode at 0x0, so we don't need to + * do any endian fix ups> + */ + . = 0 +.global _start +_start: + b boot_entry + + /* QEMU enters at 0x10 */ + . = 0x10 + FIXUP_ENDIAN + b boot_entry + + . = 0x100 + FIXUP_ENDIAN + b boot_entry + +.global boot_entry +boot_entry: + LOAD_IMM64(%r10,__bss_start) + LOAD_IMM64(%r11,__bss_end) + subf %r11,%r10,%r11 + addi %r11,%r11,63 + srdi. %r11,%r11,6 + beq 2f + mtctr %r11 +1: dcbz 0,%r10 + addi %r10,%r10,64 + bdnz 1b + + /* setup stack */ +2: LOAD_IMM64(%r1,__stack_top) + li %r0,0 + stdu %r0,-32(%r1) + LOAD_IMM64(%r12, main) + mtctr %r12 + bctrl + attn // terminate on exit + b . + +#define EXCEPTION(nr) \ + .= nr ;\ + b . + + /* More exception stubs */ + EXCEPTION(0x300) + EXCEPTION(0x380) + EXCEPTION(0x400) + EXCEPTION(0x480) + EXCEPTION(0x500) + EXCEPTION(0x600) + EXCEPTION(0x700) + EXCEPTION(0x800) + EXCEPTION(0x900) + EXCEPTION(0x980) + EXCEPTION(0xa00) + EXCEPTION(0xb00) + + . = 0xC00 + mfsrr0 3 + mfsrr1 4 + mfmsr 5 + rfid + + EXCEPTION(0xd00) + EXCEPTION(0xe00) + EXCEPTION(0xe20) + EXCEPTION(0xe40) + EXCEPTION(0xe60) + EXCEPTION(0xe80) + EXCEPTION(0xf00) + EXCEPTION(0xf20) + EXCEPTION(0xf40) + EXCEPTION(0xf60) + EXCEPTION(0xf80) +#if 0 + EXCEPTION(0x1000) + EXCEPTION(0x1100) + EXCEPTION(0x1200) + EXCEPTION(0x1300) + EXCEPTION(0x1400) + EXCEPTION(0x1500) + EXCEPTION(0x1600) +#endif diff --git a/sc_test/hello_world.c b/sc_test/hello_world.c new file mode 100644 index 0000000..6a92414 --- /dev/null +++ b/sc_test/hello_world.c @@ -0,0 +1,107 @@ +#include +#include + +#include "console.h" +#include "io.h" +#include "microwatt_soc.h" + +static char mw_logo1[] = +"\n" +" .oOOo. \n" +" .\" \". \n" +" ; .mw. ; Microwatt, it works.\n" +" . ' ' . \n" +" \\ || / HDL Git SHA1: "; + +static char mw_logo2[] = +"\n" +" ;..; \n" +" ;..; \n" +" `ww' \n\n"; + +void write_hex(uint64_t v) +{ + puts("0x"); + for(int i = 15; i >= 0; i--) + { + uint8_t digit = (v >> 4 * i) & 0xF; + if(digit >= 10) + { + putchar('A' + (digit - 10)); + } + else + { + putchar('0' + digit); + } + } +} + +void test_sc(uint64_t srr0, uint64_t srr1, uint64_t msr) +{ + puts("before sc:\n"); + puts("SRR0 = "); + write_hex(srr0); + puts(" SRR1 = "); + write_hex(srr1); + puts(" MSR = "); + write_hex(msr); + puts("\nsc"); + register uint64_t srr0_ __asm("r3"); + register uint64_t srr1_ __asm("r4"); + register uint64_t msr_ __asm("r5"); + srr0_ = srr0; + srr1_ = srr1; + msr_ = msr; + __asm( + "mtsrr0 3\n\t" + "mtsrr1 4\n\t" + "mtmsrd 5\n\t" + "sc" + : "+r"(srr0_), "+r"(srr1_), "+r"(msr_)); + srr0 = srr0_; + srr1 = srr1_; + msr = msr_; + puts("\nafter sc:\n"); + puts("SRR0 = "); + write_hex(srr0); + puts(" SRR1 = "); + write_hex(srr1); + puts(" MSR = "); + write_hex(msr); + puts("\n"); +} + +int main(void) +{ + uint64_t gitinfo; + uint8_t c; + bool dirty; + + console_init(); + + test_sc(0x12345678, 0x5678, 0x90000000783f2903ULL); + test_sc(0x12345678, 0x5678, 0x9000000000000003ULL); + + puts(mw_logo1); + + gitinfo = readq(SYSCON_BASE + SYS_REG_GIT_INFO); + dirty = gitinfo >> 63; + for (int i = 0; i < 14; i++) { + c = (gitinfo >> 52) & 0xf; + if (c >= 10) + putchar(0x61 + c - 10); // a-f + else + putchar(0x30 + c); // 0-9 + gitinfo <<= 4; + } + if (dirty) + puts("-dirty"); + puts(mw_logo2); + + while (1) { + unsigned char c = getchar(); + putchar(c); + if (c == 13) // if CR send LF + putchar(10); + } +} diff --git a/sc_test/powerpc.lds b/sc_test/powerpc.lds new file mode 100644 index 0000000..1e218c7 --- /dev/null +++ b/sc_test/powerpc.lds @@ -0,0 +1,27 @@ +SECTIONS +{ + . = 0; + _start = .; + .head : { + KEEP(*(.head)) + } + . = 0x1000; + .text : { *(.text) *(.text.*) *(.rodata) *(.rodata.*) } + . = 0x1800; + .data : { *(.data) *(.data.*) *(.got) *(.toc) } + . = ALIGN(0x80); + __bss_start = .; + .bss : { + *(.dynsbss) + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(.common) + *(.bss.*) + } + . = ALIGN(0x80); + __bss_end = .; + . = . + 0x2000; + __stack_top = .; +} -- 2.30.2