1/* 2 * Copyright (c) 2007 Apple Inc. All rights reserved. 3 */ 4/* 5 * @OSF_COPYRIGHT@ 6 */ 7/* 8 * Mach Operating System 9 * Copyright (c) 1991,1990,1989 Carnegie Mellon University 10 * All Rights Reserved. 11 * 12 * Permission to use, copy, modify and distribute this software and its 13 * documentation is hereby granted, provided that both the copyright 14 * notice and this permission notice appear in all copies of the 15 * software, derivative works or modified versions, and any portions 16 * thereof, and that both notices appear in supporting documentation. 17 * 18 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 19 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 20 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 21 * 22 * Carnegie Mellon requests users of this software to return to 23 * 24 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 25 * School of Computer Science 26 * Carnegie Mellon University 27 * Pittsburgh PA 15213-3890 28 * 29 * any improvements or extensions that they make and grant Carnegie Mellon 30 * the rights to redistribute these changes. 31 */ 32 33#ifndef _ARM_ASM_H_ 34#define _ARM_ASM_H_ 35 36#include <arm/arch.h> 37 38#ifdef _KERNEL 39#include <gprof.h> 40#endif /* _KERNEL */ 41 42#if defined(MACH_KERNEL) || defined(_KERNEL) 43#include <gprof.h> 44#endif /* MACH_KERNEL || _KERNEL */ 45 46 47#define FRAME pushl %ebp; movl %esp, %ebp 48#define EMARF leave 49 50 51/* There is another definition of ALIGN for .c sources */ 52#ifdef ASSEMBLER 53#define ALIGN 2 54#endif /* ASSEMBLER */ 55 56#ifndef FALIGN 57#define FALIGN ALIGN 58#endif 59 60#define LB(x,n) n 61#if __STDC__ 62#ifndef __NO_UNDERSCORES__ 63#define LCL(x) L ## x 64#define EXT(x) _ ## x 65#define LEXT(x) _ ## x ## : 66#else 67#define LCL(x) .L ## x 68#define EXT(x) x 69#define LEXT(x) x ## : 70#endif 71#define LBc(x,n) n ## : 72#define LBb(x,n) n ## b 73#define LBf(x,n) n ## f 74#else /* __STDC__ */ 75#ifndef __NO_UNDERSCORES__ 76#define LCL(x) L/**/x 77#define EXT(x) _/**/x 78#define LEXT(x) _/**/x/**/: 79#else /* __NO_UNDERSCORES__ */ 80#define LCL(x) .L/**/x 81#define EXT(x) x 82#define LEXT(x) x/**/: 83#endif /* __NO_UNDERSCORES__ */ 84#define LBc(x,n) n/**/: 85#define LBb(x,n) n/**/b 86#define LBf(x,n) n/**/f 87#endif /* __STDC__ */ 88 89#define String .asciz 90#define Value .word 91#define Times(a,b) (a*b) 92#define Divide(a,b) (a/b) 93 94#if 0 /* TOTOJK */ 95#ifdef __ELF__ 96#define ELF_FUNC(x) .type x,@function 97#define ELF_DATA(x) .type x,@object 98#define ELF_SIZE(x,s) .size x,s 99#else 100#define ELF_FUNC(x) 101#define ELF_DATA(x) 102#define ELF_SIZE(x,s) 103#endif 104#else 105#define ELF_FUNC(x) 106#define ELF_DATA(x) 107#define ELF_SIZE(x,s) 108#endif /* TODOJK */ 109 110#define Entry(x) .globl EXT(x); ELF_FUNC(EXT(x)); .align FALIGN; LEXT(x) 111#define ENTRY(x) Entry(x) MCOUNT 112#define ENTRY2(x,y) .globl EXT(x); .globl EXT(y); \ 113 ELF_FUNC(EXT(x)); ELF_FUNC(EXT(y)); \ 114 .align FALIGN; LEXT(x); LEXT(y) \ 115 MCOUNT 116#if __STDC__ 117#define ASENTRY(x) .globl x; .align FALIGN; x ## : ELF_FUNC(x) MCOUNT 118#else 119#define ASENTRY(x) .globl x; .align FALIGN; x: ELF_FUNC(x) MCOUNT 120#endif /* __STDC__ */ 121 122#define DATA(x) .globl EXT(x); ELF_DATA(EXT(x)); .align ALIGN; LEXT(x) 123 124#define End(x) ELF_SIZE(x,.-x) 125#define END(x) End(EXT(x)) 126#define ENDDATA(x) END(x) 127#define Enddata(x) End(x) 128 129#ifdef ASSEMBLER 130 131#define MCOUNT 132 133#else /* NOT ASSEMBLER */ 134 135/* These defines are here for .c files that wish to reference global symbols 136 * within __asm__ statements. 137 */ 138#ifndef __NO_UNDERSCORES__ 139#define CC_SYM_PREFIX "_" 140#else 141#define CC_SYM_PREFIX "" 142#endif /* __NO_UNDERSCORES__ */ 143#endif /* ASSEMBLER */ 144 145#ifdef ASSEMBLER 146 147#if defined (_ARM_ARCH_4T) 148# define RET bx lr 149# define RETeq bxeq lr 150# define RETne bxne lr 151# ifdef __STDC__ 152# define RETc(c) bx##c lr 153# else 154# define RETc(c) bx/**/c lr 155# endif 156#else 157# define RET mov pc, lr 158# define RETeq moveq pc, lr 159# define RETne movne pc, lr 160# ifdef __STDC__ 161# define RETc(c) mov##c pc, lr 162# else 163# define RETc(c) mov/**/c pc, lr 164# endif 165#endif 166 167#if defined (__thumb__) 168/* Provide a PI mechanism for thumb branching. */ 169# define BRANCH_EXTERN(x) ldr pc, [pc, #-4] ; \ 170 .long EXT(x) 171#else 172# define BRANCH_EXTERN(x) b EXT(x) 173#endif 174 175/* 176 * arg0: Register for thread pointer 177 */ 178.macro READ_THREAD 179 mrc p15, 0, $0, c13, c0, 4 /* Read TPIDRPRW */ 180.endmacro 181 182 183/* Macros for loading up addresses that are external to the .s file. 184 * LOAD_ADDR: loads the address for (label) into (reg). Not safe for 185 * loading to the PC. 186 * LOAD_ADDR_PC: Variant for loading to the PC; load the address of (label) 187 * into the pc. 188 * LOAD_ADDR_GEN_DEF: The general definition needed to support loading 189 * a label address. 190 * 191 * Usage: For any label accessed, we require one (and only one) instance 192 * of LOAD_ADDR_GEN_DEF(label). 193 * 194 * Example: 195 * LOAD_ADDR(r0, arm_init) 196 * LOAD_ADDR(lr, arm_init_cpu) 197 * LOAD_ADDR_PC(arm_init) 198 * ... 199 * 200 * LOAD_ADDR_GEN_DEF(arm_init) 201 * LOAD_ADDR_GEN_DEF(arm_init_cpu) 202 */ 203 204#ifdef _ARM_ARCH_7 205#define SLIDABLE 1 206#endif 207 208#if SLIDABLE 209/* Definitions for a position dependent kernel using non-lazy pointers. 210 */ 211 212/* TODO: Make this work with thumb .s files. */ 213#define PC_INC 0x8 214 215/* We need wrapper macros in order to ensure that __LINE__ is expanded. 216 * 217 * There is some small potential for duplicate labels here, but because 218 * we do not export the generated labels, it should not be an issue. 219 */ 220 221#define GLUE_LABEL_GUTS(label, tag) L_##label##_##tag##_glue 222#define GLUE_LABEL(label, tag) GLUE_LABEL_GUTS(label, tag) 223 224#define LOAD_ADDR(reg, label) \ 225 movw reg, :lower16:(label##$non_lazy_ptr - (GLUE_LABEL(label, __LINE__) + PC_INC)) ; \ 226 movt reg, :upper16:(label##$non_lazy_ptr - (GLUE_LABEL(label, __LINE__) + PC_INC)) ; \ 227GLUE_LABEL(label, __LINE__): ; \ 228 ldr reg, [pc, reg] 229 230/* Designed with the understanding that directly branching to thumb code 231 * is unreliable; this should allow for dealing with __thumb__ in 232 * assembly; the non-thumb variant still needs to provide the glue label 233 * to avoid failing to build on undefined symbols. 234 * 235 * TODO: Make this actually use a scratch register; this macro is convenient 236 * for translating (ldr pc, [?]) to a slidable format without the risk of 237 * clobbering registers, but it is also wasteful. 238 */ 239#if defined(__thumb__) 240#define LOAD_ADDR_PC(label) \ 241 stmfd sp!, { r0 } ; \ 242 stmfd sp!, { r0 } ; \ 243 LOAD_ADDR(r0, label) ; \ 244 str r0, [sp, #4] ; \ 245 ldmfd sp!, { r0 } ; \ 246 ldmfd sp!, { pc } 247#else 248#define LOAD_ADDR_PC(label) \ 249 b EXT(label) 250#endif 251 252#define LOAD_ADDR_GEN_DEF(label) \ 253 .section __DATA,__nl_symbol_ptr,non_lazy_symbol_pointers ; \ 254 .align 2 ; \ 255label##$non_lazy_ptr: ; \ 256 .indirect_symbol EXT(label) ; \ 257 .long 0 258 259#else /* !SLIDABLE */ 260 261/* Definitions for a position dependent kernel */ 262#define LOAD_ADDR(reg, label) \ 263 ldr reg, L_##label 264 265#if defined(__thumb__) 266#define LOAD_ADDR_PC(label) \ 267 ldr pc, L_##label 268#else 269#define LOAD_ADDR_PC(label) \ 270 b EXT(label) 271#endif 272 273#define LOAD_ADDR_GEN_DEF(label) \ 274 .text ; \ 275 .align 2 ; \ 276L_##label: ; \ 277 .long EXT(label) 278 279#endif /* SLIDABLE */ 280 281/* The linker can deal with branching from ARM to thumb in unconditional 282 * branches, but not in conditional branches. To support this in our 283 * assembly (which allows us to build xnu without -mno-thumb), use the 284 * following macros for branching conditionally to external symbols. 285 * These macros are used just like the corresponding conditional branch 286 * instructions. 287 */ 288 289#define SHIM_LABEL_GUTS(line_num) L_cond_extern_##line_num##_shim 290#define SHIM_LABEL(line_num) SHIM_LABEL_GUTS(line_num) 291 292#define COND_EXTERN_BEQ(label) \ 293 bne SHIM_LABEL(__LINE__) ; \ 294 b EXT(label) ; \ 295SHIM_LABEL(__LINE__): 296 297#define COND_EXTERN_BLNE(label) \ 298 beq SHIM_LABEL(__LINE__) ; \ 299 bl EXT(label) ; \ 300SHIM_LABEL(__LINE__): 301 302#define COND_EXTERN_BLGT(label) \ 303 ble SHIM_LABEL(__LINE__) ; \ 304 bl EXT(label) ; \ 305SHIM_LABEL(__LINE__): 306 307#endif /* ASSEMBLER */ 308 309#endif /* _ARM_ASM_H_ */ 310