Commit 5e3f4e9d authored by Damien George's avatar Damien George
Browse files

leon: Add implementation of custom setjmp/longjmp.

parent 019850c8
......@@ -9,7 +9,7 @@
#include <stdio.h>
#include <rtems.h>
#include "py/nlr.h"
#include "py/mpstate.h"
#include "py/obj.h"
#include "py/objint.h"
#include "modrtems.h"
......
# This file is part of the MicroPython port to LEON platforms
# Copyright (c) 2017 George Robotics Limited
#
# This file provides a custom setjmp/longjmp implementation for LEON2/SPARC with
# 8 register windows.
# The size of the jump buffer should be 72 bytes, to store 18 registers.
.file "sparcjmp.s"
.section ".text"
.align 4
.global sparc_setjmp
.type sparc_setjmp, #function
.global sparc_longjmp
.type sparc_longjmp, #function
# sparc_setjmp(%o0=env)
sparc_setjmp:
# save the sp (%o6) and return pointer (%o7)
st %sp, [%o0 + 0x00]
st %o7, [%o0 + 0x04]
# save the local and input registers
st %l0, [%o0 + 0x08]
st %l1, [%o0 + 0x0c]
st %l2, [%o0 + 0x10]
st %l3, [%o0 + 0x14]
st %l4, [%o0 + 0x18]
st %l5, [%o0 + 0x1c]
st %l6, [%o0 + 0x20]
st %l7, [%o0 + 0x24]
st %i0, [%o0 + 0x28]
st %i1, [%o0 + 0x2c]
st %i2, [%o0 + 0x30]
st %i3, [%o0 + 0x34]
st %i4, [%o0 + 0x38]
st %i5, [%o0 + 0x3c]
st %i6, [%o0 + 0x40]
st %i7, [%o0 + 0x44]
# return 0
retl
mov %g0, %o0
.size sparc_setjmp, .-sparc_setjmp
# sparc_longjmp(env, val):
sparc_longjmp:
call sparc_window_flush_trap_handler
nop
addcc %o1, %g0, %g6
be,a .is_zero
mov 1, %g6
.is_zero:
# restore the local and input registers (some overwrite the above)
ld [%o0 + 0x08], %l0
ld [%o0 + 0x0c], %l1
ld [%o0 + 0x10], %l2
ld [%o0 + 0x14], %l3
ld [%o0 + 0x18], %l4
ld [%o0 + 0x1c], %l5
ld [%o0 + 0x20], %l6
ld [%o0 + 0x24], %l7
ld [%o0 + 0x28], %i0
ld [%o0 + 0x2c], %i1
ld [%o0 + 0x30], %i2
ld [%o0 + 0x34], %i3
ld [%o0 + 0x38], %i4
ld [%o0 + 0x3c], %i5
ld [%o0 + 0x40], %i6
ld [%o0 + 0x44], %i7
# restore the sp (%o6) and return pointer (%o7)
ld [%o0 + 0x00], %sp
ld [%o0 + 0x04], %o7
# return the passed-in "val"
retl
mov %g6, %o0
.size sparc_longjmp, .-sparc_longjmp
# locals can be clobbered because they will be restored
sparc_window_flush_trap_handler:
# need to get PSR
rd %psr, %l0
# save global registers
mov %g1, %l3
mov %g2, %l4
mov %g3, %l5
mov %g4, %l6
mov %g5, %l7
mov %l0, %g1
rd %wim, %g2
# %g3 = CWP (hard-coded for 8 windows)
and %l0, 7, %g3
# %g5 = (CWP + 0) % NWINDOWS
add %g3, 0, %g5
and %g5, 7, %g5
# %g4 = 1 << ((CWP + 0) % NWINDOWS)
mov 1, %g4
sll %g4, %g5, %g4
.save_frame_loop:
# restore will increment CWP in the PSR
restore
std %l0, [ %sp ]
std %l2, [ %sp + 8 ]
std %l4, [ %sp + 0x10 ]
std %l6, [ %sp + 0x18 ]
std %i0, [ %sp + 0x20 ]
std %i2, [ %sp + 0x28 ]
std %i4, [ %sp + 0x30 ]
std %i6, [ %sp + 0x38 ]
# %g4 = (%g4 >> 7) | (%g4 << 1) [equiv: rol %g4 by 1]
sll %g4, 1, %g5
srl %g4, 7, %g4
or %g4, %g5, %g4
# if (%g4 & %wim == 0) goto .save_frame_loop;
btst %g4, %g2
be .save_frame_loop
nop
# %g3 = (CWP + 1) % NWINDOWS
add %g3, 1, %g3
and %g3, 7, %g3
# %wim = 1 << ((CWP + 1) % NWINDOWS)
mov 1, %g4
sll %g4, %g3, %g4
mov %g4, %wim
# restore PSR
wr %g1, %psr
nop
nop
nop
# restore global registers
mov %l3, %g1
mov %l4, %g2
mov %l5, %g3
mov %l6, %g4
mov %l7, %g5
# return
retl
nop
.size sparc_window_flush_trap_handler, .-sparc_window_flush_trap_handler
......@@ -53,6 +53,7 @@ SRC_C = \
$(LEON_COMMON)/modmem.c \
SRC_S = \
$(LEON_COMMON)/sparcjmp.s \
$(LEON_COMMON)/gchelper.s \
# these are the example Python scripts to compile
......
......@@ -7,7 +7,7 @@
*/
// options to control how MicroPython is built
#define MICROPY_NLR_SETJMP (1)
#define MICROPY_NLR_SPARC (1)
#define MICROPY_ALLOC_PATH_MAX (128)
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_EMIT_X64 (0)
......
......@@ -53,6 +53,7 @@ SRC_C = \
$(LEON_COMMON)/modmem.c \
SRC_S = \
$(LEON_COMMON)/sparcjmp.s \
$(LEON_COMMON)/gchelper.s \
# these are the example Python scripts to compile
......
......@@ -7,7 +7,7 @@
*/
// options to control how MicroPython is built
#define MICROPY_NLR_SETJMP (1)
#define MICROPY_NLR_SPARC (1)
#define MICROPY_ALLOC_PATH_MAX (128)
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_EMIT_X64 (0)
......
......@@ -55,6 +55,7 @@ SRC_C = \
$(LEON_COMMON)/modmem.c \
SRC_S = \
$(LEON_COMMON)/sparcjmp.s \
$(LEON_COMMON)/gchelper.s \
# these are the example Python scripts to compile
......
......@@ -7,7 +7,7 @@
*/
// options to control how MicroPython is built
#define MICROPY_NLR_SETJMP (1)
#define MICROPY_NLR_SPARC (1)
#define MICROPY_ALLOC_PATH_MAX (128)
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_EMIT_X64 (0)
......
......@@ -53,6 +53,7 @@ SRC_C = \
$(LEON_COMMON)/modmem.c \
SRC_S = \
$(LEON_COMMON)/sparcjmp.s \
$(LEON_COMMON)/gchelper.s \
# these are the example Python scripts to compile
......
......@@ -7,7 +7,7 @@
*/
// options to control how MicroPython is built
#define MICROPY_NLR_SETJMP (1)
#define MICROPY_NLR_SPARC (1)
#define MICROPY_ALLOC_PATH_MAX (128)
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_EMIT_X64 (0)
......
......@@ -54,6 +54,7 @@ SRC_C = \
$(LEON_COMMON)/moddatapool.c \
SRC_S = \
$(LEON_COMMON)/sparcjmp.s \
$(LEON_COMMON)/gchelper.s \
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o))
......
......@@ -7,7 +7,7 @@
*/
// options to control how MicroPython is built
#define MICROPY_NLR_SETJMP (1)
#define MICROPY_NLR_SPARC (1)
#define MICROPY_ALLOC_PATH_MAX (128)
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_EMIT_X64 (0)
......
......@@ -65,6 +65,7 @@ SRC_C = \
$(LEON_COMMON)/moddatapool.c \
SRC_S = \
$(LEON_COMMON)/sparcjmp.s \
$(LEON_COMMON)/gchelper.s \
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o))
......
......@@ -7,7 +7,7 @@
*/
// options to control how MicroPython is built
#define MICROPY_NLR_SETJMP (1)
#define MICROPY_NLR_SPARC (1)
#define MICROPY_ALLOC_PATH_MAX (128)
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_EMIT_X64 (0)
......
......@@ -53,6 +53,8 @@ struct _nlr_buf_t {
void *regs[10];
#elif defined(__xtensa__)
void *regs[10];
#elif MICROPY_NLR_SPARC
void *regs[18];
#else
#define MICROPY_NLR_SETJMP (1)
//#warning "No native NLR support for this arch, using setjmp implementation"
......@@ -74,7 +76,13 @@ NORETURN void nlr_setjmp_jump(void *val);
#define nlr_pop() { MP_STATE_THREAD(nlr_top) = MP_STATE_THREAD(nlr_top)->prev; }
#define nlr_jump(val) nlr_setjmp_jump(val)
#else
#if MICROPY_NLR_SPARC
// nlr_push() is a macro because it must not call the save/restore instructions
int sparc_setjmp(void *env);
#define nlr_push(buf) ((buf)->prev = MP_STATE_THREAD(nlr_top), MP_STATE_THREAD(nlr_top) = (buf), sparc_setjmp((buf)->regs))
#else
unsigned int nlr_push(nlr_buf_t *);
#endif
void nlr_pop(void);
NORETURN void nlr_jump(void *val);
#endif
......
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/mpstate.h"
#include "py/nlr.h"
#if MICROPY_NLR_SPARC
NORETURN void sparc_longjmp(void *env, int val);
void nlr_pop(void) {
nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
*top = (*top)->prev;
}
NORETURN void nlr_jump(void *val) {
nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
nlr_buf_t *top = *top_ptr;
if (top == NULL) {
nlr_jump_fail(val);
}
top->ret_val = val;
*top_ptr = top->prev;
sparc_longjmp(top->regs, 1);
}
#endif
......@@ -105,6 +105,7 @@ PY_O_BASENAME = \
nlrx64.o \
nlrthumb.o \
nlrxtensa.o \
nlrsparc.o \
nlrsetjmp.o \
malloc.o \
gc.o \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment