140 lines
5.5 KiB
C
140 lines
5.5 KiB
C
// overlay_os_asm.h -- Overlay manager assembly macros for OS use.
|
|
// $Id$
|
|
|
|
// Copyright (c) 2013 Tensilica Inc.
|
|
//
|
|
// 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.
|
|
|
|
|
|
#ifndef OVERLAY_OS_ASM_H
|
|
#define OVERLAY_OS_ASM_H
|
|
|
|
// The macros in here are intended to be used by RTOS task switch code
|
|
// to check overlay status. Such code is usually in assembly and cannot
|
|
// call C code without penalty. For C code usage, it is best to use the
|
|
// corresponding C functions from the library.
|
|
|
|
|
|
// Inline assembly version of xt_overlay_get_state(). The arguments are
|
|
// three AR registers (a0-a15):
|
|
//
|
|
// "pcreg" - should contain the outgoing task's PC, i.e. the point at
|
|
// which the task got interrupted. The return value is also
|
|
// returned in this register.
|
|
// "sr1/2" - Scratch registers. These must be distinct from "pcreg".
|
|
//
|
|
// The return value is a 32-bit result that should be saved with the
|
|
// task context and passed as-is to xt_overlay_check_map.
|
|
|
|
.macro _xt_overlay_get_state pcreg sr1 sr2
|
|
|
|
movi \sr1, _mapping_id
|
|
movi \sr2, _ovly_id
|
|
l16si \sr1, \sr1, 0
|
|
l16ui \sr2, \sr2, 0
|
|
slli \sr1, \sr1, 16
|
|
or \pcreg, \sr1, \sr2
|
|
|
|
.endm
|
|
|
|
|
|
// Inline assembly version of xt_overlay_check_map(). It requires 5 AR
|
|
// registers (a0-a15) as arguments.
|
|
//
|
|
// "pcreg" - should contain the interrupted task's PC, i.e. the point
|
|
// at which the task got interrupted. This will be adjusted
|
|
// if required.
|
|
// "psreg" - should contain the interrupted task's PS. This will be
|
|
// adjusted if required.
|
|
// "ovreg" - should contain the overlay state on entry. Contents may
|
|
// be clobbered.
|
|
// "spreg" - should contain the tasks stack pointer on entry.
|
|
// "sr1" - Scratch register. Must be distinct from any of the above.
|
|
//
|
|
// The return values are "pcreg" and "psreg" and these must be used
|
|
// to update the task's PC and PS.
|
|
// Note that this macro may store data below the "spreg" pointer. If
|
|
// it does, then it will also disable interrupts via the PS, so that
|
|
// the task resumes with all interrupts disabled (to avoid corrupting
|
|
// this data).
|
|
//
|
|
// (SP - 24) Overlay ID to restore
|
|
// (SP - 28) Task PC
|
|
// (SP - 32) Task PS
|
|
|
|
.macro _xt_overlay_check_map pcreg psreg ovreg spreg sr1
|
|
|
|
// There are four cases to deal with:
|
|
//
|
|
// _ovly_id = -1, _mapping_id = -1
|
|
// No overlay is mapped or mapping, nothing to do.
|
|
//
|
|
// _ovly_id >= 0, _mapping_id = -1
|
|
// An overlay was mapped, check PC to see if we need a restore.
|
|
//
|
|
// _ovly_id = -1, _mapping_id >= 0
|
|
// An overlay is being mapped. Either it belongs to this task, which
|
|
// implies that the PC is in the mapping function, or it does not
|
|
// belong to this task. Either way there is nothing to do.
|
|
//
|
|
// _ovly_id >= 0, _mapping_id >= 0
|
|
// Illegal, cannot happen by design. Don't need to handle this.
|
|
//
|
|
// So, the logic is to check _ovly_id first. If this is >= 0, then
|
|
// we check the task PC. If the PC is in the regions of interest then
|
|
// we'll patch the return PC to invoke xt_overlay_restore.
|
|
|
|
.L1:
|
|
extui \sr1, \ovreg, 0, 16 // Extract _ovly_id
|
|
bbsi.l \sr1, 15, .Lno // If -1 then we're done
|
|
mov \ovreg, \sr1 // Restore this one
|
|
|
|
// Next check the PC to see if it falls within the ranges of interest.
|
|
|
|
.L2:
|
|
movi \sr1, _overlay_vma // Is PC < VMA range ?
|
|
bltu \pcreg, \sr1, .L3
|
|
movi \sr1, _overlay_vma_end // Is PC > VMA range ?
|
|
bgeu \pcreg, \sr1, .L3
|
|
j .L4 // PC is in VMA range
|
|
.L3:
|
|
movi \sr1, _overlay_call_stubs_start // Is PC < call stubs range ?
|
|
bltu \pcreg, \sr1, .Lno
|
|
movi \sr1, _overlay_call_stubs_end // Is PC > call stubs range ?
|
|
bgeu \pcreg, \sr1, .Lno
|
|
|
|
// If we get here then a restore is needed. Save the overlay ID, PC and PS.
|
|
// Return modified PC and PS so that xt_overlay_restore() will execute in
|
|
// the context of the task when resumed. Note that the OS resumption code
|
|
// may expect PS.EXCM to be set so we leave it as is in the return value.
|
|
|
|
.L4:
|
|
s32e \ovreg, \spreg, -24 // Save overlay ID
|
|
s32e \pcreg, \spreg, -28 // Save task PC
|
|
s32e \psreg, \spreg, -32 // Save task PS
|
|
movi \pcreg, xt_overlay_restore // Adjust resumption PC
|
|
movi \sr1, 15
|
|
or \psreg, \psreg, \sr1 // Set intlevel to highest
|
|
.Lno:
|
|
|
|
.endm
|
|
|
|
#endif // OVERLAY_OS_ASM_H
|
|
|