mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-17 03:03:27 +00:00
nintendoswitch: Add experimental Nintendo Switch support without CRT
Bare minimal nintendo switch support using LLD
This commit is contained in:
@@ -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
|
||||
@@ -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() {}
|
||||
@@ -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,4 +1,5 @@
|
||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
||||
// +build !nintendoswitch
|
||||
|
||||
package runtime
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
||||
// +build !nintendoswitch
|
||||
|
||||
// +build gc.conservative gc.leaking
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// +build darwin linux,!baremetal freebsd,!baremetal
|
||||
|
||||
// +build !nintendoswitch
|
||||
|
||||
// +build gc.none gc.extalloc
|
||||
|
||||
package runtime
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build darwin
|
||||
// +build darwin nintendoswitch
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user