Implemented clock ISR.

Fixed _CPU_Context_Initialize, _CPU_Context_Switch and _CPU_Context_Restore
(stack and shadow stack management).

Fixed linker missing symbols.
This commit is contained in:
afpr
2013-08-28 18:04:01 +01:00
parent b9765e1de1
commit a6ace744e6
6 changed files with 614 additions and 338 deletions

View File

@@ -23,14 +23,7 @@
#include <bsp.h>
void Clock_exit( void );
rtems_isr Clock_isr( rtems_vector_number vector );
/*
* The interrupt vector number associated with the clock tick device
* driver.
*/
#define CLOCK_VECTOR 4
rtems_isr Clock_isr( rtems_vector_number vector )__attribute__((naked));
/*
* Clock_driver_ticks is a monotonically increasing counter of the
@@ -64,22 +57,248 @@ rtems_isr_entry Old_ticker;
void Clock_exit( void );
void set_cpu_cycles (u64 time_warp)
{
__PATMOS_RTC_WR_CYCLE_LOW((unsigned int)time_warp);
__PATMOS_RTC_WR_CYCLE_UP((unsigned int)(time_warp >> 32));
}
u64 get_cpu_cycles(void)
{
unsigned int u;
unsigned int l;
__PATMOS_RTC_RD_CYCLE_LOW(l);
__PATMOS_RTC_RD_CYCLE_UP(u);
return (((u64)u) << 32) | l;
}
u64 get_cpu_time(void)
{
unsigned int u;
unsigned int l;
__PATMOS_RTC_RD_TIME_LOW(l);
__PATMOS_RTC_RD_TIME_UP(u);
return (((u64)u) << 32) | l;
}
uint32_t bsp_clock_nanoseconds_since_last_tick(void)
{
uint32_t usecs;
usecs = get_cpu_time() - Clock_driver_ticks*rtems_configuration_get_microseconds_per_tick();
return usecs * 1000;
}
#define Clock_driver_nanoseconds_since_last_tick \
bsp_clock_nanoseconds_since_last_tick
/*
* Isr Handler
* Clock_isr
*
* This is the clock tick interrupt handler.
*
* Input parameters:
* vector - vector number
*
* Output parameters: NONE
*
* Return values: NONE
*/
rtems_isr Clock_isr(
rtems_vector_number vector
)
{
/*
* bump the number of clock driver ticks since initialization
*
* determine if it is time to announce the passing of tick as configured
* to RTEMS through the rtems_clock_tick directive
*
* perform any timer dependent tasks
*/
/*
* save general-purpose registers to the shadow stack
* copy the current stack to memory and save the stack size to the shadow stack
* save special-purpose registers to the shadow stack
* reset r0 and update function return address base and offset registers r30 and r31
*/
asm volatile("sub $r29 = $r29, %0 \n\t" // offset shadow stack pointer
"swm [ $r29 + %1 ] = $r0 \n\t" //save r0
"swm [ $r29 + %2 ] = $r1 \n\t" //save r1
"swm [ $r29 + %3 ] = $r2 \n\t" //save r2
"swm [ $r29 + %4 ] = $r3 \n\t" //save r3
"swm [ $r29 + %5 ] = $r4 \n\t" //save r4
"swm [ $r29 + %6 ] = $r5 \n\t" //save r5
"swm [ $r29 + %7 ] = $r6 \n\t" //save r6
"swm [ $r29 + %8 ] = $r7 \n\t" //save r7
"swm [ $r29 + %9 ] = $r8 \n\t" //save r8
"swm [ $r29 + %10 ] = $r9 \n\t" //save r9
"swm [ $r29 + %11 ] = $r10 \n\t" //save r10
"swm [ $r29 + %12 ] = $r11 \n\t" //save r11
"swm [ $r29 + %13 ] = $r12 \n\t" //save r12
"swm [ $r29 + %14 ] = $r13 \n\t" //save r13
"swm [ $r29 + %15 ] = $r14 \n\t" //save r14
"swm [ $r29 + %16 ] = $r15 \n\t" //save r15
"swm [ $r29 + %17 ] = $r16 \n\t" //save r16
"swm [ $r29 + %18 ] = $r17 \n\t" //save r17
"swm [ $r29 + %19 ] = $r18 \n\t" //save r18
"swm [ $r29 + %20 ] = $r19 \n\t" //save r19
"swm [ $r29 + %21 ] = $r20 \n\t" //save r20
"swm [ $r29 + %22 ] = $r21 \n\t" //save r21
"swm [ $r29 + %23 ] = $r22 \n\t" //save r22
"swm [ $r29 + %24 ] = $r23 \n\t" //save r23
"swm [ $r29 + %25 ] = $r24 \n\t" //save r24
"swm [ $r29 + %26 ] = $r25 \n\t" //save r25
"swm [ $r29 + %27 ] = $r26 \n\t" //save r26
"swm [ $r29 + %28 ] = $r27 \n\t" //save r27
"swm [ $r29 + %29 ] = $r28 \n\t" //save r28
"swm [ $r29 + %30 ] = $r29 \n\t" //save r29
"swm [ $r29 + %31 ] = $r30 \n\t" //save r30
"swm [ $r29 + %32 ] = $r31 \n\t" //save r31
"mfs $r5 = $s5 \n\t"
"mfs $r6 = $s6 \n\t"
"sub $r2 = $r5, $r6 \n\t" // get stack size
"sspill $r2 \n\t"
"swm [ $r29 + %33 ] = $r2 \n\t" //save stack size to memory
"mfs $r1 = $s0 \n\t" //move s0 to r1
"swm [ $r29 + %34 ] = $r1 \n\t" //save s0
"mfs $r1 = $s1 \n\t" //move s1 to r1
"swm [ $r29 + %35 ] = $r1 \n\t" //save s1
"mfs $r1 = $s2 \n\t" //move s2 to r1
"swm [ $r29 + %36 ] = $r1 \n\t" //save s2
"mfs $r1 = $s3 \n\t" //move s3 to r1
"swm [ $r29 + %37 ] = $r1 \n\t" //save s3
"mfs $r1 = $s4 \n\t" //move s4 to r1
"swm [ $r29 + %38 ] = $r1 \n\t" //save s4
"mfs $r1 = $s5 \n\t" //move s5 to r1
"swm [ $r29 + %39 ] = $r1 \n\t" //save s5
"mfs $r1 = $s6 \n\t" //move s6 to r1
"swm [ $r29 + %40 ] = $r1 \n\t" //save s6
"mfs $r1 = $s7 \n\t" //move s7 to r1
"swm [ $r29 + %41 ] = $r1 \n\t" //save s7
"mfs $r1 = $s8 \n\t" //move s8 to r1
"swm [ $r29 + %42 ] = $r1 \n\t" //save s8
"mfs $r1 = $s9 \n\t" //move s9 to r1
"swm [ $r29 + %43 ] = $r1 \n\t" //save s9
"mfs $r1 = $s10 \n\t" //move s10 to r1
"swm [ $r29 + %44 ] = $r1 \n\t" //save s10
"mfs $r1 = $s11 \n\t" //move s11 to r1
"swm [ $r29 + %45 ] = $r1 \n\t" //save s11
"mfs $r1 = $s12 \n\t" //move s12 to r1
"swm [ $r29 + %46 ] = $r1 \n\t" //save s12
"mfs $r1 = $s13 \n\t" //move s13 to r1
"swm [ $r29 + %47 ] = $r1 \n\t" //save s13
"mfs $r1 = $s14 \n\t" //move s14 to r1
"swm [ $r29 + %48 ] = $r1 \n\t" //save s14
"mfs $r1 = $s15 \n\t" //move s15 to r1
"swm [ $r29 + %49 ] = $r1 \n\t" //save s15
"and $r0 = $r0, 0\n\t" //reset r0
"li $r30 = Clock_isr\n\t" //set return address
"li $r31 = restore_context\n\t"
: : "i" (CONTEXT_OFFSET), "i" (r0_OFFSET), "i" (r1_OFFSET),"i" (r2_OFFSET), "i" (r3_OFFSET),
"i" (r4_OFFSET), "i" (r5_OFFSET), "i" (r6_OFFSET), "i" (r7_OFFSET), "i" (r8_OFFSET),
"i" (r9_OFFSET), "i" (r10_OFFSET), "i" (r11_OFFSET), "i" (r12_OFFSET), "i" (r13_OFFSET),
"i" (r14_OFFSET), "i" (r15_OFFSET), "i" (r16_OFFSET), "i" (r17_OFFSET), "i" (r18_OFFSET),
"i" (r19_OFFSET), "i" (r20_OFFSET), "i" (r21_OFFSET), "i" (r22_OFFSET), "i" (r23_OFFSET),
"i" (r24_OFFSET), "i" (r25_OFFSET), "i" (r26_OFFSET), "i" (r27_OFFSET), "i" (r28_OFFSET),
"i" (r29_OFFSET), "i" (r30_OFFSET), "i" (r31_OFFSET), "i" (ssize_OFFSET), "i" (s0_OFFSET),
"i" (s1_OFFSET), "i" (s2_OFFSET), "i" (s3_OFFSET), "i" (s4_OFFSET), "i" (s5_OFFSET),
"i" (s6_OFFSET), "i" (s7_OFFSET), "i" (s8_OFFSET), "i" (s9_OFFSET), "i" (s10_OFFSET),
"i" (s11_OFFSET), "i" (s12_OFFSET), "i" (s13_OFFSET), "i" (s14_OFFSET), "i" (s15_OFFSET));
/*
* Accurate count of ISRs
*/
Clock_driver_ticks += 1;
__PATMOS_RTC_WR_INTERVAL(rtems_configuration_get_microseconds_per_tick() * PATMOS_FREQ_MHZ);
rtems_clock_tick();
/*
* load general-purpose registers from the shadow stack
* load special-purpose registers from the shadow stack cache
*/
asm volatile("restore_context: \n\t"
"lwc $r0 = [ $r29 + %0 ] \n\t" //load r0
"lwc $r2 = [ $r29 + %1 ] \n\t" //load r2
"lwc $r3 = [ $r29 + %2 ] \n\t" //load r3
"lwc $r4 = [ $r29 + %3 ] \n\t" //load r4
"lwc $r5 = [ $r29 + %4 ] \n\t" //load r5
"lwc $r6 = [ $r29 + %5 ] \n\t" //load r6
"lwc $r7 = [ $r29 + %6 ] \n\t" //load r7
"lwc $r8 = [ $r29 + %7 ] \n\t" //load r8
"lwc $r9 = [ $r29 + %8 ] \n\t" //load r9
"lwc $r10 = [ $r29 + %9 ] \n\t" //load r10
"lwc $r11 = [ $r29 + %10 ] \n\t" //load r11
"lwc $r12 = [ $r29 + %11 ] \n\t" //load r12
"lwc $r13 = [ $r29 + %12 ] \n\t" //load r13
"lwc $r14 = [ $r29 + %13 ] \n\t" //load r14
"lwc $r15 = [ $r29 + %14 ] \n\t" //load r15
"lwc $r16 = [ $r29 + %15 ] \n\t" //load r16
"lwc $r17 = [ $r29 + %16 ] \n\t" //load r17
"lwc $r18 = [ $r29 + %17 ] \n\t" //load r18
"lwc $r19 = [ $r29 + %18 ] \n\t" //load r19
"lwc $r20 = [ $r29 + %19 ] \n\t" //load r20
"lwc $r21 = [ $r29 + %20 ] \n\t" //load r21
"lwc $r22 = [ $r29 + %21 ] \n\t" //load r22
"lwc $r23 = [ $r29 + %22 ] \n\t" //load r23
"lwc $r24 = [ $r29 + %23 ] \n\t" //load r24
"lwc $r25 = [ $r29 + %24 ] \n\t" //load r25
"lwc $r26 = [ $r29 + %25 ] \n\t" //load r26
"lwc $r27 = [ $r29 + %26 ] \n\t" //load r27
"lwc $r28 = [ $r29 + %27 ] \n\t" //load r28
"lwc $r30 = [ $r29 + %28 ] \n\t" //load r30
"lwc $r31 = [ $r29 + %29 ] \n\t" //load r31
"lwc $r1 = [ $r29 + %30 ] \n\t nop \n\t" //load s0
"mts $s0 = $r1 \n\t" //move r1 to s0
"lwc $r1 = [ $r29 + %31 ] \n\t nop \n\t" //load s1
"mts $s1 = $r1 \n\t" //move r1 to s1
"lwc $r1 = [ $r29 + %32 ] \n\t nop \n\t" //load s2
"mts $s2 = $r1 \n\t" //move r1 to s2
"lwc $r1 = [ $r29 + %33 ] \n\t nop \n\t" //load s3
"mts $s3 = $r1 \n\t" //move r1 to s3
"lwc $r1 = [ $r29 + %34 ] \n\t nop \n\t" //load s4
"mts $s4 = $r1 \n\t" //move r1 to s4
"lwc $r1 = [ $r29 + %35 ] \n\t nop \n\t" //load s5
"mts $s5 = $r1 \n\t" //move r1 to s5
"lwc $r1 = [ $r29 + %36 ] \n\t nop \n\t" //load s6
"mts $s6 = $r1 \n\t" //move r1 to s6
"lwc $r1 = [ $r29 + %37 ] \n\t nop \n\t" //load s7
"mts $s7 = $r1 \n\t" //move r1 to s7
"lwc $r1 = [ $r29 + %38 ] \n\t nop \n\t" //load s8
"mts $s8 = $r1 \n\t" //move r1 to s8
"lwc $r1 = [ $r29 + %39 ] \n\t nop \n\t" //load s10
"mts $s10 = $r1 \n\t" //move r1 to s10
"lwc $r1 = [ $r29 + %40 ] \n\t nop \n\t" //load s11
"mts $s11 = $r1 \n\t" //move r1 to s11
"lwc $r1 = [ $r29 + %41 ] \n\t nop \n\t" //load s12
"mts $s12 = $r1 \n\t" //move r1 to s12
"lwc $r1 = [ $r29 + %42 ] \n\t nop \n\t" //load s13
"mts $s13 = $r1 \n\t" //move r1 to s13
"lwc $r1 = [ $r29 + %43 ] \n\t nop \n\t" //load s14
"mts $s14 = $r1 \n\t" //move r1 to s14
"lwc $r1 = [ $r29 + %44 ] \n\t nop \n\t" //load s15
"mts $s15 = $r1 \n\t" //move r1 to s15
"lwm $r1 = [ $r29 + %45 ] \n\t nop \n\t" //load ssize
"sens $r1 \n\t" //ensure the stack size in the stack cache
"lwc $r1 = [ $r29 + %46 ] \n\t nop \n\t" //load s9
"mts $s9 = $r1 \n\t" //move r1 to s9
"lwc $r1 = [ $r29 + %47 ] \n\t" //load r1
"ret $r1, $r0 \n\t" //return to s9 (r1 still has s9 due to lwc cycle delay slot)
"lwc $r29 = [ $r29 + %48 ] \n\t nop \n\t" //load r29
"add $r29 = $r29, %49 \n\t" // reset shadow stack pointer
: : "i" (r0_OFFSET), "i" (r2_OFFSET), "i" (r3_OFFSET), "i" (r4_OFFSET), "i" (r5_OFFSET),
"i" (r6_OFFSET), "i" (r7_OFFSET), "i" (r8_OFFSET), "i" (r9_OFFSET), "i" (r10_OFFSET),
"i" (r11_OFFSET), "i" (r12_OFFSET), "i" (r13_OFFSET), "i" (r14_OFFSET), "i" (r15_OFFSET),
"i" (r16_OFFSET), "i" (r17_OFFSET), "i" (r18_OFFSET), "i" (r19_OFFSET), "i" (r20_OFFSET),
"i" (r21_OFFSET), "i" (r22_OFFSET), "i" (r23_OFFSET), "i" (r24_OFFSET), "i" (r25_OFFSET),
"i" (r26_OFFSET), "i" (r27_OFFSET), "i" (r28_OFFSET), "i" (r30_OFFSET), "i" (r31_OFFSET),
"i" (s0_OFFSET), "i" (s1_OFFSET), "i" (s2_OFFSET), "i" (s3_OFFSET), "i" (s4_OFFSET),
"i" (s5_OFFSET), "i" (s6_OFFSET), "i" (s7_OFFSET), "i" (s8_OFFSET), "i" (s10_OFFSET),
"i" (s11_OFFSET), "i" (s12_OFFSET), "i" (s13_OFFSET), "i" (s14_OFFSET), "i" (s15_OFFSET),
"i" (ssize_OFFSET), "i" (s9_OFFSET), "i" (r1_OFFSET), "i" (r29_OFFSET), "i" (CONTEXT_OFFSET));
}
/*
@@ -100,11 +319,15 @@ void Install_clock(
Clock_driver_ticks = 0;
Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
/*
* Hardware specific initialize goes here
*/
__PATMOS_RTC_WR_ISR((uint32_t)clock_isr);
/* XXX */
#if defined(Clock_driver_nanoseconds_since_last_tick)
rtems_clock_set_nanoseconds_extension(
Clock_driver_nanoseconds_since_last_tick
);
#endif
__PATMOS_RTC_WR_INTERVAL(rtems_configuration_get_microseconds_per_tick() * PATMOS_FREQ_MHZ);
/*
* Schedule the clock cleanup routine to execute if the application exits.
@@ -138,10 +361,6 @@ rtems_device_driver Clock_initialize(
{
Install_clock( Clock_isr );
/*
* make major/minor avail to others such as shared memory driver
*/
rtems_clock_major = major;
rtems_clock_minor = minor;

