x86: iamcu: Add support for the IAMCU calling convention.
Add support for compilers conforming to the IAMCU calling convention as documented by https://github.com/hjl-tools/x86-psABI/wiki/iamcu-psABI-0.7.pdf Change-Id: I6fd9d5bede0538b2049772e3850a5940c5dd911e Signed-off-by: Dirk Brandewie <dirk.j.brandewie@intel.com>
This commit is contained in:
parent
8683dc4836
commit
d8a1c8ef17
16 changed files with 595 additions and 3 deletions
|
@ -22,6 +22,18 @@ menu "x86 architecture"
|
|||
config ARCH
|
||||
default "x86"
|
||||
|
||||
config X86_IAMCU
|
||||
bool
|
||||
default n
|
||||
prompt "IAMCU calling convention"
|
||||
help
|
||||
The IAMCU calling convention changes the X86 C calling convention to
|
||||
pass some arguments via registers allowing for code size and performance
|
||||
improvements. Great care needs to be taken if you have assembly code
|
||||
that will be called from C or C code called from assembly code, the
|
||||
assembly code will need to be updated to conform to the new calling
|
||||
convention. If in doubt say N
|
||||
|
||||
config ARCH_DEFCONFIG
|
||||
string
|
||||
default "arch/x86/defconfig"
|
||||
|
|
|
@ -11,7 +11,11 @@ endif
|
|||
# character starts a comment
|
||||
KBUILD_AFLAGS += -Wa,--divide
|
||||
|
||||
obj-y = i386_sysV_abi/
|
||||
ifndef CONFIG_X86_IAMCU
|
||||
obj-y += i386_sysV_abi/
|
||||
else
|
||||
obj-y += iamcu_abi/
|
||||
endif
|
||||
|
||||
obj-y += gdt.o fatal.o cpuhalt.o \
|
||||
msr.o dynamic.o intconnect.o \
|
||||
|
|
6
arch/x86/core/iamcu_abi/Makefile
Normal file
6
arch/x86/core/iamcu_abi/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
ccflags-y += -I$(srctree)/kernel/nanokernel/include
|
||||
ccflags-y += -I$(srctree)/kernel/microkernel/include
|
||||
|
||||
obj-y += swap.o intstub.o thread.o \
|
||||
iamcu.o
|
||||
|
132
arch/x86/core/iamcu_abi/iamcu.S
Normal file
132
arch/x86/core/iamcu_abi/iamcu.S
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define _ASMLANGUAGE
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <sections.h>
|
||||
#include <nano_private.h>
|
||||
#include <arch/x86/asm.h>
|
||||
#include <offsets.h> /* nanokernel structure offset definitions */
|
||||
#include <arch/cpu.h> /* _NANO_ERR_SPURIOUS_INT */
|
||||
|
||||
|
||||
GTEXT(_thread_entry_wrapper)
|
||||
GTEXT(_thread_entry)
|
||||
GTEXT(_irq_sw_handler)
|
||||
|
||||
/*
|
||||
* @brief Wrapper for _thread_entry
|
||||
*
|
||||
* The routine pops parameters for the _thread_entry from stack frame, prepared
|
||||
* by the _new_thread() routine.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, _thread_entry_wrapper)
|
||||
popl %eax
|
||||
popl %edx
|
||||
popl %ecx
|
||||
jmp _thread_entry
|
||||
|
||||
|
||||
#if CONFIG_IRQ_OFFLOAD
|
||||
SECTION_FUNC(TEXT, _irq_sw_handler)
|
||||
pushl %eax
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
call _irq_do_offload
|
||||
pop %ecx
|
||||
pop %edx
|
||||
pop %eax
|
||||
iret
|
||||
#endif
|
||||
|
||||
#if ALL_DYN_IRQ_STUBS > 0
|
||||
|
||||
|
||||
|
||||
BRANCH_LABEL(_DynIntStubCommon)
|
||||
pushl %eax
|
||||
pushl %ecx
|
||||
movl _common_dynamic_irq_handler, %eax
|
||||
call _execute_handler
|
||||
/* Clean up and call IRET */
|
||||
pop %ecx
|
||||
pop %eax
|
||||
pop %edx
|
||||
iret
|
||||
|
||||
|
||||
/* Create all the dynamic IRQ stubs
|
||||
*
|
||||
* NOTE: Please update DYN_STUB_SIZE in include/arch/x86/arch.h if you change
|
||||
* how large the generated stubs are, otherwise _get_dynamic_stub() will
|
||||
* be unable to correctly determine the offset
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create nice labels for all the stubs so we can see where we
|
||||
* are in a debugger
|
||||
*/
|
||||
.altmacro
|
||||
.macro __INT_STUB_NUM id
|
||||
BRANCH_LABEL(_DynIntStub\id)
|
||||
.endm
|
||||
.macro INT_STUB_NUM id
|
||||
__INT_STUB_NUM %id
|
||||
.endm
|
||||
GTEXT(_DynIntStubsBegin)
|
||||
SECTION_FUNC(TEXT, _DynIntStubsBegin)
|
||||
stub_num = 0
|
||||
|
||||
.rept ((ALL_DYN_IRQ_STUBS + DYN_STUB_PER_BLOCK - 1) / DYN_STUB_PER_BLOCK)
|
||||
block_counter = 0
|
||||
.rept DYN_STUB_PER_BLOCK
|
||||
.if stub_num < ALL_DYN_IRQ_STUBS
|
||||
INT_STUB_NUM stub_num
|
||||
|
||||
pushl %edx
|
||||
|
||||
|
||||
/*
|
||||
* 2-byte push imm8. Consumed by
|
||||
* common_dynamic_handler(), see intconnect.c
|
||||
*/
|
||||
movl $stub_num, %edx
|
||||
|
||||
/*
|
||||
* Check to make sure this isn't the last stub in
|
||||
* a block, in which case we just fall through
|
||||
*/
|
||||
.if (block_counter <> (DYN_STUB_PER_BLOCK - 1) && \
|
||||
(stub_num <> ALL_DYN_IRQ_STUBS - 1))
|
||||
/* This should always be a 2-byte jmp rel8 */
|
||||
jmp 1f
|
||||
.endif
|
||||
stub_num = stub_num + 1
|
||||
block_counter = block_counter + 1
|
||||
.endif
|
||||
.endr
|
||||
/*
|
||||
* This must a 5-bvte jump rel32, which is why _DynStubCommon
|
||||
* is before the actual stubs
|
||||
*/
|
||||
1: jmp _DynIntStubCommon
|
||||
.endr
|
||||
#endif /* ALL_DYN_IRQ_STUBS */
|
||||
|
115
arch/x86/core/iamcu_abi/intstub.c
Normal file
115
arch/x86/core/iamcu_abi/intstub.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <nano_private.h>
|
||||
#include <drivers/loapic.h>
|
||||
|
||||
extern void _sys_power_save_idle_exit(int32_t ticks);
|
||||
|
||||
#ifdef CONFIG_NESTED_INTERRUPTS
|
||||
static inline void enable_interrupts(void)
|
||||
{
|
||||
__asm__ volatile("sti");
|
||||
};
|
||||
#else
|
||||
static inline void enable_interrupts(void){};
|
||||
#endif
|
||||
|
||||
static inline void disable_interrupts(void)
|
||||
{
|
||||
__asm__ volatile("sti");
|
||||
};
|
||||
|
||||
typedef void (*int_handler_t) (int context);
|
||||
|
||||
void _execute_handler(int_handler_t function, int context)
|
||||
{
|
||||
_int_latency_start();
|
||||
|
||||
if (!_nanokernel.nested) {
|
||||
/* move to the interrupt stack and push current stack
|
||||
* pointer onto interrupt stack
|
||||
*/
|
||||
__asm__ volatile ("movl %%esp, %%edx \n\t"
|
||||
"movl %0, %%esp \n\t"
|
||||
"pushl %%edx \n\t"
|
||||
:
|
||||
:"m" (_nanokernel.common_isp)
|
||||
:"%edx"
|
||||
);
|
||||
}
|
||||
_nanokernel.nested++;
|
||||
|
||||
#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT
|
||||
if (_nanokernel.idle) {
|
||||
_sys_power_save_idle_exit(_nanokernel.idle);
|
||||
_nanokernel.idle = 0;
|
||||
}
|
||||
#endif
|
||||
_int_latency_stop();
|
||||
enable_interrupts();
|
||||
|
||||
(*function)(context);
|
||||
_loapic_eoi();
|
||||
|
||||
disable_interrupts();
|
||||
_nanokernel.nested--;
|
||||
|
||||
/* Are we returning to a task or fiber context? If so we need
|
||||
* to do some work based on the context that was interrupted
|
||||
*/
|
||||
if (!_nanokernel.nested) {
|
||||
/* switch to kernel stack */
|
||||
__asm__ volatile ("popl %esp");
|
||||
|
||||
/* if the interrupted context was a task we need to
|
||||
* swap back to the interrupted context
|
||||
*/
|
||||
if ((_nanokernel.current->flags & PREEMPTIBLE) &&
|
||||
_nanokernel.fiber) {
|
||||
/* move flags into arg0 we can't use local
|
||||
* variables here since the stack may have
|
||||
* changed.
|
||||
*/
|
||||
__asm__ volatile ("pushfl \n\t"
|
||||
"popl %eax \n\t"
|
||||
"call _Swap");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _SpuriousIntHandler(void)
|
||||
{
|
||||
__asm__ volatile("cld"); /* clear direction flag */
|
||||
|
||||
/*
|
||||
* The task's regular stack is being used, but push the value of ESP
|
||||
* anyway so that _ExcExit can "recover the stack pointer"
|
||||
* without determining whether the exception occurred while CPL=3
|
||||
*/
|
||||
__asm__ volatile ("pushl %esp");
|
||||
|
||||
again:
|
||||
_NanoFatalErrorHandler(_NANO_ERR_SPURIOUS_INT, &_default_esf);
|
||||
/* The handler should no return but if it does call it again */
|
||||
goto again;
|
||||
}
|
||||
|
||||
void _SpuriousIntNoErrCodeHandler(void)
|
||||
{
|
||||
__asm__ volatile ("pushl %eax");
|
||||
_SpuriousIntHandler();
|
||||
}
|
68
arch/x86/core/iamcu_abi/swap.c
Normal file
68
arch/x86/core/iamcu_abi/swap.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <sections.h>
|
||||
#include <nano_private.h>
|
||||
|
||||
unsigned int _Swap(unsigned int eflags)
|
||||
{
|
||||
struct tcs *next;
|
||||
int rv;
|
||||
|
||||
/* Save the current context onto the stack */
|
||||
__asm__ volatile("pushl %eax\n\t" /* push eflags _Swap argumet*/
|
||||
"pushl %edi\n\t"
|
||||
"pushl %esi\n\t"
|
||||
"pushl %ebx\n\t"
|
||||
"pushl %ebp\n\t"
|
||||
"pushl %ebx\n\t"); /* eax slot for fiber return */
|
||||
|
||||
/* save the stack pointer into the current context structure */
|
||||
__asm__ volatile("mov %%esp, %0"
|
||||
:"=m" (_nanokernel.current->coopReg.esp));
|
||||
|
||||
/* find the next context to run */
|
||||
if (_nanokernel.fiber) {
|
||||
next = _nanokernel.fiber;
|
||||
_nanokernel.fiber = (struct tcs *)_nanokernel.fiber->link;
|
||||
} else {
|
||||
next = _nanokernel.task;
|
||||
}
|
||||
_nanokernel.current = next;
|
||||
|
||||
/* recover the stack pointer for the incoming context */
|
||||
__asm__ volatile("mov %0, %%esp"
|
||||
:
|
||||
:"m" (next->coopReg.esp));
|
||||
|
||||
/* restore the context */
|
||||
__asm__ volatile("popl %eax\n\t"
|
||||
"popl %ebp\n\t"
|
||||
"popl %ebx\n\t"
|
||||
"popl %esi\n\t"
|
||||
"popl %edi\n\t"
|
||||
"popfl \n\t"
|
||||
);
|
||||
|
||||
/* The correct return value is already in eax but this makes
|
||||
* the compiler happy
|
||||
*/
|
||||
__asm__ volatile("mov %%eax, %0"
|
||||
:"=m" (rv)
|
||||
);
|
||||
return rv;
|
||||
}
|
141
arch/x86/core/iamcu_abi/thread.c
Normal file
141
arch/x86/core/iamcu_abi/thread.c
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_MICROKERNEL
|
||||
#include <microkernel.h>
|
||||
#include <micro_private_types.h>
|
||||
#endif /* CONFIG_MICROKERNEL */
|
||||
#ifdef CONFIG_INIT_STACKS
|
||||
#include <string.h>
|
||||
#endif /* CONFIG_INIT_STACKS */
|
||||
|
||||
#include <toolchain.h>
|
||||
#include <sections.h>
|
||||
#include <nano_private.h>
|
||||
#include <wait_q.h>
|
||||
|
||||
/* the one and only nanokernel control structure */
|
||||
|
||||
tNANO _nanokernel = {0};
|
||||
|
||||
/* forward declaration to asm function to adjust setup the arguments
|
||||
* to _thread_entry()
|
||||
*/
|
||||
void _thread_entry_wrapper(_thread_entry_t, _thread_arg_t,
|
||||
_thread_arg_t, _thread_arg_t);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Create a new kernel execution context
|
||||
*
|
||||
* This function initializes a thread control structure (TCS) for a
|
||||
* new kernel execution context. A fake stack frame is created as if
|
||||
* the context had been "swapped out" via _Swap()
|
||||
*
|
||||
* @param stack_memory pointer to the context stack area
|
||||
* @param stack_size size of contexts stack area
|
||||
* @param thread_func new contexts entry function
|
||||
* @param parameter1 first entry function parameter
|
||||
* @param parameter2 second entry function parameter
|
||||
* @param parameter3 third entry function parameter
|
||||
* @param priority Priority of the new context
|
||||
* @param options Additional options for the context
|
||||
*
|
||||
* @return none
|
||||
*
|
||||
* \NOMANUAL
|
||||
*/
|
||||
|
||||
void _new_thread(char *stack_memory, unsigned stack_size,
|
||||
_thread_entry_t thread_func, void *parameter1,
|
||||
void *parameter2, void *parameter3, int priority,
|
||||
unsigned options)
|
||||
{
|
||||
unsigned long *thread_context;
|
||||
struct tcs *tcs = (struct tcs *)stack_memory;
|
||||
|
||||
ARG_UNUSED(options);
|
||||
|
||||
#ifdef CONFIG_INIT_STACKS
|
||||
memset(stack_memory, 0xaa, stack_size);
|
||||
#endif
|
||||
|
||||
tcs->link = (struct tcs *)NULL; /* thread not inserted into list yet */
|
||||
tcs->prio = priority;
|
||||
|
||||
if (priority == -1) {
|
||||
tcs->flags = PREEMPTIBLE | TASK;
|
||||
} else {
|
||||
tcs->flags = FIBER;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_THREAD_CUSTOM_DATA
|
||||
/* Initialize custom data field (value is opaque to kernel) */
|
||||
|
||||
tcs->custom_data = NULL;
|
||||
#endif
|
||||
|
||||
/* carve the thread entry struct from the "base" of the stack */
|
||||
|
||||
thread_context =
|
||||
(unsigned long *)STACK_ROUND_DOWN(stack_memory + stack_size);
|
||||
|
||||
/*
|
||||
* Create an initial context on the stack expected by the _Swap()
|
||||
* primitive.
|
||||
* Given that both task and fibers execute at privilege 0, the
|
||||
* setup for both threads are equivalent.
|
||||
*/
|
||||
|
||||
/* push arguments required by _thread_entry() */
|
||||
|
||||
*--thread_context = (unsigned long)parameter3;
|
||||
*--thread_context = (unsigned long)parameter2;
|
||||
*--thread_context = (unsigned long)parameter1;
|
||||
*--thread_context = (unsigned long)thread_func;
|
||||
|
||||
/* push initial EFLAGS; only modify IF and IOPL bits */
|
||||
|
||||
*--thread_context = (unsigned long)_thread_entry_wrapper;
|
||||
*--thread_context = (EflagsGet() & ~EFLAGS_MASK) | EFLAGS_INITIAL;
|
||||
*--thread_context = 0;
|
||||
*--thread_context = 0;
|
||||
*--thread_context = 0;
|
||||
--thread_context;
|
||||
*thread_context = (unsigned long)(thread_context + 4);
|
||||
*--thread_context = 0;
|
||||
|
||||
tcs->coopReg.esp = (unsigned long)thread_context;
|
||||
#if defined(CONFIG_THREAD_MONITOR)
|
||||
{
|
||||
unsigned int imask;
|
||||
|
||||
/*
|
||||
* Add the newly initialized thread to head of the
|
||||
* list of threads. This singly linked list of threads
|
||||
* maintains ALL the threads in the system: both tasks
|
||||
* and fibers regardless of whether they are runnable.
|
||||
*/
|
||||
|
||||
imask = irq_lock();
|
||||
tcs->next_thread = _nanokernel.threads;
|
||||
_nanokernel.threads = tcs;
|
||||
irq_unlock(imask);
|
||||
}
|
||||
#endif /* CONFIG_THREAD_MONITOR */
|
||||
|
||||
_nano_timeout_tcs_init(tcs);
|
||||
}
|
|
@ -14,3 +14,5 @@ CONFIG_IPM_CONSOLE_RECEIVER=y
|
|||
CONFIG_ARC_INIT=y
|
||||
CONFIG_PINMUX=y
|
||||
CONFIG_PINMUX_NUM_PINS=58
|
||||
CONFIG_X86_IAMCU=y
|
||||
CONFIG_TOOLCHAIN_VARIANT="iamcu"
|
||||
|
|
|
@ -11,3 +11,5 @@ CONFIG_SERIAL_HAS_DRIVER=y
|
|||
CONFIG_PRINTK=y
|
||||
CONFIG_ISR_STACK_SIZE=256
|
||||
CONFIG_MAIN_STACK_SIZE=512
|
||||
CONFIG_X86_IAMCU=y
|
||||
CONFIG_TOOLCHAIN_VARIANT="iamcu"
|
||||
|
|
|
@ -12,3 +12,5 @@ CONFIG_IPM_QUARK_SE=y
|
|||
CONFIG_IPM_QUARK_SE_MASTER=y
|
||||
CONFIG_IPM_CONSOLE_RECEIVER=y
|
||||
CONFIG_ARC_INIT=y
|
||||
CONFIG_X86_IAMCU=y
|
||||
CONFIG_TOOLCHAIN_VARIANT="iamcu"
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
|
||||
#define ALL_DYN_STUBS (ALL_DYN_EXC_STUBS + ALL_DYN_IRQ_STUBS)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Synchronize these DYN_STUB_* macros with the generated assembly for
|
||||
* _DynIntStubsBegin in intstub.S / _DynExcStubsBegin in excstub.S
|
||||
|
@ -58,7 +60,11 @@
|
|||
*/
|
||||
|
||||
/* Size of each dynamic interrupt/exception stub in bytes */
|
||||
#ifdef CONFIG_IAMCU
|
||||
#define DYN_STUB_SIZE 8
|
||||
#else
|
||||
#define DYN_STUB_SIZE 9
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Offset from the beginning of a stub to the byte containing the argument
|
||||
|
|
|
@ -57,6 +57,7 @@ extern "C" {
|
|||
#ifdef _ASMLANGUAGE
|
||||
loapic_eoi = (CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_EOI)
|
||||
|
||||
#if !defined(CONFIG_X86_IAMCU)
|
||||
.macro loapic_mkstub device isr context
|
||||
GTEXT(_\()\device\()_\()\isr\()_stub)
|
||||
|
||||
|
@ -66,6 +67,25 @@ SECTION_FUNC(TEXT, _\()\device\()_\()\isr\()_stub)
|
|||
call \isr /* Call actual interrupt handler */
|
||||
jmp _IntExitWithEoi /* Inform kernel interrupt is done */
|
||||
.endm
|
||||
#else
|
||||
|
||||
.macro loapic_mkstub device isr context
|
||||
|
||||
GTEXT(_\()\device\()_\()\isr\()_stub)
|
||||
|
||||
SECTION_FUNC(TEXT, _\()\device\()_\()\isr\()_stub)
|
||||
pushl %eax
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
movl $\isr, %eax
|
||||
movl $\context, %edx
|
||||
call _execute_handler
|
||||
pop %ecx
|
||||
pop %edx
|
||||
pop %eax
|
||||
iret
|
||||
.endm
|
||||
#endif /* CONFIG_X86_IAMCU */
|
||||
|
||||
#else /* _ASMLANGUAGE */
|
||||
#include <device.h>
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#error test_asm_inline_gcc.h goes only with x86 GCC
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_X86_IAMCU)
|
||||
static inline void isr_dummy(void)
|
||||
{
|
||||
extern void _IntEnt(void);
|
||||
|
@ -39,5 +40,27 @@ static inline void isr_dummy(void)
|
|||
: :
|
||||
);
|
||||
}
|
||||
#else
|
||||
typedef void (*int_handler_t) (int context);
|
||||
|
||||
static inline void isr_dummy(void)
|
||||
{
|
||||
extern void _execute_handler(int_handler_t function, int context);
|
||||
|
||||
__asm__ volatile (
|
||||
"pushl %%eax \n\t"
|
||||
"pushl %%edx \n\t"
|
||||
"pushl %%ecx \n\t"
|
||||
"mov dummyIsr, %%eax \n\t"
|
||||
"movl $0, %%edx \n\t"
|
||||
"call _execute_handler \n\t"
|
||||
"pop %%ecx \n\t"
|
||||
"pop %%edx \n\t"
|
||||
"pop %%eax \n\t"
|
||||
"iret \n\t"
|
||||
: :
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TEST_ASM_INLINE_GCC_H */
|
||||
|
|
|
@ -49,14 +49,26 @@ SYS_NANO_CPU_EXC_CONNECT(exc_divide_error_handler,IV_DIVIDE_ERROR)
|
|||
|
||||
|
||||
GTEXT(nanoIntStub)
|
||||
|
||||
#if !defined(CONFIG_X86_IAMCU)
|
||||
SECTION_FUNC(TEXT, nanoIntStub)
|
||||
call _IntEnt
|
||||
pushl $0
|
||||
call isr_handler
|
||||
addl $4, %esp
|
||||
jmp _IntExit
|
||||
|
||||
#else
|
||||
SECTION_FUNC(TEXT, nanoIntStub)
|
||||
pushl %eax
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
movl $isr_handler, %eax
|
||||
movl $0, %edx
|
||||
call _execute_handler
|
||||
pop %ecx
|
||||
pop %edx
|
||||
pop %eax
|
||||
iret
|
||||
#endif
|
||||
#else
|
||||
|
||||
#error Arch not supported
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#error test_asm_inline_gcc.h goes only with x86 GCC
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_X86_IAMCU)
|
||||
static inline void isr_dummy(void)
|
||||
{
|
||||
extern void _IntEnt(void);
|
||||
|
@ -39,5 +40,27 @@ static inline void isr_dummy(void)
|
|||
: :
|
||||
);
|
||||
}
|
||||
#else
|
||||
typedef void (*int_handler_t) (int context);
|
||||
|
||||
static inline void isr_dummy(void)
|
||||
{
|
||||
extern void _execute_handler(int_handler_t function, int context);
|
||||
|
||||
__asm__ volatile (
|
||||
"pushl %%eax \n\t"
|
||||
"pushl %%edx \n\t"
|
||||
"pushl %%ecx \n\t"
|
||||
"mov dummyIsr, %%eax \n\t"
|
||||
"movl $0, %%edx \n\t"
|
||||
"call _execute_handler \n\t"
|
||||
"pop %%ecx \n\t"
|
||||
"pop %%edx \n\t"
|
||||
"pop %%eax \n\t"
|
||||
"iret \n\t"
|
||||
: :
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TEST_ASM_INLINE_GCC_H */
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#error test_asm_inline_gcc.h goes only with x86 GCC
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_X86_IAMCU)
|
||||
static inline void isr_dummy(void)
|
||||
{
|
||||
extern void _IntEnt(void);
|
||||
|
@ -40,4 +41,27 @@ static inline void isr_dummy(void)
|
|||
);
|
||||
}
|
||||
|
||||
#else
|
||||
typedef void (*int_handler_t) (int context);
|
||||
|
||||
static inline void isr_dummy(void)
|
||||
{
|
||||
extern void _execute_handler(int_handler_t function, int context);
|
||||
|
||||
__asm__ volatile (
|
||||
"pushl %%eax \n\t"
|
||||
"pushl %%edx \n\t"
|
||||
"pushl %%ecx \n\t"
|
||||
"mov dummyIsr, %%eax \n\t"
|
||||
"movl $0, %%edx \n\t"
|
||||
"call _execute_handler \n\t"
|
||||
"pop %%ecx \n\t"
|
||||
"pop %%edx \n\t"
|
||||
"pop %%eax \n\t"
|
||||
"iret \n\t"
|
||||
: :
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TEST_ASM_INLINE_GCC_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue