nintendoswitch: Add experimental Nintendo Switch support without CRT

Bare minimal nintendo switch support using LLD
This commit is contained in:
Lucas Teske
2020-05-09 15:39:19 -03:00
committed by Ayke
parent d4e04e4e49
commit 3650c2c739
19 changed files with 401 additions and 4 deletions
+73
View File
@@ -0,0 +1,73 @@
// +build nintendoswitch
package runtime
type timeUnit int64
const asyncScheduler = false
func postinit() {}
// Entry point for Go. Initialize all packages and call main.main().
//export main
func main() int {
preinit()
run()
// Call exit to correctly finish the program
// Without this, the application crashes at start, not sure why
return exit(0)
}
// sleepTicks sleeps for the specified system ticks
func sleepTicks(d timeUnit) {
sleepThread(uint64(ticksToNanoseconds(d)))
}
// armTicksToNs converts cpu ticks to nanoseconds
// Nintendo Switch CPU ticks has a fixed rate at 19200000
// It is basically 52 ns per tick
// The formula 625 / 12 is equivalent to 1e9 / 19200000
func ticksToNanoseconds(tick timeUnit) int64 {
return int64(tick * 625 / 12)
}
func nanosecondsToTicks(ns int64) timeUnit {
return timeUnit(12 * ns / 625)
}
func ticks() timeUnit {
return timeUnit(ticksToNanoseconds(timeUnit(getArmSystemTick())))
}
var stdoutBuffer = make([]byte, 0, 120)
func putchar(c byte) {
if c == '\n' || len(stdoutBuffer)+1 >= 120 {
NxOutputString(string(stdoutBuffer))
stdoutBuffer = stdoutBuffer[:0]
return
}
stdoutBuffer = append(stdoutBuffer, c)
}
func usleep(usec uint) int {
sleepThread(uint64(usec) * 1000)
return 0
}
func abort() {
for {
exit(1)
}
}
//export sleepThread
func sleepThread(nanos uint64)
//export exit
func exit(code int) int
//export armGetSystemTick
func getArmSystemTick() int64
+45
View File
@@ -0,0 +1,45 @@
.section .text.armGetSystemTick, "ax", %progbits
.global armGetSystemTick
.type armGetSystemTick, %function
.align 2
armGetSystemTick:
mrs x0, cntpct_el0
ret
.section .text.nxOutputString, "ax", %progbits
.global nxOutputString
.type nxOutputString, %function
.align 2
.cfi_startproc
nxOutputString:
svc 0x27
ret
.cfi_endproc
.section .text.exit, "ax", %progbits
.global exit
.type exit, %function
.align 2
exit:
svc 0x7
ret
.section .text.setHeapSize, "ax", %progbits
.global setHeapSize
.type setHeapSize, %function
.align 2
setHeapSize:
str x0, [sp, #-16]!
svc 0x1
ldr x2, [sp], #16
str x1, [x2]
ret
.section .text.sleepThread, "ax", %progbits
.global sleepThread
.type sleepThread, %function
.align 2
sleepThread:
svc 0xB
ret
@@ -0,0 +1,31 @@
// +build nintendoswitch
// +build gc.conservative gc.leaking
package runtime
import "unsafe"
const heapSize = 0x2000000 * 16 // Default by libnx
//go:extern _stack_top
var stackTopSymbol [0]byte
var (
heapStart = uintptr(0)
heapEnd = uintptr(0)
stackTop = uintptr(unsafe.Pointer(&stackTopSymbol))
)
//export setHeapSize
func setHeapSize(addr *uintptr, length uint64) uint64
func preinit() {
setHeapSize(&heapStart, heapSize)
if heapStart == 0 {
panic("failed to allocate heap")
}
heapEnd = heapStart + heapSize
}
@@ -0,0 +1,7 @@
// +build nintendoswitch
// +build gc.none gc.extalloc
package runtime
func preinit() {}
+22
View File
@@ -0,0 +1,22 @@
// +build nintendoswitch
package runtime
import (
"unsafe"
)
// Result nxOutputString(const char *str, u64 size)
//export nxOutputString
func nxOutputString(str *uint8, size uint64) uint64
func NxOutputString(str string) uint64 {
strData := (*_string)(unsafe.Pointer(&str))
return nxOutputString((*uint8)(unsafe.Pointer(strData.ptr)), uint64(strData.length))
}
//export malloc
func extalloc(size uintptr) unsafe.Pointer
//export free
func extfree(ptr unsafe.Pointer)
+1
View File
@@ -1,4 +1,5 @@
// +build darwin linux,!baremetal freebsd,!baremetal
// +build !nintendoswitch
package runtime
+1
View File
@@ -1,4 +1,5 @@
// +build darwin linux,!baremetal freebsd,!baremetal
// +build !nintendoswitch
// +build gc.conservative gc.leaking
+2
View File
@@ -1,5 +1,7 @@
// +build darwin linux,!baremetal freebsd,!baremetal
// +build !nintendoswitch
// +build gc.none gc.extalloc
package runtime
+1 -1
View File
@@ -1,4 +1,4 @@
// +build darwin
// +build darwin nintendoswitch
package syscall
+48
View File
@@ -0,0 +1,48 @@
// +build nintendoswitch
package syscall
import "errors"
// A Signal is a number describing a process signal.
// It implements the os.Signal interface.
type Signal int
const (
_ Signal = iota
SIGCHLD
SIGINT
SIGKILL
SIGTRAP
SIGQUIT
SIGTERM
)
// File system
const (
Stdin = 0
Stdout = 1
Stderr = 2
)
const (
O_RDONLY = 0
O_WRONLY = 1
O_RDWR = 2
O_CREAT = 0100
O_CREATE = O_CREAT
O_TRUNC = 01000
O_APPEND = 02000
O_EXCL = 0200
O_SYNC = 010000
O_CLOEXEC = 0
)
var dummyError = errors.New("unknown syscall error")
func getErrno() error {
return dummyError
}
+1 -1
View File
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build baremetal
// +build baremetal nintendoswitch
package syscall