View File

@@ -30,9 +30,6 @@ extern "C" {
/* PATMOS CPU variant: PASIM */
#define PASIM 1
#define STDOUT_FILENO 0 /* standard output file descriptor */
#define STDERR_FILENO 1 /* standard error file descriptor */
/* Constants */
/*

View File

@@ -22,24 +22,23 @@
extern "C" {
#endif
/*
#define PASIM_SHADOW_STACK_BASE 0x4000
#define PASIM_STACK_CACHE_BASE 0x3000
*/
#define PASIM_SHADOW_STACK_BASE 0x4000000
#define PASIM_STACK_CACHE_BASE 0x3000000
#ifndef ASM
extern char _iomap_base; /* linker symbol giving the base address of the IO map address range */
#define _IODEV __attribute__((address_space(1)))
typedef _IODEV unsigned int volatile * const _iodev_ptr_t;
typedef unsigned long long u64;
extern char _uart_status_base; /* linker symbol giving the address of the UART status register */
/*
* UART Management
*/
extern char _uart_data_base; /* linker symbol giving the address of the UART data register */
extern char _iomap_base; /* linker symbol giving the base address of the IO map address range */
extern char _uart_base; /* linker symbol giving the address of the UART */
#endif
@@ -52,8 +51,15 @@ extern char _uart_data_base; /* linker symbol giving the address of the UART dat
#define __PATMOS_UART_PAE 4 /* Bit mask for the parity-error bit (PAE) */
#define __PATMOS_UART_TFL 8 /* Bit mask for the transmit-flush bit (TFL) */
#define __PATMOS_UART_STATUS_ADDR (&_uart_status_base) /* Address to access the status register of the UART coming with Patmos */
#define __PATMOS_UART_DATA_ADDR (&_uart_data_base) /* Address to access the data register of the UART coming with Patmos */
/*
* Address to access the status register of the UART coming with Patmos
*/
#define __PATMOS_UART_STATUS_ADDR (&_uart_base + 0x00)
/*
* Address to access the data register of the UART coming with Patmos
*/
#define __PATMOS_UART_DATA_ADDR (&_uart_base + 0x04)
#ifndef ASM
@@ -73,6 +79,69 @@ extern char _uart_data_base; /* linker symbol giving the address of the UART dat
/* Macro to write the UART's data register */
#define __PATMOS_UART_WR_DATA(data) *((_iodev_ptr_t)__PATMOS_UART_DATA_ADDR) = data;
/*
* End of UART Management
*/
/*
* RTC Management
*/
extern char _timer_base; /* linker symbol giving the address of the RTC */
#define PATMOS_FREQ_MHZ 74
#define PATMOS_FREQ_HZ ( PATMOS_FREQ_MHZ * 1000000U)
/* Address to access the cycle counter low register of the RTC */
#define __PATMOS_RTC_CYCLE_LOW_ADDR (&_timer_base + 0x00)
/* Address to access the cycle counter up register of the RTC */
#define __PATMOS_RTC_CYCLE_UP_ADDR (&_timer_base + 0x04)
/* Address to access the time in microseconds low register of the RTC */
#define __PATMOS_RTC_TIME_LOW_ADDR (&_timer_base + 0x08)
/* Address to access the time in microseconds up register of the RTC */
#define __PATMOS_RTC_TIME_UP_ADDR (&_timer_base + 0x0C)
/* Address to access the interrupt interval register of the RTC */
#define __PATMOS_RTC_INTERVAL_ADDR (&_timer_base + 0x10)
/* Address to access the ISR address register of the RTC */
#define __PATMOS_RTC_ISR_ADDR (&_timer_base + 0x14)
/* Macro to read the RTC's cycle counter low register of the RTC */
#define __PATMOS_RTC_RD_CYCLE_LOW(res) res = *((_iodev_ptr_t)__PATMOS_RTC_CYCLE_LOW_ADDR);
/* Macro to read the RTC's cycle counter up register of the RTC */
#define __PATMOS_RTC_RD_CYCLE_UP(res) res = *((_iodev_ptr_t)__PATMOS_RTC_CYCLE_UP_ADDR);
/* Macro to read the RTC's time in microseconds low register of the RTC */
#define __PATMOS_RTC_RD_TIME_LOW(res) res = *((_iodev_ptr_t)__PATMOS_RTC_TIME_LOW_ADDR);
/* Macro to read the RTC's time in microseconds up register of the RTC */
#define __PATMOS_RTC_RD_TIME_UP(res) res = *((_iodev_ptr_t)__PATMOS_RTC_TIME_UP_ADDR);
/* Macro to read the RTC's interrupt interval register */
#define __PATMOS_RTC_RD_INTERVAL(interval) interval = *((_iodev_ptr_t)__PATMOS_RTC_INTERVAL_ADDR);
/* Macro to write the RTC's cycle counter low register */
#define __PATMOS_RTC_WR_CYCLE_LOW(val) *((_iodev_ptr_t)__PATMOS_RTC_CYCLE_LOW_ADDR) = val;
/* Macro to write the RTC's cycle counter up register */
#define __PATMOS_RTC_WR_CYCLE_UP(val) *((_iodev_ptr_t)__PATMOS_RTC_CYCLE_UP_ADDR) = val;
/* Macro to write the RTC's interrupt interval register */
#define __PATMOS_RTC_WR_INTERVAL(interval) *((_iodev_ptr_t)__PATMOS_RTC_INTERVAL_ADDR) = interval;
/* Macro to write the RTC's ISR address register */
#define __PATMOS_RTC_WR_ISR(address) *((_iodev_ptr_t)__PATMOS_RTC_ISR_ADDR) = address;
/*
* End of RTC Management
*/
#endif /* !ASM */
#ifdef __cplusplus

View File

@@ -21,8 +21,10 @@ declare i32 @_close_r(%struct._reent* nocapture %ptr, i32 %fd) nounwind
declare i32 @boot_card(i32 %argc, i8** nocapture %argv, i8** nocapture %envp) nounwind
declare i32 @getdents(i32 %dd_fd, i32 %dd_buf, i32 %dd_len) nounwind
declare i32 @_rename_r(%struct._reent* nocapture %ptr, i32 %old, i32 %new) nounwind
declare i32 @rtems_clock_set_nanoseconds_extension(i32 ()* nocapture %routine) nounwind
declare i32 @rtems_clock_tick() nounwind
@llvm.used = appending global [17 x i8*] [
@llvm.used = appending global [19 x i8*] [
i8* bitcast (i32 (i8*)* @rtems_termios_write to i8*),
i8* bitcast (i32 (i8*, i32, i32)* @rtems_io_register_name to i8*),
i8* bitcast (void ()* @libc_init to i8*),
@@ -39,7 +41,9 @@ i8* bitcast (i32 (%struct._reent*, i32, i32, i32)* @_lseek_r to i8*),
i8* bitcast (i32 (%struct._reent*, i32)* @_close_r to i8*),
i8* bitcast (i32 (i32, i8**, i8**)* @boot_card to i8*),
i8* bitcast (i32 (i32, i32, i32)* @getdents to i8*),
i8* bitcast (i32 (%struct._reent*, i32, i32)* @_rename_r to i8*)
i8* bitcast (i32 (%struct._reent*, i32, i32)* @_rename_r to i8*),
i8* bitcast (i32 (i32()*)* @rtems_clock_set_nanoseconds_extension to i8*),
i8* bitcast (i32 ()* @rtems_clock_tick to i8*)
], section "llvm.metadata"
; End of libsyms.ll

View File

@@ -49,7 +49,7 @@ void _CPU_Initialize(void)
uint32_t _CPU_ISR_Get_level( void )
{
return 0;
return 0;
}
/*PAGE
@@ -71,11 +71,11 @@ uint32_t _CPU_ISR_Get_level( void )
*/
void _CPU_ISR_install_raw_handler(
uint32_t vector,
proc_ptr new_handler,
proc_ptr *old_handler
uint32_t vector,
proc_ptr new_handler,
proc_ptr *old_handler
)
{
{
}
/*PAGE
@@ -96,11 +96,11 @@ void _CPU_ISR_install_raw_handler(
*/
void _CPU_ISR_install_vector(
uint32_t vector,
proc_ptr new_handler,
proc_ptr *old_handler
uint32_t vector,
proc_ptr new_handler,
proc_ptr *old_handler
)
{
{
}
/*PAGE
@@ -122,338 +122,321 @@ void _CPU_ISR_install_vector(
*/
void _CPU_Context_Initialize(
Context_Control *the_context ,
uint32_t *stack_base ,
uint32_t size ,
uint32_t new_level ,
void *entry_point ,
uint32_t *shadow_stack_base
)
Context_Control *the_context ,
uint32_t *stack_base ,
uint32_t size ,
uint32_t new_level ,
void *entry_point ,
uint32_t *shadow_stack_base
)
{
/* set the shadow stack pointer */
the_context->r29 = (uint32_t)shadow_stack_base;
/* set the stack pointer and spill pointer */
the_context->s5 = (uint32_t)stack_base;
the_context->s6 = (uint32_t)stack_base;
/* set the return address */
the_context->r30 = (uint32_t)entry_point;
uint32_t stack_high; /* highest "stack aligned" address */
/* set the stack size */
the_context->ssize = 0;
/*
* On CPUs with stacks which grow down (i.e. PATMOS), we build the stack
* based on the stack_high address.
*/
stack_high = ((uint32_t)(stack_base) + size);
stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
/* set the shadow stack pointer */
the_context->r29 = (uint32_t)shadow_stack_base;
/* set the stack pointer and spill pointer */
the_context->s5 = stack_high;
the_context->s6 = stack_high;
/* set the return address */
the_context->r30 = (uint32_t)entry_point;
/* set the stack size */
the_context->ssize = 0;
}
void _CPU_Context_switch(
Context_Control *run ,
Context_Control *heir
)
Context_Control *run ,
Context_Control *heir
)
{
volatile unsigned int aux;
aux = (unsigned int) run;
aux = aux + (unsigned int) heir;
/*
* save general-purpose registers (skip r0 which is always 0)
* address of the previous task is passed as function argument in register r3
*/
asm volatile("swm [ $r3 + %0 ] = $r1 \n\t" //save r1
"swm [ $r3 + %1 ] = $r2 \n\t" //save r2
"swm [ $r3 + %2 ] = $r3 \n\t" //save r3
"swm [ $r3 + %3 ] = $r4 \n\t" //save r4
"swm [ $r3 + %4 ] = $r5 \n\t" //save r5
"swm [ $r3 + %5 ] = $r6 \n\t" //save r6
"swm [ $r3 + %6 ] = $r7 \n\t" //save r7
"swm [ $r3 + %7 ] = $r8 \n\t" //save r8
"swm [ $r3 + %8 ] = $r9 \n\t" //save r9
"swm [ $r3 + %9 ] = $r10 \n\t" //save r10
"swm [ $r3 + %10 ] = $r11 \n\t" //save r11
"swm [ $r3 + %11 ] = $r12 \n\t" //save r12
"swm [ $r3 + %12 ] = $r13 \n\t" //save r13
"swm [ $r3 + %13 ] = $r14 \n\t" //save r14
"swm [ $r3 + %14 ] = $r15 \n\t" //save r15
"swm [ $r3 + %15 ] = $r16 \n\t" //save r16
"swm [ $r3 + %16 ] = $r17 \n\t" //save r17
"swm [ $r3 + %17 ] = $r18 \n\t" //save r18
"swm [ $r3 + %18 ] = $r19 \n\t" //save r19
"swm [ $r3 + %19 ] = $r20 \n\t" //save r20
"swm [ $r3 + %20 ] = $r21 \n\t" //save r21
"swm [ $r3 + %21 ] = $r22 \n\t" //save r22
"swm [ $r3 + %22 ] = $r23 \n\t" //save r23
"swm [ $r3 + %23 ] = $r24 \n\t" //save r24
"swm [ $r3 + %24 ] = $r25 \n\t" //save r25
"swm [ $r3 + %25 ] = $r26 \n\t" //save r26
"swm [ $r3 + %26 ] = $r27 \n\t" //save r27
"swm [ $r3 + %27 ] = $r28 \n\t" //save r28
"swm [ $r3 + %28 ] = $r29 \n\t" //save r29
"swm [ $r3 + %29 ] = $r30 \n\t" //save r30
"swm [ $r3 + %30 ] = $r31 \n\t" //save r31
: : "i" (r1_OFFSET),"i" (r2_OFFSET), "i" (r3_OFFSET), "i" (r4_OFFSET), "i" (r5_OFFSET),
"i" (r6_OFFSET), "i" (r7_OFFSET), "i" (r8_OFFSET), "i" (r9_OFFSET), "i" (r10_OFFSET),
"i" (r11_OFFSET), "i" (r12_OFFSET), "i" (r13_OFFSET), "i" (r14_OFFSET), "i" (r15_OFFSET),
"i" (r16_OFFSET), "i" (r17_OFFSET), "i" (r18_OFFSET), "i" (r19_OFFSET), "i" (r20_OFFSET),
"i" (r21_OFFSET), "i" (r22_OFFSET), "i" (r23_OFFSET), "i" (r24_OFFSET), "i" (r25_OFFSET),
"i" (r26_OFFSET), "i" (r27_OFFSET), "i" (r28_OFFSET), "i" (r29_OFFSET), "i" (r30_OFFSET),
"i" (r31_OFFSET));
asm volatile("swm [ %0 + %1 ] = $r1 \n\t" //save r1
"swm [ %0 + %2 ] = $r2 \n\t" //save r2
"swm [ %0 + %3 ] = $r3 \n\t" //save r3
"swm [ %0 + %4 ] = $r4 \n\t" //save r4
"swm [ %0 + %5 ] = $r5 \n\t" //save r5
"swm [ %0 + %6 ] = $r6 \n\t" //save r6
"swm [ %0 + %7 ] = $r7 \n\t" //save r7
"swm [ %0 + %8 ] = $r8 \n\t" //save r8
"swm [ %0 + %9 ] = $r9 \n\t" //save r9
"swm [ %0 + %10 ] = $r10 \n\t" //save r10
"swm [ %0 + %11 ] = $r11 \n\t" //save r11
"swm [ %0 + %12 ] = $r12 \n\t" //save r12
"swm [ %0 + %13 ] = $r13 \n\t" //save r13
"swm [ %0 + %14 ] = $r14 \n\t" //save r14
"swm [ %0 + %15 ] = $r15 \n\t" //save r15
"swm [ %0 + %16 ] = $r16 \n\t" //save r16
"swm [ %0 + %17 ] = $r17 \n\t" //save r17
"swm [ %0 + %18 ] = $r18 \n\t" //save r18
"swm [ %0 + %19 ] = $r19 \n\t" //save r19
"swm [ %0 + %20 ] = $r20 \n\t" //save r20
"swm [ %0 + %21 ] = $r21 \n\t" //save r21
"swm [ %0 + %22 ] = $r22 \n\t" //save r22
"swm [ %0 + %23 ] = $r23 \n\t" //save r23
"swm [ %0 + %24 ] = $r24 \n\t" //save r24
"swm [ %0 + %25 ] = $r25 \n\t" //save r25
"swm [ %0 + %26 ] = $r26 \n\t" //save r26
"swm [ %0 + %27 ] = $r27 \n\t" //save r27
"swm [ %0 + %28 ] = $r28 \n\t" //save r28
"swm [ %0 + %29 ] = $r29 \n\t" //save r29
"swm [ %0 + %30 ] = $r30 \n\t" //save r30
"swm [ %0 + %31 ] = $r31 \n\t" //save r31
: : "r" (run), "i" (r1_OFFSET),"i" (r2_OFFSET), "i" (r3_OFFSET), "i" (r4_OFFSET),
"i" (r5_OFFSET), "i" (r6_OFFSET), "i" (r7_OFFSET), "i" (r8_OFFSET), "i" (r9_OFFSET),
"i" (r10_OFFSET), "i" (r11_OFFSET), "i" (r12_OFFSET), "i" (r13_OFFSET), "i" (r14_OFFSET),
"i" (r15_OFFSET), "i" (r16_OFFSET), "i" (r17_OFFSET), "i" (r18_OFFSET), "i" (r19_OFFSET),
"i" (r20_OFFSET), "i" (r21_OFFSET), "i" (r22_OFFSET), "i" (r23_OFFSET), "i" (r24_OFFSET),
"i" (r25_OFFSET), "i" (r26_OFFSET), "i" (r27_OFFSET), "i" (r28_OFFSET), "i" (r29_OFFSET),
"i" (r30_OFFSET), "i" (r31_OFFSET));
/*
* copy the current stack to memory and save the stack size to the Context_Control struct in memory
*/
asm volatile("mfs $r5 = $s5 \n\t"
"mfs $r6 = $s6 \n\t"
"sub $r2 = $r5, $r6 \n\t" // get stack size
"sspill $r2 \n\t"
"swm [ $r3 + %0 ] = $r2 \n\t" //save stack size to memory
: : "i" (ssize_OFFSET));
"mfs $r6 = $s6 \n\t"
"sub $r2 = $r5, $r6 \n\t" // get stack size
"sspill $r2 \n\t"
"swm [ %0 + %1 ] = $r2 \n\t" //save stack size to memory
: : "r" (run), "i" (ssize_OFFSET));
/*
* save special-purpose registers
* use r1 as intermediate register to save special-purpose registers (no instruction to do it directly)
*/
asm volatile("mfs $r1 = $s0 \n\t" //move s0 to r1
"swm [ $r3 + %0 ] = $r1 \n\t" //save s0
"mfs $r1 = $s1 \n\t" //move s1 to r1
"swm [ $r3 + %1 ] = $r1 \n\t" //save s1
"mfs $r1 = $s2 \n\t" //move s2 to r1
"swm [ $r3 + %2 ] = $r1 \n\t" //save s2
"mfs $r1 = $s3 \n\t" //move s3 to r1
"swm [ $r3 + %3 ] = $r1 \n\t" //save s3
"mfs $r1 = $s4 \n\t" //move s4 to r1
"swm [ $r3 + %4 ] = $r1 \n\t" //save s4
"mfs $r1 = $s5 \n\t" //move s5 to r1
"swm [ $r3 + %5 ] = $r1 \n\t" //save s5
"mfs $r1 = $s6 \n\t" //move s6 to r1
"swm [ $r3 + %6 ] = $r1 \n\t" //save s6
"mfs $r1 = $s7 \n\t" //move s7 to r1
"swm [ $r3 + %7 ] = $r1 \n\t" //save s7
"mfs $r1 = $s8 \n\t" //move s8 to r1
"swm [ $r3 + %8 ] = $r1 \n\t" //save s8
"mfs $r1 = $s9 \n\t" //move s9 to r1
"swm [ $r3 + %9 ] = $r1 \n\t" //save s9
"mfs $r1 = $s10 \n\t" //move s10 to r1
"swm [ $r3 + %10 ] = $r1 \n\t" //save s10
"mfs $r1 = $s11 \n\t" //move s11 to r1
"swm [ $r3 + %11 ] = $r1 \n\t" //save s11
"mfs $r1 = $s12 \n\t" //move s12 to r1
"swm [ $r3 + %12 ] = $r1 \n\t" //save s12
"mfs $r1 = $s13 \n\t" //move s13 to r1
"swm [ $r3 + %13 ] = $r1 \n\t" //save s13
"mfs $r1 = $s14 \n\t" //move s14 to r1
"swm [ $r3 + %14 ] = $r1 \n\t" //save s14
"mfs $r1 = $s15 \n\t" //move s15 to r1
"swm [ $r3 + %15 ] = $r1 \n\t" //save s15
: : "i" (s0_OFFSET), "i" (s1_OFFSET), "i" (s2_OFFSET), "i" (s3_OFFSET),
"i" (s4_OFFSET), "i" (s5_OFFSET), "i" (s6_OFFSET), "i" (s7_OFFSET),
"i" (s8_OFFSET), "i" (s9_OFFSET), "i" (s10_OFFSET),"i" (s11_OFFSET),
"i" (s12_OFFSET), "i" (s13_OFFSET), "i" (s14_OFFSET), "i" (s15_OFFSET));
asm volatile("mfs $r1 = $s0 \n\t" //move s0 to r1
"swm [ %0 + %1 ] = $r1 \n\t" //save s0
"mfs $r1 = $s1 \n\t" //move s1 to r1
"swm [ %0 + %2 ] = $r1 \n\t" //save s1
"mfs $r1 = $s2 \n\t" //move s2 to r1
"swm [ %0 + %3 ] = $r1 \n\t" //save s2
"mfs $r1 = $s3 \n\t" //move s3 to r1
"swm [ %0 + %4 ] = $r1 \n\t" //save s3
"mfs $r1 = $s4 \n\t" //move s4 to r1
"swm [ %0 + %5 ] = $r1 \n\t" //save s4
"mfs $r1 = $s5 \n\t" //move s5 to r1
"swm [ %0 + %6 ] = $r1 \n\t" //save s5
"mfs $r1 = $s6 \n\t" //move s6 to r1
"swm [ %0 + %7 ] = $r1 \n\t" //save s6
"mfs $r1 = $s7 \n\t" //move s7 to r1
"swm [ %0 + %8 ] = $r1 \n\t" //save s7
"mfs $r1 = $s8 \n\t" //move s8 to r1
"swm [ %0 + %9 ] = $r1 \n\t" //save s8
"mfs $r1 = $s9 \n\t" //move s9 to r1
"swm [ %0 + %10 ] = $r1 \n\t" //save s9
"mfs $r1 = $s10 \n\t" //move s10 to r1
"swm [ %0 + %11 ] = $r1 \n\t" //save s10
"mfs $r1 = $s11 \n\t" //move s11 to r1
"swm [ %0 + %12 ] = $r1 \n\t" //save s11
"mfs $r1 = $s12 \n\t" //move s12 to r1
"swm [ %0 + %13 ] = $r1 \n\t" //save s12
"mfs $r1 = $s13 \n\t" //move s13 to r1
"swm [ %0 + %14 ] = $r1 \n\t" //save s13
"mfs $r1 = $s14 \n\t" //move s14 to r1
"swm [ %0 + %15 ] = $r1 \n\t" //save s14
"mfs $r1 = $s15 \n\t" //move s15 to r1
"swm [ %0 + %16 ] = $r1 \n\t" //save s15
: : "r" (run), "i" (s0_OFFSET), "i" (s1_OFFSET), "i" (s2_OFFSET), "i" (s3_OFFSET),
"i" (s4_OFFSET), "i" (s5_OFFSET), "i" (s6_OFFSET), "i" (s7_OFFSET), "i" (s8_OFFSET),
"i" (s9_OFFSET), "i" (s10_OFFSET),"i" (s11_OFFSET), "i" (s12_OFFSET), "i" (s13_OFFSET),
"i" (s14_OFFSET), "i" (s15_OFFSET));
/*
* load general-purpose registers (skip r0 which is always 0)
* address of the current task is passed as function argument in register r4
* r4 is the last register to be loaded so that the memory address of the current task is not lost
* r1 will be used as auxiliary register, so it is not loaded yet
*/
asm volatile("lwc $r2 = [ $r4 + %0 ] \n\t" //load r2
"lwc $r3 = [ $r4 + %1 ] \n\t" //load r3
"lwc $r5 = [ $r4 + %2 ] \n\t" //load r5
"lwc $r6 = [ $r4 + %3 ] \n\t" //load r6
"lwc $r7 = [ $r4 + %4 ] \n\t" //load r7
"lwc $r8 = [ $r4 + %5 ] \n\t" //load r8
"lwc $r9 = [ $r4 + %6 ] \n\t" //load r9
"lwc $r10 = [ $r4 + %7 ] \n\t" //load r10
"lwc $r11 = [ $r4 + %8 ] \n\t" //load r11
"lwc $r12 = [ $r4 + %9 ] \n\t" //load r12
"lwc $r13 = [ $r4 + %10 ] \n\t" //load r13
"lwc $r14 = [ $r4 + %11 ] \n\t" //load r14
"lwc $r15 = [ $r4 + %12 ] \n\t" //load r15
"lwc $r16 = [ $r4 + %13 ] \n\t" //load r16
"lwc $r17 = [ $r4 + %14 ] \n\t" //load r17
"lwc $r18 = [ $r4 + %15 ] \n\t" //load r18
"lwc $r19 = [ $r4 + %16 ] \n\t" //load r19
"lwc $r20 = [ $r4 + %17 ] \n\t" //load r20
"lwc $r21 = [ $r4 + %18 ] \n\t" //load r21
"lwc $r22 = [ $r4 + %19 ] \n\t" //load r22
"lwc $r23 = [ $r4 + %20 ] \n\t" //load r23
"lwc $r24 = [ $r4 + %21 ] \n\t" //load r24
"lwc $r25 = [ $r4 + %22 ] \n\t" //load r25
"lwc $r26 = [ $r4 + %23 ] \n\t" //load r26
"lwc $r27 = [ $r4 + %24 ] \n\t" //load r27
"lwc $r28 = [ $r4 + %25 ] \n\t" //load r28
"lwc $r29 = [ $r4 + %26 ] \n\t" //load r29
"lwc $r30 = [ $r4 + %27 ] \n\t" //load r30
"lwc $r31 = [ $r4 + %28 ] \n\t" //load r31
: : "i" (r2_OFFSET), "i" (r3_OFFSET), "i" (r5_OFFSET), "i" (r6_OFFSET), "i" (r7_OFFSET),
"i" (r8_OFFSET), "i" (r9_OFFSET), "i" (r10_OFFSET), "i" (r11_OFFSET), "i" (r12_OFFSET),
"i" (r13_OFFSET), "i" (r14_OFFSET), "i" (r15_OFFSET), "i" (r16_OFFSET), "i" (r17_OFFSET),
"i" (r18_OFFSET), "i" (r19_OFFSET), "i" (r20_OFFSET), "i" (r21_OFFSET), "i" (r22_OFFSET),
"i" (r23_OFFSET), "i" (r24_OFFSET), "i" (r25_OFFSET), "i" (r26_OFFSET), "i" (r27_OFFSET),
"i" (r28_OFFSET), "i" (r29_OFFSET), "i" (r30_OFFSET), "i" (r31_OFFSET));
asm volatile("lwc $r2 = [ %0 + %1 ] \n\t" //load r2
"lwc $r3 = [ %0 + %2 ] \n\t" //load r3
"lwc $r5 = [ %0 + %3 ] \n\t" //load r5
"lwc $r6 = [ %0 + %4 ] \n\t" //load r6
"lwc $r7 = [ %0 + %5 ] \n\t" //load r7
"lwc $r8 = [ %0 + %6 ] \n\t" //load r8
"lwc $r9 = [ %0 + %7 ] \n\t" //load r9
"lwc $r10 = [ %0 + %8 ] \n\t" //load r10
"lwc $r11 = [ %0 + %9 ] \n\t" //load r11
"lwc $r12 = [ %0 + %10 ] \n\t" //load r12
"lwc $r13 = [ %0 + %11 ] \n\t" //load r13
"lwc $r14 = [ %0 + %12 ] \n\t" //load r14
"lwc $r15 = [ %0 + %13 ] \n\t" //load r15
"lwc $r16 = [ %0 + %14 ] \n\t" //load r16
"lwc $r17 = [ %0 + %15 ] \n\t" //load r17
"lwc $r18 = [ %0 + %16 ] \n\t" //load r18
"lwc $r19 = [ %0 + %17 ] \n\t" //load r19
"lwc $r20 = [ %0 + %18 ] \n\t" //load r20
"lwc $r21 = [ %0 + %19 ] \n\t" //load r21
"lwc $r22 = [ %0 + %20 ] \n\t" //load r22
"lwc $r23 = [ %0 + %21 ] \n\t" //load r23
"lwc $r24 = [ %0 + %22 ] \n\t" //load r24
"lwc $r25 = [ %0 + %23 ] \n\t" //load r25
"lwc $r26 = [ %0 + %24 ] \n\t" //load r26
"lwc $r27 = [ %0 + %25 ] \n\t" //load r27
"lwc $r28 = [ %0 + %26 ] \n\t" //load r28
"lwc $r29 = [ %0 + %27 ] \n\t" //load r29
"lwc $r30 = [ %0 + %28 ] \n\t" //load r30
"lwc $r31 = [ %0 + %29 ] \n\t" //load r31
: : "r" (heir), "i" (r2_OFFSET), "i" (r3_OFFSET), "i" (r5_OFFSET), "i" (r6_OFFSET),
"i" (r7_OFFSET), "i" (r8_OFFSET), "i" (r9_OFFSET), "i" (r10_OFFSET), "i" (r11_OFFSET),
"i" (r12_OFFSET), "i" (r13_OFFSET), "i" (r14_OFFSET), "i" (r15_OFFSET), "i" (r16_OFFSET),
"i" (r17_OFFSET), "i" (r18_OFFSET), "i" (r19_OFFSET), "i" (r20_OFFSET), "i" (r21_OFFSET),
"i" (r22_OFFSET), "i" (r23_OFFSET), "i" (r24_OFFSET), "i" (r25_OFFSET), "i" (r26_OFFSET),
"i" (r27_OFFSET), "i" (r28_OFFSET), "i" (r29_OFFSET), "i" (r30_OFFSET), "i" (r31_OFFSET));
asm volatile("lwm $r1 = [ $r4 + %0 ] \n\t" //load ssize
"sens $r1 \n\t" //ensure the stack size in the stack cache
: : "i" (ssize_OFFSET));
/*
* load special-purpose registers
* use r1 as intermediate register to load special-purpose registers (no instruction to do it directly)
*/
asm volatile("lwc $r1 = [ $r4 + %0 ] \n\t" //load s0
"mts $s0 = $r1 \n\t" //move r1 to s0
"lwc $r1 = [ $r4 + %1 ] \n\t" //load s1
"mts $s1 = $r1 \n\t" //move r1 to s1
"lwc $r1 = [ $r4 + %2 ] \n\t" //load s2
"mts $s2 = $r1 \n\t" //move r1 to s2
"lwc $r1 = [ $r4 + %3 ] \n\t" //load s3
"mts $s3 = $r1 \n\t" //move r1 to s3
"lwc $r1 = [ $r4 + %4 ] \n\t" //load s4
"mts $s4 = $r1 \n\t" //move r1 to s4
"lwc $r1 = [ $r4 + %5 ] \n\t" //load s5
"mts $s5 = $r1 \n\t" //move r1 to s5
"lwc $r1 = [ $r4 + %6 ] \n\t" //load s6
"mts $s6 = $r1 \n\t" //move r1 to s6
"lwc $r1 = [ $r4 + %7 ] \n\t" //load s7
"mts $s7 = $r1 \n\t" //move r1 to s7
"lwc $r1 = [ $r4 + %8 ] \n\t" //load s8
"mts $s8 = $r1 \n\t" //move r1 to s8
"lwc $r1 = [ $r4 + %9 ] \n\t" //load s9
"mts $s9 = $r1 \n\t" //move r1 to s9
"lwc $r1 = [ $r4 + %10 ] \n\t" //load s10
"mts $s10 = $r1 \n\t" //move r1 to s10
"lwc $r1 = [ $r4 + %11 ] \n\t" //load s11
"mts $s11 = $r1 \n\t" //move r1 to s11
"lwc $r1 = [ $r4 + %12 ] \n\t" //load s12
"mts $s12 = $r1 \n\t" //move r1 to s12
"lwc $r1 = [ $r4 + %13 ] \n\t" //load s13
"mts $s13 = $r1 \n\t" //move r1 to s13
"lwc $r1 = [ $r4 + %14 ] \n\t" //load s14
"mts $s14 = $r1 \n\t" //move r1 to s14
"lwc $r1 = [ $r4 + %15 ] \n\t" //load s15
"mts $s15 = $r1 \n\t" //move r1 to s15
: : "i" (s0_OFFSET), "i" (s1_OFFSET), "i" (s2_OFFSET), "i" (s3_OFFSET), "i" (s4_OFFSET),
"i" (s5_OFFSET), "i" (s6_OFFSET), "i" (s7_OFFSET), "i" (s8_OFFSET), "i" (s9_OFFSET),
"i" (s10_OFFSET), "i" (s11_OFFSET), "i" (s12_OFFSET), "i" (s13_OFFSET), "i" (s14_OFFSET),
"i" (s15_OFFSET));
/*
* restore the thread's stack into the stack cache
* use r1 to store the size of the thread's stack
* use r2 and r3 as intermediate registers to load special-purpose registers (no instruction to do it directly)
*/
asm volatile(//"mfs $r2 = $s6 \n\t" //store the stack cache's top pointer in auxiliary register r2
//"mfs $r3 = $s5 \n\t" //store the stack cache's bottom pointer in auxiliary register r3
//"sub $r1 = $r2, $r3 \n\t" //store the size of the thread's stack
//"mts $s6 = $r3 \n\t" //make stack cache's bottom and top pointers equal to each other
//"sens $r1 \n\t" //restores the thread's stack into the stack cache
//"mts $s6 = $r2 \n\t" //restore the stack cache's top pointer from auxiliary register r2
"lwc $r1 = [ $r4 + %0 ] \n\t" //load r1
"lwc $r4 = [ $r4 + %1 ] \n\t" //load r4
: : "i" (r1_OFFSET), "i" (r4_OFFSET));
asm volatile("lwc $r1 = [ %0 + %1 ] \n\t nop \n\t" //load s0
"mts $s0 = $r1 \n\t" //move r1 to s0
"lwc $r1 = [ %0 + %2 ] \n\t nop \n\t" //load s1
"mts $s1 = $r1 \n\t" //move r1 to s1
"lwc $r1 = [ %0 + %3 ] \n\t nop \n\t" //load s2
"mts $s2 = $r1 \n\t" //move r1 to s2
"lwc $r1 = [ %0 + %4 ] \n\t nop \n\t" //load s3
"mts $s3 = $r1 \n\t" //move r1 to s3
"lwc $r1 = [ %0 + %5 ] \n\t nop \n\t" //load s4
"mts $s4 = $r1 \n\t" //move r1 to s4
"lwc $r1 = [ %0 + %6 ] \n\t nop \n\t" //load s5
"mts $s5 = $r1 \n\t" //move r1 to s5
"lwc $r1 = [ %0 + %7 ] \n\t nop \n\t" //load s6
"mts $s6 = $r1 \n\t" //move r1 to s6
"lwc $r1 = [ %0 + %8 ] \n\t nop \n\t" //load s7
"mts $s7 = $r1 \n\t" //move r1 to s7
"lwc $r1 = [ %0 + %9 ] \n\t nop \n\t" //load s8
"mts $s8 = $r1 \n\t" //move r1 to s8
"lwc $r1 = [ %0 + %10 ] \n\t nop \n\t" //load s9
"mts $s9 = $r1 \n\t" //move r1 to s9
"lwc $r1 = [ %0 + %11 ] \n\t nop \n\t" //load s10
"mts $s10 = $r1 \n\t" //move r1 to s10
"lwc $r1 = [ %0 + %12 ] \n\t nop \n\t" //load s11
"mts $s11 = $r1 \n\t" //move r1 to s11
"lwc $r1 = [ %0 + %13 ] \n\t nop \n\t" //load s12
"mts $s12 = $r1 \n\t" //move r1 to s12
"lwc $r1 = [ %0 + %14 ] \n\t nop \n\t" //load s13
"mts $s13 = $r1 \n\t" //move r1 to s13
"lwc $r1 = [ %0 + %15 ] \n\t nop \n\t" //load s14
"mts $s14 = $r1 \n\t" //move r1 to s14
"lwc $r1 = [ %0 + %16 ] \n\t nop \n\t" //load s15
"mts $s15 = $r1 \n\t" //move r1 to s15
: : "r" (heir), "i" (s0_OFFSET), "i" (s1_OFFSET), "i" (s2_OFFSET), "i" (s3_OFFSET),
"i" (s4_OFFSET), "i" (s5_OFFSET), "i" (s6_OFFSET), "i" (s7_OFFSET), "i" (s8_OFFSET),
"i" (s9_OFFSET), "i" (s10_OFFSET), "i" (s11_OFFSET), "i" (s12_OFFSET), "i" (s13_OFFSET),
"i" (s14_OFFSET), "i" (s15_OFFSET));
asm volatile("lwm $r1 = [ %0 + %1 ] \n\t nop \n\t" //load ssize
"sens $r1 \n\t" //ensure the stack size in the stack cache
"lwc $r1 = [ %0 + %2 ] \n\t" //load r1
"lwc $r4 = [ %0 + %3 ] \n\t" //load r4
: : "r" (heir), "i" (ssize_OFFSET), "i" (r1_OFFSET), "i" (r4_OFFSET));
}
void _CPU_Context_restore(
Context_Control *new_context
)
Context_Control *new_context
)
{
volatile unsigned int aux;
aux = (unsigned int) new_context + 1;
/*
* load general-purpose registers (skip r0 which is always 0)
* address of the current task is passed as function argument in register r3
* r3 is the last register to be loaded so that the memory address of the current task is not lost
* r1 will be used as auxiliary register, so it is not loaded yet
*/
asm volatile("lwc $r2 = [ $r3 + %0 ] \n\t" //load r2
"lwc $r4 = [ $r3 + %1 ] \n\t" //load r4
"lwc $r5 = [ $r3 + %2 ] \n\t" //load r5
"lwc $r6 = [ $r3 + %3 ] \n\t" //load r6
"lwc $r7 = [ $r3 + %4 ] \n\t" //load r7
"lwc $r8 = [ $r3 + %5 ] \n\t" //load r8
"lwc $r9 = [ $r3 + %6 ] \n\t" //load r9
"lwc $r10 = [ $r3 + %7 ] \n\t" //load r10
"lwc $r11 = [ $r3 + %8 ] \n\t" //load r11
"lwc $r12 = [ $r3 + %9 ] \n\t" //load r12
"lwc $r13 = [ $r3 + %10 ] \n\t" //load r13
"lwc $r14 = [ $r3 + %11 ] \n\t" //load r14
"lwc $r15 = [ $r3 + %12 ] \n\t" //load r15
"lwc $r16 = [ $r3 + %13 ] \n\t" //load r16
"lwc $r17 = [ $r3 + %14 ] \n\t" //load r17
"lwc $r18 = [ $r3 + %15 ] \n\t" //load r18
"lwc $r19 = [ $r3 + %16 ] \n\t" //load r19
"lwc $r20 = [ $r3 + %17 ] \n\t" //load r20
"lwc $r21 = [ $r3 + %18 ] \n\t" //load r21
"lwc $r22 = [ $r3 + %19 ] \n\t" //load r22
"lwc $r23 = [ $r3 + %20 ] \n\t" //load r23
"lwc $r24 = [ $r3 + %21 ] \n\t" //load r24
"lwc $r25 = [ $r3 + %22 ] \n\t" //load r25
"lwc $r26 = [ $r3 + %23 ] \n\t" //load r26
"lwc $r27 = [ $r3 + %24 ] \n\t" //load r27
"lwc $r28 = [ $r3 + %25 ] \n\t" //load r28
"lwc $r29 = [ $r3 + %26 ] \n\t" //load r29
"lwc $r30 = [ $r3 + %27 ] \n\t" //load r30
"lwc $r31 = [ $r3 + %28 ] \n\t" //load r31
: : "i" (r2_OFFSET), "i" (r4_OFFSET), "i" (r5_OFFSET), "i" (r6_OFFSET), "i" (r7_OFFSET),
"i" (r8_OFFSET), "i" (r9_OFFSET), "i" (r10_OFFSET), "i" (r11_OFFSET), "i" (r12_OFFSET),
"i" (r13_OFFSET), "i" (r14_OFFSET), "i" (r15_OFFSET), "i" (r16_OFFSET), "i" (r17_OFFSET),
"i" (r18_OFFSET), "i" (r19_OFFSET), "i" (r20_OFFSET), "i" (r21_OFFSET), "i" (r22_OFFSET),
"i" (r23_OFFSET), "i" (r24_OFFSET), "i" (r25_OFFSET), "i" (r26_OFFSET), "i" (r27_OFFSET),
"i" (r28_OFFSET), "i" (r29_OFFSET), "i" (r30_OFFSET), "i" (r31_OFFSET));
asm volatile("lwm $r1 = [ $r3 + %0 ] \n\t" //load ssize
"sens $r1 \n\t" //ensure the stack size in the stack cache
: : "i" (ssize_OFFSET));
asm volatile("lwc $r2 = [ %0 + %1 ] \n\t" //load r2
"lwc $r4 = [ %0 + %2 ] \n\t" //load r4
"lwc $r5 = [ %0 + %3 ] \n\t" //load r5
"lwc $r6 = [ %0 + %4 ] \n\t" //load r6
"lwc $r7 = [ %0 + %5 ] \n\t" //load r7
"lwc $r8 = [ %0 + %6 ] \n\t" //load r8
"lwc $r9 = [ %0 + %7 ] \n\t" //load r9
"lwc $r10 = [ %0 + %8 ] \n\t" //load r10
"lwc $r11 = [ %0 + %9 ] \n\t" //load r11
"lwc $r12 = [ %0 + %10 ] \n\t" //load r12
"lwc $r13 = [ %0 + %11 ] \n\t" //load r13
"lwc $r14 = [ %0 + %12 ] \n\t" //load r14
"lwc $r15 = [ %0 + %13 ] \n\t" //load r15
"lwc $r16 = [ %0 + %14 ] \n\t" //load r16
"lwc $r17 = [ %0 + %15 ] \n\t" //load r17
"lwc $r18 = [ %0 + %16 ] \n\t" //load r18
"lwc $r19 = [ %0 + %17 ] \n\t" //load r19
"lwc $r20 = [ %0 + %18 ] \n\t" //load r20
"lwc $r21 = [ %0 + %19 ] \n\t" //load r21
"lwc $r22 = [ %0 + %20 ] \n\t" //load r22
"lwc $r23 = [ %0 + %21 ] \n\t" //load r23
"lwc $r24 = [ %0 + %22 ] \n\t" //load r24
"lwc $r25 = [ %0 + %23 ] \n\t" //load r25
"lwc $r26 = [ %0 + %24 ] \n\t" //load r26
"lwc $r27 = [ %0 + %25 ] \n\t" //load r27
"lwc $r28 = [ %0 + %26 ] \n\t" //load r28
"lwc $r29 = [ %0 + %27 ] \n\t" //load r29
"lwc $r30 = [ %0 + %28 ] \n\t" //load r30
"lwc $r31 = [ %0 + %29 ] \n\t" //load r31
: : "r" (new_context), "i" (r2_OFFSET), "i" (r4_OFFSET), "i" (r5_OFFSET), "i" (r6_OFFSET),
"i" (r7_OFFSET), "i" (r8_OFFSET), "i" (r9_OFFSET), "i" (r10_OFFSET), "i" (r11_OFFSET),
"i" (r12_OFFSET), "i" (r13_OFFSET), "i" (r14_OFFSET), "i" (r15_OFFSET), "i" (r16_OFFSET),
"i" (r17_OFFSET), "i" (r18_OFFSET), "i" (r19_OFFSET), "i" (r20_OFFSET), "i" (r21_OFFSET),
"i" (r22_OFFSET), "i" (r23_OFFSET), "i" (r24_OFFSET), "i" (r25_OFFSET), "i" (r26_OFFSET),
"i" (r27_OFFSET), "i" (r28_OFFSET), "i" (r29_OFFSET), "i" (r30_OFFSET), "i" (r31_OFFSET));
/*
* load special-purpose registers
* load special-purpose registers
* use r1 as intermediate register to load special-purpose registers (no instruction to do it directly)
*/
asm volatile("lwc $r1 = [ $r3 + %0 ] \n\t" //load s0
"mts $s0 = $r1 \n\t" //move r1 to s0
"lwc $r1 = [ $r3 + %1 ] \n\t" //load s1
"mts $s1 = $r1 \n\t" //move r1 to s1
"lwc $r1 = [ $r3 + %2 ] \n\t" //load s2
"mts $s2 = $r1 \n\t" //move r1 to s2
"lwc $r1 = [ $r3 + %3 ] \n\t" //load s3
"mts $s3 = $r1 \n\t" //move r1 to s3
"lwc $r1 = [ $r3 + %4 ] \n\t" //load s4
"mts $s4 = $r1 \n\t" //move r1 to s4
"lwc $r1 = [ $r3 + %5 ] \n\t" //load s5
"mts $s5 = $r1 \n\t" //move r1 to s5
"lwc $r1 = [ $r3 + %6 ] \n\t" //load s6
"mts $s6 = $r1 \n\t" //move r1 to s6
"lwc $r1 = [ $r3 + %7 ] \n\t" //load s7
"mts $s7 = $r1 \n\t" //move r1 to s7
"lwc $r1 = [ $r3 + %8 ] \n\t" //load s8
"mts $s8 = $r1 \n\t" //move r1 to s8
"lwc $r1 = [ $r3 + %9 ] \n\t" //load s9
"mts $s9 = $r1 \n\t" //move r1 to s9
"lwc $r1 = [ $r3 + %10 ] \n\t" //load s10
"mts $s10 = $r1 \n\t" //move r1 to s10
"lwc $r1 = [ $r3 + %11 ] \n\t" //load s11
"mts $s11 = $r1 \n\t" //move r1 to s11
"lwc $r1 = [ $r3 + %12 ] \n\t" //load s12
"mts $s12 = $r1 \n\t" //move r1 to s12
"lwc $r1 = [ $r3 + %13 ] \n\t" //load s13
"mts $s13 = $r1 \n\t" //move r1 to s13
"lwc $r1 = [ $r3 + %14 ] \n\t" //load s14
"mts $s14 = $r1 \n\t" //move r1 to s14
"lwc $r1 = [ $r3 + %15 ] \n\t" //load s15
"mts $s15 = $r1 \n\t" //move r1 to s15
: : "i" (s0_OFFSET), "i" (s1_OFFSET), "i" (s2_OFFSET), "i" (s3_OFFSET), "i" (s4_OFFSET),
"i" (s5_OFFSET), "i" (s6_OFFSET), "i" (s7_OFFSET), "i" (s8_OFFSET), "i" (s9_OFFSET),
"i" (s10_OFFSET), "i" (s11_OFFSET), "i" (s12_OFFSET), "i" (s13_OFFSET), "i" (s14_OFFSET),
"i" (s15_OFFSET));
/*
* restore r1 and r3
*/
asm volatile("lwc $r1 = [ $r3 + %0 ] \n\t" //load r1
"lwc $r3 = [ $r3 + %1 ] \n\t" //load r3
: : "i" (r1_OFFSET), "i" (r3_OFFSET));
asm volatile("lwc $r1 = [ %0 + %1 ] \n\t nop \n\t" //load s0
"mts $s0 = $r1 \n\t" //move r1 to s0
"lwc $r1 = [ %0 + %2 ] \n\t nop \n\t" //load s1
"mts $s1 = $r1 \n\t" //move r1 to s1
"lwc $r1 = [ %0 + %3 ] \n\t nop \n\t" //load s2
"mts $s2 = $r1 \n\t" //move r1 to s2
"lwc $r1 = [ %0 + %4 ] \n\t nop \n\t" //load s3
"mts $s3 = $r1 \n\t" //move r1 to s3
"lwc $r1 = [ %0 + %5 ] \n\t nop \n\t" //load s4
"mts $s4 = $r1 \n\t" //move r1 to s4
"lwc $r1 = [ %0 + %6 ] \n\t nop \n\t" //load s5
"mts $s5 = $r1 \n\t" //move r1 to s5
"lwc $r1 = [ %0 + %7 ] \n\t nop \n\t" //load s6
"mts $s6 = $r1 \n\t" //move r1 to s6
"lwc $r1 = [ %0 + %8 ] \n\t nop \n\t" //load s7
"mts $s7 = $r1 \n\t" //move r1 to s7
"lwc $r1 = [ %0 + %9 ] \n\t nop \n\t" //load s8
"mts $s8 = $r1 \n\t" //move r1 to s8
"lwc $r1 = [ %0 + %10 ] \n\t nop \n\t" //load s9
"mts $s9 = $r1 \n\t" //move r1 to s9
"lwc $r1 = [ %0 + %11 ] \n\t nop \n\t" //load s10
"mts $s10 = $r1 \n\t" //move r1 to s10
"lwc $r1 = [ %0 + %12 ] \n\t nop \n\t" //load s11
"mts $s11 = $r1 \n\t" //move r1 to s11
"lwc $r1 = [ %0 + %13 ] \n\t nop \n\t" //load s12
"mts $s12 = $r1 \n\t" //move r1 to s12
"lwc $r1 = [ %0 + %14 ] \n\t nop \n\t" //load s13
"mts $s13 = $r1 \n\t" //move r1 to s13
"lwc $r1 = [ %0 + %15 ] \n\t nop \n\t" //load s14
"mts $s14 = $r1 \n\t" //move r1 to s14
"lwc $r1 = [ %0 + %16 ] \n\t nop \n\t" //load s15
"mts $s15 = $r1 \n\t" //move r1 to s15
: : "r" (new_context), "i" (s0_OFFSET), "i" (s1_OFFSET), "i" (s2_OFFSET), "i" (s3_OFFSET),
"i" (s4_OFFSET), "i" (s5_OFFSET), "i" (s6_OFFSET), "i" (s7_OFFSET), "i" (s8_OFFSET),
"i" (s9_OFFSET), "i" (s10_OFFSET), "i" (s11_OFFSET), "i" (s12_OFFSET), "i" (s13_OFFSET),
"i" (s14_OFFSET), "i" (s15_OFFSET));
asm volatile("lwm $r1 = [ %0 + %1 ] \n\t nop \n\t" //load ssize
"sens $r1 \n\t" //ensure the stack size in the stack cache
"lwc $r1 = [ %0 + %2 ] \n\t" //load r1
"lwc $r3 = [ %0 + %3 ] \n\t" //load r3
: : "r" (new_context), "i" (ssize_OFFSET), "i" (r1_OFFSET), "i" (r3_OFFSET));
}
void abort_trap()

View File

@@ -335,12 +335,16 @@ typedef struct {
#define ssize_OFFSET 47
#define r0_OFFSET 48
/*
* context control size (in number of bytes)
*/
#define CONTEXT_CONTROL_SIZE 192
#define CONTEXT_OFFSET 200
/**
*
* This macro returns the stack pointer associated with _context.
@@ -541,7 +545,7 @@ SCORE_EXTERN volatile uint32_t _CPU_ISR_Dispatch_disable;
* NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
*/
#define CPU_STACK_ALIGNMENT 0
#define CPU_STACK_ALIGNMENT 16
#ifndef ASM