X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/4d15aeb193b2c68f1d38666c317f8d3734f5f083..5ba3f43ea354af8ad55bea84372a2bc834d8757c:/osfmk/arm/asm.h diff --git a/osfmk/arm/asm.h b/osfmk/arm/asm.h new file mode 100644 index 000000000..f27a8763a --- /dev/null +++ b/osfmk/arm/asm.h @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2007 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* + * @OSF_COPYRIGHT@ + */ +/* + * Mach Operating System + * Copyright (c) 1991,1990,1989 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef _ARM_ASM_H_ +#define _ARM_ASM_H_ + +#include + +#define FRAME pushl %ebp; movl %esp, %ebp +#define EMARF leave + + +/* There is another definition of ALIGN for .c sources */ +#ifdef ASSEMBLER +#define ALIGN 2 +#endif /* ASSEMBLER */ + +#ifndef FALIGN +#define FALIGN ALIGN +#endif + +#define LB(x,n) n +#if __STDC__ +#ifndef __NO_UNDERSCORES__ +#define LCL(x) L ## x +#define EXT(x) _ ## x +#define LEXT(x) _ ## x ## : +#else +#define LCL(x) .L ## x +#define EXT(x) x +#define LEXT(x) x ## : +#endif +#define LBc(x,n) n ## : +#define LBb(x,n) n ## b +#define LBf(x,n) n ## f +#else /* __STDC__ */ +#ifndef __NO_UNDERSCORES__ +#define LCL(x) L/**/x +#define EXT(x) _/**/x +#define LEXT(x) _/**/x/**/: +#else /* __NO_UNDERSCORES__ */ +#define LCL(x) .L/**/x +#define EXT(x) x +#define LEXT(x) x/**/: +#endif /* __NO_UNDERSCORES__ */ +#define LBc(x,n) n/**/: +#define LBb(x,n) n/**/b +#define LBf(x,n) n/**/f +#endif /* __STDC__ */ + +#define String .asciz +#define Value .word +#define Times(a,b) (a*b) +#define Divide(a,b) (a/b) + +#if 0 /* TOTOJK */ +#ifdef __ELF__ +#define ELF_FUNC(x) .type x,@function +#define ELF_DATA(x) .type x,@object +#define ELF_SIZE(x,s) .size x,s +#else +#define ELF_FUNC(x) +#define ELF_DATA(x) +#define ELF_SIZE(x,s) +#endif +#else +#define ELF_FUNC(x) +#define ELF_DATA(x) +#define ELF_SIZE(x,s) +#endif /* TODOJK */ + +#define Entry(x) .globl EXT(x); ELF_FUNC(EXT(x)); .align FALIGN; LEXT(x) +#define ENTRY(x) Entry(x) MCOUNT +#define ENTRY2(x,y) .globl EXT(x); .globl EXT(y); \ + ELF_FUNC(EXT(x)); ELF_FUNC(EXT(y)); \ + .align FALIGN; LEXT(x); LEXT(y) \ + MCOUNT +#if __STDC__ +#define ASENTRY(x) .globl x; .align FALIGN; x ## : ELF_FUNC(x) MCOUNT +#else +#define ASENTRY(x) .globl x; .align FALIGN; x: ELF_FUNC(x) MCOUNT +#endif /* __STDC__ */ + +#define DATA(x) .globl EXT(x); ELF_DATA(EXT(x)); .align ALIGN; LEXT(x) + +#define End(x) ELF_SIZE(x,.-x) +#define END(x) End(EXT(x)) +#define ENDDATA(x) END(x) +#define Enddata(x) End(x) + +#ifdef ASSEMBLER + +#define MCOUNT + +#else /* NOT ASSEMBLER */ + +/* These defines are here for .c files that wish to reference global symbols + * within __asm__ statements. + */ +#ifndef __NO_UNDERSCORES__ +#define CC_SYM_PREFIX "_" +#else +#define CC_SYM_PREFIX "" +#endif /* __NO_UNDERSCORES__ */ +#endif /* ASSEMBLER */ + +#ifdef ASSEMBLER + +#if defined (_ARM_ARCH_4T) +# define RET bx lr +# define RETeq bxeq lr +# define RETne bxne lr +# ifdef __STDC__ +# define RETc(c) bx##c lr +# else +# define RETc(c) bx/**/c lr +# endif +#else +# define RET mov pc, lr +# define RETeq moveq pc, lr +# define RETne movne pc, lr +# ifdef __STDC__ +# define RETc(c) mov##c pc, lr +# else +# define RETc(c) mov/**/c pc, lr +# endif +#endif + +#if defined (__thumb__) +/* Provide a PI mechanism for thumb branching. */ +# define BRANCH_EXTERN(x) ldr pc, [pc, #-4] ; \ + .long EXT(x) +#else +# define BRANCH_EXTERN(x) b EXT(x) +#endif + +/* + * arg0: Register for thread pointer + */ +.macro READ_THREAD + mrc p15, 0, $0, c13, c0, 4 /* Read TPIDRPRW */ +.endmacro + + +/* Macros for loading up addresses that are external to the .s file. + * LOAD_ADDR: loads the address for (label) into (reg). Not safe for + * loading to the PC. + * LOAD_ADDR_PC: Variant for loading to the PC; load the address of (label) + * into the pc. + * LOAD_ADDR_GEN_DEF: The general definition needed to support loading + * a label address. + * + * Usage: For any label accessed, we require one (and only one) instance + * of LOAD_ADDR_GEN_DEF(label). + * + * Example: + * LOAD_ADDR(r0, arm_init) + * LOAD_ADDR(lr, arm_init_cpu) + * LOAD_ADDR_PC(arm_init) + * ... + * + * LOAD_ADDR_GEN_DEF(arm_init) + * LOAD_ADDR_GEN_DEF(arm_init_cpu) + */ + +#if SLIDABLE +/* Definitions for a position dependent kernel using non-lazy pointers. + */ + +/* TODO: Make this work with thumb .s files. */ +#define PC_INC 0x8 + +/* We need wrapper macros in order to ensure that __LINE__ is expanded. + * + * There is some small potential for duplicate labels here, but because + * we do not export the generated labels, it should not be an issue. + */ + +#define GLUE_LABEL_GUTS(label, tag) L_##label##_##tag##_glue +#define GLUE_LABEL(label, tag) GLUE_LABEL_GUTS(label, tag) + +#define LOAD_ADDR(reg, label) \ + movw reg, :lower16:(label##$non_lazy_ptr - (GLUE_LABEL(label, __LINE__) + PC_INC)) ; \ + movt reg, :upper16:(label##$non_lazy_ptr - (GLUE_LABEL(label, __LINE__) + PC_INC)) ; \ +GLUE_LABEL(label, __LINE__): ; \ + ldr reg, [pc, reg] + +/* Designed with the understanding that directly branching to thumb code + * is unreliable; this should allow for dealing with __thumb__ in + * assembly; the non-thumb variant still needs to provide the glue label + * to avoid failing to build on undefined symbols. + * + * TODO: Make this actually use a scratch register; this macro is convenient + * for translating (ldr pc, [?]) to a slidable format without the risk of + * clobbering registers, but it is also wasteful. + */ +#if defined(__thumb__) +#define LOAD_ADDR_PC(label) \ + stmfd sp!, { r0 } ; \ + stmfd sp!, { r0 } ; \ + LOAD_ADDR(r0, label) ; \ + str r0, [sp, #4] ; \ + ldmfd sp!, { r0 } ; \ + ldmfd sp!, { pc } +#else +#define LOAD_ADDR_PC(label) \ + b EXT(label) +#endif + +#define LOAD_ADDR_GEN_DEF(label) \ + .section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers ; \ + .align 2 ; \ +label##$non_lazy_ptr: ; \ + .indirect_symbol EXT(label) ; \ + .long 0 + +#else /* !SLIDABLE */ + +/* Definitions for a position dependent kernel */ +#define LOAD_ADDR(reg, label) \ + ldr reg, L_##label + +#if defined(__thumb__) +#define LOAD_ADDR_PC(label) \ + ldr pc, L_##label +#else +#define LOAD_ADDR_PC(label) \ + b EXT(label) +#endif + +#define LOAD_ADDR_GEN_DEF(label) \ + .text ; \ + .align 2 ; \ +L_##label: ; \ + .long EXT(label) + +#endif /* SLIDABLE */ + +/* The linker can deal with branching from ARM to thumb in unconditional + * branches, but not in conditional branches. To support this in our + * assembly (which allows us to build xnu without -mno-thumb), use the + * following macros for branching conditionally to external symbols. + * These macros are used just like the corresponding conditional branch + * instructions. + */ + +#define SHIM_LABEL_GUTS(line_num) L_cond_extern_##line_num##_shim +#define SHIM_LABEL(line_num) SHIM_LABEL_GUTS(line_num) + +#define COND_EXTERN_BEQ(label) \ + bne SHIM_LABEL(__LINE__) ; \ + b EXT(label) ; \ +SHIM_LABEL(__LINE__): + +#define COND_EXTERN_BLNE(label) \ + beq SHIM_LABEL(__LINE__) ; \ + bl EXT(label) ; \ +SHIM_LABEL(__LINE__): + +#define COND_EXTERN_BLGT(label) \ + ble SHIM_LABEL(__LINE__) ; \ + bl EXT(label) ; \ +SHIM_LABEL(__LINE__): + +#endif /* ASSEMBLER */ + +#endif /* _ARM_ASM_H_ */