mirror of
				https://github.com/0xFEEDC0DE64/arduino-esp32.git
				synced 2025-11-03 23:51:39 +01:00 
			
		
		
		
	
		
			
	
	
		
			141 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			141 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
							 | 
						||
| 
								 | 
							
								
							 |